From 26c1197bf4384e948456e794508663340848457e Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 15 Jan 2026 14:30:12 +0100 Subject: [PATCH 01/11] Add section about memory hardening --- docs/architecture/security/memory-hardening.mdx | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/architecture/security/memory-hardening.mdx diff --git a/docs/architecture/security/memory-hardening.mdx b/docs/architecture/security/memory-hardening.mdx new file mode 100644 index 000000000..e69de29bb From bef2e9a1c4dbd89f55bfdc4d38b5dbacc0ca79b0 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 15 Jan 2026 14:30:35 +0100 Subject: [PATCH 02/11] Format --- .../security/memory-hardening.mdx | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/architecture/security/memory-hardening.mdx b/docs/architecture/security/memory-hardening.mdx index e69de29bb..747803591 100644 --- a/docs/architecture/security/memory-hardening.mdx +++ b/docs/architecture/security/memory-hardening.mdx @@ -0,0 +1,40 @@ +# Memory Hardening + +While protecting against user-space memory attacks in the general case is not within the threat +model for Bitwarden applications, the lock state must be protected, and it should not be possible to +unlock a locked vault. Because of this, passwords or keys cannot be left behind in memory an +accessible state. Besides this requirement, some features such as SSH agent require process +hardening where possible, required by the specification of the protocol. + +## Zeroizing and Process Reload + +To clear secrets on locking, Bitwarden clients use two techniques, zeroizing and process reload. For +any memory that lives in Rust, memory is overwritten with zeroes, as soon as it becomes unused / +gets dropped. This hardens the SDK, and the Rust desktop module (desktop native) against memory +being left behind. Process reload wipes the entire process - on the web app by reloading the page, +on browser by reloading the extension, and on desktop by force-crashing the renderer process. The +assumption here is that since the process dies, the memory gets wiped too. Javascript does not allow +zeroizing memory consistently, and frequently leaves secrets, or partial secrets behind in memory, +that are not cleared, even after a garbage collection cycle. + +## Process Isolation and Key Protection on Desktop Apps + +Next to process reload and zeorizing, desktop apps can use OS-level protections to harden memory. +There are two mechanisms used here: Process isolation and key protection. Process isolation uses +OS-level features to isolate the process from debugger access. Windows and desktop Linux by default +allow user-space processes to debug other user-space processes and read memory. MacOS does not allow +this by default and requires user consent to allow a process to debug another process. On Linux, +some distros such as Ubuntu use yama.ptrace_scope to limit ptrace access. + +To harden against user-space memory attacks, Bitwarden desktop isolates the main process. On +Windows, DACL is used to restrict access to the process, on Linux PR_SET_DUMPABLE is used to disable +ptrace access and on MacOS the process is hardened using the Hardened Runtime entitlements, and also +by using PT_DENY_ATTACH to prevent debugger attachment. On Linux, a dynamic library that sets +PR_SET_DUMPABLE is also injected into the renderer processes, so that these are isolated too. These +mechanisms apply on all apps except for the Snap desktop app. + +Next to hardening the entire process, operating systems offer mechanisms to protect cryptographic +keys in memory. On Windows, DPAPI can be used to encrypt a key in memory, with a key bound to the +process. On Linux, `memfd_secret` and `keyctl` are available, each of which can be used to store +keys in memory while preventing other processes from reading them. This is used to hold the +biometric unlock key in memory while the desktop app is locked. From 2f30313279b603b629cb564755d671751d89eaa4 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 15 Jan 2026 14:37:49 +0100 Subject: [PATCH 03/11] Fix grammar and spelling --- .../architecture/security/memory-hardening.mdx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/architecture/security/memory-hardening.mdx b/docs/architecture/security/memory-hardening.mdx index 747803591..24a1a873d 100644 --- a/docs/architecture/security/memory-hardening.mdx +++ b/docs/architecture/security/memory-hardening.mdx @@ -2,9 +2,9 @@ While protecting against user-space memory attacks in the general case is not within the threat model for Bitwarden applications, the lock state must be protected, and it should not be possible to -unlock a locked vault. Because of this, passwords or keys cannot be left behind in memory an -accessible state. Besides this requirement, some features such as SSH agent require process -hardening where possible, required by the specification of the protocol. +unlock a locked vault. Because of this, passwords or keys cannot be left behind in memory in an +accessible state. Besides this requirement, some features such as SSH agent need process hardening +where possible, as required by the protocol specification. ## Zeroizing and Process Reload @@ -12,14 +12,14 @@ To clear secrets on locking, Bitwarden clients use two techniques, zeroizing and any memory that lives in Rust, memory is overwritten with zeroes, as soon as it becomes unused / gets dropped. This hardens the SDK, and the Rust desktop module (desktop native) against memory being left behind. Process reload wipes the entire process - on the web app by reloading the page, -on browser by reloading the extension, and on desktop by force-crashing the renderer process. The -assumption here is that since the process dies, the memory gets wiped too. Javascript does not allow -zeroizing memory consistently, and frequently leaves secrets, or partial secrets behind in memory, -that are not cleared, even after a garbage collection cycle. +on browser extensions by reloading the extension, and on desktop by force-crashing the renderer +process. The assumption here is that since the process dies, the memory gets wiped too. Javascript +does not allow zeroizing memory consistently, and frequently leaves secrets, or partial secrets +behind in memory, that are not cleared, even after a garbage collection cycle. ## Process Isolation and Key Protection on Desktop Apps -Next to process reload and zeorizing, desktop apps can use OS-level protections to harden memory. +Next to process reload and zeroizing, desktop apps can use OS-level protections to harden memory. There are two mechanisms used here: Process isolation and key protection. Process isolation uses OS-level features to isolate the process from debugger access. Windows and desktop Linux by default allow user-space processes to debug other user-space processes and read memory. MacOS does not allow @@ -31,7 +31,7 @@ Windows, DACL is used to restrict access to the process, on Linux PR_SET_DUMPABL ptrace access and on MacOS the process is hardened using the Hardened Runtime entitlements, and also by using PT_DENY_ATTACH to prevent debugger attachment. On Linux, a dynamic library that sets PR_SET_DUMPABLE is also injected into the renderer processes, so that these are isolated too. These -mechanisms apply on all apps except for the Snap desktop app. +mechanisms apply to all apps except for the Snap desktop app. Next to hardening the entire process, operating systems offer mechanisms to protect cryptographic keys in memory. On Windows, DPAPI can be used to encrypt a key in memory, with a key bound to the From e4b973ffe68088970633655fabd9fe05c5718eeb Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 15 Jan 2026 14:41:59 +0100 Subject: [PATCH 04/11] Clean up --- custom-words.txt | 1 + .../security/memory-hardening.mdx | 26 +++++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/custom-words.txt b/custom-words.txt index aaf6cc11e..55d88b746 100644 --- a/custom-words.txt +++ b/custom-words.txt @@ -93,6 +93,7 @@ Yellowpages Yubico YubiKey YubiKeys +Zeroizing # Forbidden words !auto-fill diff --git a/docs/architecture/security/memory-hardening.mdx b/docs/architecture/security/memory-hardening.mdx index 24a1a873d..c774e0c1e 100644 --- a/docs/architecture/security/memory-hardening.mdx +++ b/docs/architecture/security/memory-hardening.mdx @@ -1,3 +1,7 @@ +--- +sidebar_position: 10 +--- + # Memory Hardening While protecting against user-space memory attacks in the general case is not within the threat @@ -6,35 +10,35 @@ unlock a locked vault. Because of this, passwords or keys cannot be left behind accessible state. Besides this requirement, some features such as SSH agent need process hardening where possible, as required by the protocol specification. -## Zeroizing and Process Reload +## Zeroizing and process reload To clear secrets on locking, Bitwarden clients use two techniques, zeroizing and process reload. For -any memory that lives in Rust, memory is overwritten with zeroes, as soon as it becomes unused / +any memory that lives in Rust, memory is overwritten with zeroes, as soon as it becomes unused or gets dropped. This hardens the SDK, and the Rust desktop module (desktop native) against memory being left behind. Process reload wipes the entire process - on the web app by reloading the page, on browser extensions by reloading the extension, and on desktop by force-crashing the renderer -process. The assumption here is that since the process dies, the memory gets wiped too. Javascript +process. The assumption here is that since the process dies, the memory gets wiped too. JavaScript does not allow zeroizing memory consistently, and frequently leaves secrets, or partial secrets behind in memory, that are not cleared, even after a garbage collection cycle. -## Process Isolation and Key Protection on Desktop Apps +## Process isolation and key protection on desktop apps Next to process reload and zeroizing, desktop apps can use OS-level protections to harden memory. There are two mechanisms used here: Process isolation and key protection. Process isolation uses OS-level features to isolate the process from debugger access. Windows and desktop Linux by default allow user-space processes to debug other user-space processes and read memory. MacOS does not allow this by default and requires user consent to allow a process to debug another process. On Linux, -some distros such as Ubuntu use yama.ptrace_scope to limit ptrace access. +some distributions such as Ubuntu use yama.ptrace_scope to limit ptrace access. To harden against user-space memory attacks, Bitwarden desktop isolates the main process. On -Windows, DACL is used to restrict access to the process, on Linux PR_SET_DUMPABLE is used to disable -ptrace access and on MacOS the process is hardened using the Hardened Runtime entitlements, and also -by using PT_DENY_ATTACH to prevent debugger attachment. On Linux, a dynamic library that sets -PR_SET_DUMPABLE is also injected into the renderer processes, so that these are isolated too. These -mechanisms apply to all apps except for the Snap desktop app. +Windows, `DACL` is used to restrict access to the process, on Linux `PR_SET_DUMPABLE` is used to +disable ptrace access and on MacOS the process is hardened using the Hardened Runtime entitlements, +and also by using `PT_DENY_ATTACH` to prevent debugger attachment. On Linux, a dynamic library that +sets `PR_SET_DUMPABLE` is also injected into the renderer processes, so that these are isolated too. +These mechanisms apply to all apps except for the Snap desktop app. Next to hardening the entire process, operating systems offer mechanisms to protect cryptographic -keys in memory. On Windows, DPAPI can be used to encrypt a key in memory, with a key bound to the +keys in memory. On Windows, `DPAPI` can be used to encrypt a key in memory, with a key bound to the process. On Linux, `memfd_secret` and `keyctl` are available, each of which can be used to store keys in memory while preventing other processes from reading them. This is used to hold the biometric unlock key in memory while the desktop app is locked. From a8751cbde496790b3a06203354f049562979c198 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 15 Jan 2026 14:42:54 +0100 Subject: [PATCH 05/11] Move to deep-dives --- .../memory-hardening.mdx => deep-dives/memory-hardening.md} | 4 ---- 1 file changed, 4 deletions(-) rename docs/architecture/{security/memory-hardening.mdx => deep-dives/memory-hardening.md} (98%) diff --git a/docs/architecture/security/memory-hardening.mdx b/docs/architecture/deep-dives/memory-hardening.md similarity index 98% rename from docs/architecture/security/memory-hardening.mdx rename to docs/architecture/deep-dives/memory-hardening.md index c774e0c1e..b79e212f9 100644 --- a/docs/architecture/security/memory-hardening.mdx +++ b/docs/architecture/deep-dives/memory-hardening.md @@ -1,7 +1,3 @@ ---- -sidebar_position: 10 ---- - # Memory Hardening While protecting against user-space memory attacks in the general case is not within the threat From f5f4cee997ad820d24f6a8c0aeadfa19c40fd956 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Thu, 15 Jan 2026 14:49:52 +0100 Subject: [PATCH 06/11] Apply feedback --- docs/architecture/deep-dives/memory-hardening.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/architecture/deep-dives/memory-hardening.md b/docs/architecture/deep-dives/memory-hardening.md index b79e212f9..6a62f2448 100644 --- a/docs/architecture/deep-dives/memory-hardening.md +++ b/docs/architecture/deep-dives/memory-hardening.md @@ -14,8 +14,8 @@ gets dropped. This hardens the SDK, and the Rust desktop module (desktop native) being left behind. Process reload wipes the entire process - on the web app by reloading the page, on browser extensions by reloading the extension, and on desktop by force-crashing the renderer process. The assumption here is that since the process dies, the memory gets wiped too. JavaScript -does not allow zeroizing memory consistently, and frequently leaves secrets, or partial secrets -behind in memory, that are not cleared, even after a garbage collection cycle. +does not provide mechanisms for reliably zeroizing memory. Secrets or partial secrets frequently +remain in memory even after garbage collection cycles complete. ## Process isolation and key protection on desktop apps @@ -31,7 +31,8 @@ Windows, `DACL` is used to restrict access to the process, on Linux `PR_SET_DUMP disable ptrace access and on MacOS the process is hardened using the Hardened Runtime entitlements, and also by using `PT_DENY_ATTACH` to prevent debugger attachment. On Linux, a dynamic library that sets `PR_SET_DUMPABLE` is also injected into the renderer processes, so that these are isolated too. -These mechanisms apply to all apps except for the Snap desktop app. +These mechanisms apply to all apps except for the Snap desktop app. Snap does not support +`PR_SET_DUMPABLE` currently and breaks file picker support, due to a bug in the desktop portal. Next to hardening the entire process, operating systems offer mechanisms to protect cryptographic keys in memory. On Windows, `DPAPI` can be used to encrypt a key in memory, with a key bound to the From 5f847b0d97cea7db07697fbfe9b791eaed68eb3c Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Mon, 19 Jan 2026 13:09:25 +0100 Subject: [PATCH 07/11] Add links --- .../deep-dives/memory-hardening.md | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/docs/architecture/deep-dives/memory-hardening.md b/docs/architecture/deep-dives/memory-hardening.md index 6a62f2448..18819955d 100644 --- a/docs/architecture/deep-dives/memory-hardening.md +++ b/docs/architecture/deep-dives/memory-hardening.md @@ -10,12 +10,15 @@ where possible, as required by the protocol specification. To clear secrets on locking, Bitwarden clients use two techniques, zeroizing and process reload. For any memory that lives in Rust, memory is overwritten with zeroes, as soon as it becomes unused or -gets dropped. This hardens the SDK, and the Rust desktop module (desktop native) against memory -being left behind. Process reload wipes the entire process - on the web app by reloading the page, -on browser extensions by reloading the extension, and on desktop by force-crashing the renderer -process. The assumption here is that since the process dies, the memory gets wiped too. JavaScript -does not provide mechanisms for reliably zeroizing memory. Secrets or partial secrets frequently -remain in memory even after garbage collection cycles complete. +gets dropped +[1](https://github.com/bitwarden/sdk-internal/blob/4591981820f12a24e64609fb0a9fd4fdaabbb216/crates/bitwarden-crypto/src/lib.rs#L13). +This hardens the SDK, and the Rust desktop module (desktop native) against memory being left behind. +Process reload wipes the entire process - on the web app by reloading the page, on browser +extensions by reloading the extension, and on desktop by force-crashing the renderer process +[2](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/libs/common/src/key-management/services/default-process-reload.service.ts#L22). +The assumption here is that since the process dies, the memory gets wiped too. JavaScript does not +provide mechanisms for reliably zeroizing memory. Secrets or partial secrets frequently remain in +memory even after garbage collection cycles complete. ## Process isolation and key protection on desktop apps @@ -24,18 +27,33 @@ There are two mechanisms used here: Process isolation and key protection. Proces OS-level features to isolate the process from debugger access. Windows and desktop Linux by default allow user-space processes to debug other user-space processes and read memory. MacOS does not allow this by default and requires user consent to allow a process to debug another process. On Linux, -some distributions such as Ubuntu use yama.ptrace_scope to limit ptrace access. +some distributions such as Ubuntu use +[yama.ptrace_scope](https://www.kernel.org/doc/Documentation/security/Yama.txt) to limit ptrace +access. To harden against user-space memory attacks, Bitwarden desktop isolates the main process. On -Windows, `DACL` is used to restrict access to the process, on Linux `PR_SET_DUMPABLE` is used to +Windows, [`DACL`](https://learn.microsoft.com/en-us/windows/win32/secauthz/dacls-and-aces) is used +to restrict access to the process, on Linux +[`PR_SET_DUMPABLE`](https://man7.org/linux/man-pages/man2/pr_set_dumpable.2const.html) is used to disable ptrace access and on MacOS the process is hardened using the Hardened Runtime entitlements, and also by using `PT_DENY_ATTACH` to prevent debugger attachment. On Linux, a dynamic library that -sets `PR_SET_DUMPABLE` is also injected into the renderer processes, so that these are isolated too. -These mechanisms apply to all apps except for the Snap desktop app. Snap does not support -`PR_SET_DUMPABLE` currently and breaks file picker support, due to a bug in the desktop portal. +sets [`PR_SET_DUMPABLE`](https://man7.org/linux/man-pages/man2/pr_set_dumpable.2const.html) is also +injected into the renderer processes by injecting a shared object into the renderer processes +[3](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/apps/desktop/desktop_native/process_isolation/src/lib.rs), +so that these are isolated too. These mechanisms apply to all apps except for the Snap desktop app. +Snap does not support +[`PR_SET_DUMPABLE`](https://man7.org/linux/man-pages/man2/pr_set_dumpable.2const.html) currently and +breaks file picker support, due to a [bug](https://github.com/flatpak/xdg-desktop-portal/issues/785) +in the desktop portal. Next to hardening the entire process, operating systems offer mechanisms to protect cryptographic -keys in memory. On Windows, `DPAPI` can be used to encrypt a key in memory, with a key bound to the -process. On Linux, `memfd_secret` and `keyctl` are available, each of which can be used to store -keys in memory while preventing other processes from reading them. This is used to hold the -biometric unlock key in memory while the desktop app is locked. +keys in memory. On Windows, +[`DPAPI`](https://learn.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptprotectmemory) can +be used to encrypt a key in memory, with a key bound to the process. On Linux, +[`memfd_secret`](https://man7.org/linux/man-pages/man2/memfd_secret.2.html) and +[`keyctl`](https://man7.org/linux/man-pages/man1/keyctl.1.html) are available, each of which can be +used to store keys in memory while preventing other processes from reading them. This is used to +hold the biometric unlock key in memory while the desktop app is locked. Access to this protected +memory is available via the +[`EncryptedMemoryStore`](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/apps/desktop/desktop_native/core/src/secure_memory/encrypted_memory_store.rs#L16) +abstraction that automatically uses the correct memory protection. From df2450f2f6501a9351ed6f2b524c1ac7f843640a Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Tue, 20 Jan 2026 17:00:16 +0100 Subject: [PATCH 08/11] Fix citation rendering --- docs/architecture/deep-dives/memory-hardening.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/architecture/deep-dives/memory-hardening.md b/docs/architecture/deep-dives/memory-hardening.md index 18819955d..6a65ab741 100644 --- a/docs/architecture/deep-dives/memory-hardening.md +++ b/docs/architecture/deep-dives/memory-hardening.md @@ -11,11 +11,11 @@ where possible, as required by the protocol specification. To clear secrets on locking, Bitwarden clients use two techniques, zeroizing and process reload. For any memory that lives in Rust, memory is overwritten with zeroes, as soon as it becomes unused or gets dropped -[1](https://github.com/bitwarden/sdk-internal/blob/4591981820f12a24e64609fb0a9fd4fdaabbb216/crates/bitwarden-crypto/src/lib.rs#L13). +[[1]](https://github.com/bitwarden/sdk-internal/blob/4591981820f12a24e64609fb0a9fd4fdaabbb216/crates/bitwarden-crypto/src/lib.rs#L13). This hardens the SDK, and the Rust desktop module (desktop native) against memory being left behind. Process reload wipes the entire process - on the web app by reloading the page, on browser extensions by reloading the extension, and on desktop by force-crashing the renderer process -[2](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/libs/common/src/key-management/services/default-process-reload.service.ts#L22). +[[2]](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/libs/common/src/key-management/services/default-process-reload.service.ts#L22). The assumption here is that since the process dies, the memory gets wiped too. JavaScript does not provide mechanisms for reliably zeroizing memory. Secrets or partial secrets frequently remain in memory even after garbage collection cycles complete. @@ -39,7 +39,7 @@ disable ptrace access and on MacOS the process is hardened using the Hardened Ru and also by using `PT_DENY_ATTACH` to prevent debugger attachment. On Linux, a dynamic library that sets [`PR_SET_DUMPABLE`](https://man7.org/linux/man-pages/man2/pr_set_dumpable.2const.html) is also injected into the renderer processes by injecting a shared object into the renderer processes -[3](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/apps/desktop/desktop_native/process_isolation/src/lib.rs), +[`3`](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/apps/desktop/desktop_native/process_isolation/src/lib.rs), so that these are isolated too. These mechanisms apply to all apps except for the Snap desktop app. Snap does not support [`PR_SET_DUMPABLE`](https://man7.org/linux/man-pages/man2/pr_set_dumpable.2const.html) currently and From 3748358c5d3ff04525baebf00e63241ecf18c9f1 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Tue, 20 Jan 2026 19:01:57 +0100 Subject: [PATCH 09/11] Change references to names --- docs/architecture/deep-dives/memory-hardening.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/architecture/deep-dives/memory-hardening.md b/docs/architecture/deep-dives/memory-hardening.md index 6a65ab741..edb9f9209 100644 --- a/docs/architecture/deep-dives/memory-hardening.md +++ b/docs/architecture/deep-dives/memory-hardening.md @@ -10,12 +10,12 @@ where possible, as required by the protocol specification. To clear secrets on locking, Bitwarden clients use two techniques, zeroizing and process reload. For any memory that lives in Rust, memory is overwritten with zeroes, as soon as it becomes unused or -gets dropped -[[1]](https://github.com/bitwarden/sdk-internal/blob/4591981820f12a24e64609fb0a9fd4fdaabbb216/crates/bitwarden-crypto/src/lib.rs#L13). +gets dropped, which is implemented in +[lib.rs](https://github.com/bitwarden/sdk-internal/blob/4591981820f12a24e64609fb0a9fd4fdaabbb216/crates/bitwarden-crypto/src/lib.rs#L13). This hardens the SDK, and the Rust desktop module (desktop native) against memory being left behind. Process reload wipes the entire process - on the web app by reloading the page, on browser -extensions by reloading the extension, and on desktop by force-crashing the renderer process -[[2]](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/libs/common/src/key-management/services/default-process-reload.service.ts#L22). +extensions by reloading the extension, and on desktop by force-crashing the renderer process in the +[process reload service](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/libs/common/src/key-management/services/default-process-reload.service.ts#L22). The assumption here is that since the process dies, the memory gets wiped too. JavaScript does not provide mechanisms for reliably zeroizing memory. Secrets or partial secrets frequently remain in memory even after garbage collection cycles complete. @@ -38,8 +38,8 @@ to restrict access to the process, on Linux disable ptrace access and on MacOS the process is hardened using the Hardened Runtime entitlements, and also by using `PT_DENY_ATTACH` to prevent debugger attachment. On Linux, a dynamic library that sets [`PR_SET_DUMPABLE`](https://man7.org/linux/man-pages/man2/pr_set_dumpable.2const.html) is also -injected into the renderer processes by injecting a shared object into the renderer processes -[`3`](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/apps/desktop/desktop_native/process_isolation/src/lib.rs), +injected into the renderer processes by injecting a shared object into the renderer processes in the +[process isolation library](https://github.com/bitwarden/clients/blob/16e67566436ae7becbea85f900656c437204824b/apps/desktop/desktop_native/process_isolation/src/lib.rs), so that these are isolated too. These mechanisms apply to all apps except for the Snap desktop app. Snap does not support [`PR_SET_DUMPABLE`](https://man7.org/linux/man-pages/man2/pr_set_dumpable.2const.html) currently and From 31cee0f066f1a310111e731e83a05a10da1cd485 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Wed, 21 Jan 2026 11:18:31 +0100 Subject: [PATCH 10/11] Rename MacOS to macOS --- docs/architecture/deep-dives/memory-hardening.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture/deep-dives/memory-hardening.md b/docs/architecture/deep-dives/memory-hardening.md index edb9f9209..04204d365 100644 --- a/docs/architecture/deep-dives/memory-hardening.md +++ b/docs/architecture/deep-dives/memory-hardening.md @@ -35,7 +35,7 @@ To harden against user-space memory attacks, Bitwarden desktop isolates the main Windows, [`DACL`](https://learn.microsoft.com/en-us/windows/win32/secauthz/dacls-and-aces) is used to restrict access to the process, on Linux [`PR_SET_DUMPABLE`](https://man7.org/linux/man-pages/man2/pr_set_dumpable.2const.html) is used to -disable ptrace access and on MacOS the process is hardened using the Hardened Runtime entitlements, +disable ptrace access and on macOS the process is hardened using the Hardened Runtime entitlements, and also by using `PT_DENY_ATTACH` to prevent debugger attachment. On Linux, a dynamic library that sets [`PR_SET_DUMPABLE`](https://man7.org/linux/man-pages/man2/pr_set_dumpable.2const.html) is also injected into the renderer processes by injecting a shared object into the renderer processes in the From 3b0c40fdf233e09fb9e2289a2f208d9511d34457 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Wed, 21 Jan 2026 11:30:09 +0100 Subject: [PATCH 11/11] Rename MacOS to macOS --- docs/architecture/deep-dives/memory-hardening.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture/deep-dives/memory-hardening.md b/docs/architecture/deep-dives/memory-hardening.md index 04204d365..11831dcb4 100644 --- a/docs/architecture/deep-dives/memory-hardening.md +++ b/docs/architecture/deep-dives/memory-hardening.md @@ -25,7 +25,7 @@ memory even after garbage collection cycles complete. Next to process reload and zeroizing, desktop apps can use OS-level protections to harden memory. There are two mechanisms used here: Process isolation and key protection. Process isolation uses OS-level features to isolate the process from debugger access. Windows and desktop Linux by default -allow user-space processes to debug other user-space processes and read memory. MacOS does not allow +allow user-space processes to debug other user-space processes and read memory. macOS does not allow this by default and requires user consent to allow a process to debug another process. On Linux, some distributions such as Ubuntu use [yama.ptrace_scope](https://www.kernel.org/doc/Documentation/security/Yama.txt) to limit ptrace