diff --git a/docs/contributing/commit-signing.mdx b/docs/contributing/commit-signing.mdx
index 1ca6e98ec..9457c2f86 100644
--- a/docs/contributing/commit-signing.mdx
+++ b/docs/contributing/commit-signing.mdx
@@ -2,337 +2,379 @@
sidebar_position: 3
---
-import Tabs from "@theme/Tabs";
-import TabItem from "@theme/TabItem";
-
# Commit signing
-It's possible to configure git with any name and email, enabling bad actors to spoof commits and
-impersonate whomever they want. GitHub supports several ways to digitally sign git commits,
-verifying that they came from someone with access to a previously configured private key.
-
-For example, on 3 August 2022, Stephen Lacy
-[shared on Twitter](https://twitter.com/stephenlacy/status/1554697080718823424) how he uncovered a
-massive malware attack on GitHub by noticing unverified commits (i.e. commits that were not
-digitally signed).
-
-To protect against commit spoofing, all Bitwarden contributors are encouraged to digitally
-sign their commits.
+Git allows anyone to configure any name and email on their commits, which means bad actors can spoof
+commits and impersonate other contributors. Digitally signing commits proves they came from someone
+with access to a specific private key.
-## Setting up commit signing
+To protect against commit spoofing, **all Bitwarden contributors are encouraged to digitally sign
+their commits**.
-GitHub supports [commit signing][github-verification] with SSH, GPG, and S/MIME.
+## Choosing a signing method
-:::tip
+GitHub supports [commit signing][github-verification] with SSH, GPG, and S/MIME. This guide covers
+SSH, which GitHub recommends as [the simplest approach for individual users][github-verification].
-If you're unsure what to use, we recommend you create a commit signing key using SSH per
-latest security best practices (see the
-[PGP problem](https://www.latacora.com/blog/2019/07/16/the-pgp-problem/) for more details). For
-maximum security, consider using a [hardware-backed SSH key](#hardware-backed-ssh-key-configuration)
-(YubiKey or other FIDO2 device) as your signing key.
-
-:::
+There are three ways to set up SSH commit signing, in order of recommendation:
-### Standard SSH key configuration
+1. **[Hardware-backed SSH key](#hardware-backed-ssh-key)**: private key lives on a FIDO2 security
+ key (e.g., YubiKey 5+). Each commit requires a PIN and a physical touch. This is the most secure
+ option.
+2. **[Standard SSH key](#standard-ssh-key)**: private key lives on disk, protected by a passphrase.
+ Simpler to set up, but the key material is extractable.
+3. **[Bitwarden SSH agent](#bitwarden-ssh-agent)**: import an SSH key into Bitwarden Desktop and use
+ the built-in SSH agent. Keys are available while your vault is unlocked.
-1. Ensure you have globally configured your git email address:
+Pick one path below, then continue to [Add the key to GitHub](#add-the-key-to-github).
- ```bash
- git config --global user.email "you@example.com"
- ```
+## Hardware-backed SSH key
-2. Generate an SSH key for commit signing:
+Hardware-backed keys using FIDO2 security keys provide the strongest protection. Private keys are
+generated on and never leave the hardware, and every signing operation requires physical interaction
+with the device.
- ```bash
- # path to save your private signing key
- KEY_FILE=~/.ssh/bw-signing
- ssh-keygen -f $KEY_FILE -C "$(git config --global --get user.email)" -t ed25519
- ```
+### Prerequisites
- :::tip
+- macOS (Apple Silicon) with Homebrew
+- A FIDO2-compatible security key (must support ed25519-sk; older U2F-only keys only support
+ ecdsa-sk)
- Remember to protect the key with a [strong passphrase or password][password-generation].
- Alternatively set up
- [a hardware key as your signing key](#hardware-backed-ssh-key-configuration).
+### Install dependencies
- :::
+The system OpenSSH (8.2+) technically supports ed25519-sk, but lacks the FIDO middleware needed to
+talk to hardware keys. Install Homebrew's OpenSSH, which has FIDO support compiled in, along with
+`libfido2`:
-3. Configure git to sign using SSH.
+```bash
+brew install openssh libfido2
+```
- ```bash
- git config --global gpg.format ssh
- git config --global user.signingkey "${KEY_FILE}.pub"
- ```
+Ensure Homebrew's binaries take precedence. Add to `~/.zshrc` if not already present:
-4. Follow the
- [SSH GitHub documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification#ssh-commit-signature-verification)
- to configure commit signing
+```bash
+export PATH="/opt/homebrew/bin:$PATH"
+```
-5. Configure your preferred git tool below ([CLI](#commit-signing-with-git-cli),
- [VS Code](#commit-signing-with-visual-studio-code),
- [SourceTree](#commit-signing-with-sourcetree))
+Restart your shell (open a new terminal tab, or run `source ~/.zshrc`) and verify the correct binary
+is active:
-6. Push a test commit to GitHub and ensure that the "Verified" badge appears next to the commit
- description:
+```bash
+which ssh-keygen # should print /opt/homebrew/bin/ssh-keygen
+```
- 
+If it points to `/usr/bin/`, your PATH isn't set correctly. Fix that before continuing; the system
+binary will silently fail at later steps.
-7. (Optional) See
- [Store your passphrase in your OS keychain](#store-your-passphrase-in-your-os-keychain) below to
- avoid being prompted for your SSH key passphrase every time you sign a commit.
+### Set a FIDO2 PIN
-### Use Bitwarden SSH agent
+If you haven't already, set a PIN on your security key:
-Import your SSH key into Bitwarden desktop. Then, follow our
-[guide](https://bitwarden.com/help/ssh-agent/#configure-git-for-ssh-signing) on configuring the
-desktop app for SSH authentication and Git commit signing. This ensures your SSH keys are available
-while your vault is unlocked.
+```bash
+brew install ykman
+ykman fido access change-pin
+```
-### Store your passphrase in your OS keychain
+### Generate the key
-#### macOS
+Ensure your git email is configured, then plug in your security key and generate the key:
-On macOS, you can use the built-in Keychain to store your SSH key passphrase so you don't have to
-enter it every time you sign a commit.
+```bash
+git config --global user.email "you@example.com"
+ssh-keygen -t ed25519-sk -O verify-required -C "$(git config --global --get user.email)"
+```
-1. Add your SSH key to the ssh-agent and store your passphrase in the Keychain:
+`-O verify-required` ensures every SSH operation requires both a PIN and a physical touch. You'll be
+prompted to touch the key during generation. The passphrase prompt is optional, since the hardware
+key itself is the primary security factor.
- ```bash
- ssh-add --apple-use-keychain ~/.ssh/bw-signing
- ssh-add -l # verify the key was added
- ```
+To create a **resident key** (stored on the hardware, portable across machines via `ssh-keygen -K`),
+add `-O resident`:
-2. The above command will need to be run each time you restart your computer. If you would like to
- automate this process, then you can leverage
- [LaunchAgents](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html#//apple_ref/doc/uid/10000172i-SW7-BCIEDDBJ)
- to run the command on startup.
+```bash
+ssh-keygen -t ed25519-sk -O resident -O verify-required -C "$(git config --global --get user.email)"
+```
- a. Ensure the LaunchAgents directory exists:
+Confirm the key was created:
- ```bash
- mkdir -p ~/Library/LaunchAgents
- ```
+```bash
+ls -la ~/.ssh/id_ed25519_sk*
+```
- b. Create a new plist file for the LaunchAgent:
+You should see both `id_ed25519_sk` (private key handle) and `id_ed25519_sk.pub` (public key).
- ```bash
- USER_NAME=$(whoami)
+### Configure SSH
- cat > ~/Library/LaunchAgents/com.ssh-add-bw-signing.plist <
+```
+IgnoreUnknown UseKeychain,AddKeysToAgent
-
+Host github.com
+ IdentityFile ~/.ssh/id_ed25519_sk
+ IdentityAgent none
+```
-
-
- Label
- com.ssh-add-bw-signing
- ProgramArguments
-
- /usr/bin/ssh-add
- --apple-use-keychain
- /Users/${USER_NAME}/.ssh/bw-signing
-
- RunAtLoad
-
-
-
- PLIST
- ```
+`IgnoreUnknown` lets this config work with both the system SSH (which supports Apple-specific
+options like `UseKeychain`) and Homebrew's SSH (which doesn't). `IdentityAgent none` bypasses the
+macOS SSH agent, which can cache the FIDO key handle and then fail on subsequent auth attempts.
+Disabling it forces SSH to talk to the YubiKey directly every time, which is the correct behavior
+for `verify-required` keys.
+### Configure Git
- c. Validate that your plist is valid:
+```bash
+git config --global gpg.format ssh
+git config --global user.signingkey ~/.ssh/id_ed25519_sk.pub
+git config --global commit.gpgSign true
+git config --global tag.gpgSign true
+```
- ```bash
- plutil -lint ~/Library/LaunchAgents/com.ssh-add-bw-signing.plist
- # you should see: "OK"
- ```
+Set up an allowed signers file for local signature verification. This snippet is idempotent, so it's
+safe to run more than once:
- d. Configure `launchctl` to enable the new LaunchAgent for your next restart:
+```bash
+SIGNER_ENTRY="$(git config user.email) $(cat ~/.ssh/id_ed25519_sk.pub)"
+touch ~/.ssh/allowed_signers
+grep -qF "$SIGNER_ENTRY" ~/.ssh/allowed_signers || echo "$SIGNER_ENTRY" >> ~/.ssh/allowed_signers
+git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
+```
- ```bash
- launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.ssh-add-bw-signing.plist
- launchctl enable gui/$(id -u)/com.ssh-add-bw-signing
- ```
+#### Fix the PIN prompt for commit signing
- e. You can kickstart the LaunchAgent and confirm it will work by running (only works if you haven't loaded your key yet):
+Git calls `ssh-keygen -Y sign` internally without connecting it to your terminal, so the PIN prompt
+gets swallowed and the commit appears to hang. The fix is a wrapper script that redirects
+stdin/stderr to `/dev/tty`:
- ```bash
- launchctl kickstart -k gui/$(id -u)/com.ssh-add-bw-signing
- ssh-add -l # verify the key was added
- ```
+```bash
+cat > ~/.ssh/ssh-keygen-sign-wrapper <<'EOF'
+#!/bin/bash
+exec /opt/homebrew/bin/ssh-keygen "$@" < /dev/tty 2> /dev/tty
+EOF
+chmod +x ~/.ssh/ssh-keygen-sign-wrapper
- f. Restart your computer to verify that the LaunchAgent works as expected. After restarting, run `ssh-add -l` to verify that your key was added to the ssh-agent
- automatically.
+git config --global gpg.ssh.program ~/.ssh/ssh-keygen-sign-wrapper
+```
-### Hardware-backed SSH key configuration
+Now continue to [Add the key to GitHub](#add-the-key-to-github).
-For contributors who want maximum security, hardware-backed SSH keys using FIDO2/U2F security keys
-(like YubiKeys) provide superior protection by storing private keys on hardware that cannot be
-extracted or copied.
+### Fallback strategy
-#### Benefits of hardware-backed keys
+:::caution
-- **Physical presence required**: Each signing operation requires touching the hardware key
-- **Locked private keys**: Private keys are generated on and never leave the hardware
-- **Tamper-resistant**: Hardware provides protection against physical and software attacks
-- **Multi-factor authentication**: Combines something you have (the key) with something you know
- (PIN)
+Make sure you have a recovery plan in case you lose your hardware key:
-#### Setting up sk-ed25519 keys
+- Register multiple hardware keys with GitHub
+- Keep a traditional SSH key as a secure backup for emergencies
+- If using resident keys, back up the key handle with `ssh-keygen -K` on a second machine
-:::note macOS Users
+:::
-On macOS, you'll need to install OpenSSH via Homebrew as the system's built-in OpenSSH lacks proper
-FIDO2 support:
+## Standard SSH key
-```bash
-brew install openssh
-```
+A standard ed25519 SSH key stored on disk, protected by a passphrase.
-After installation, restart your terminal to ensure the Homebrew version is used. If it's not then
-fully qualify the path to the homebrew version of ssh-keygen in the example, like
-`/opt/homebrew/bin/ssh-keygen [everything else]`.
+1. Ensure your git email is configured:
-:::
+ ```bash
+ git config --global user.email "you@example.com"
+ ```
-1. Generate an sk-ed25519 key for commit signing:
+2. Generate an SSH key for commit signing:
```bash
- # Generate hardware-backed signing key
- ssh-keygen -t ed25519-sk -f ~/.ssh/bw-signing-sk -C "$(git config --global --get user.email)"
+ ssh-keygen -t ed25519 -f ~/.ssh/bw-signing -C "$(git config --global --get user.email)"
```
- :::note
+ :::tip
- You'll need to touch your security key when prompted during key generation and each time you sign
- a commit.
+ Protect the key with a [strong passphrase][password-generation]. For stronger protection,
+ consider a [hardware-backed key](#hardware-backed-ssh-key) instead.
:::
-2. Configure git to use your hardware-backed key:
+3. Configure Git to sign using SSH:
```bash
git config --global gpg.format ssh
- git config --global user.signingkey ~/.ssh/bw-signing-sk.pub
+ git config --global user.signingkey ~/.ssh/bw-signing.pub
git config --global commit.gpgSign true
git config --global tag.gpgSign true
```
-3. Add the public key to your GitHub account following the [GitHub
- documentation][github-verification]
+4. (Optional) Store your passphrase in the macOS Keychain so you don't have to enter it on every
+ commit. See
+ [Store your passphrase in the macOS Keychain](#store-your-passphrase-in-the-macos-keychain).
-#### Hardware key requirements
+Now continue to [Add the key to GitHub](#add-the-key-to-github).
-- **FIDO2/U2F compatible security key** (YubiKey 5 series, SoloKeys, etc.)
-- **OpenSSH 8.2+** with FIDO2 support (on macOS, install via Homebrew: `brew install openssh`)
-- **Physical access** to the security key for each signing operation
+## Bitwarden SSH agent
-#### Fallback strategy
+Import your SSH key into Bitwarden Desktop, then follow the
+[Bitwarden SSH agent guide](https://bitwarden.com/help/ssh-agent/#configure-git-for-ssh-signing) to
+configure the desktop app for SSH authentication and Git commit signing. Your SSH keys will be
+available while your vault is unlocked.
-:::caution
+After completing that guide, continue to [Add the key to GitHub](#add-the-key-to-github).
-When going the hardware key route it is important to make sure you have the infrastructure set up to
-recover from the loss of a hardware key. At least one backup plan should be set up. Some ideas:
+## Add the key to GitHub
-- Create and configure multiple hardware keys
-- Generate both a hardware-backed key and a traditional SSH key:
- - Use the hardware-backed key for day-to-day development
- - Keep a traditional SSH key as a secure backup for emergency situations
+Copy your public key (adjust the path if you used a custom filename):
-:::
+```bash
+# Hardware-backed key
+pbcopy < ~/.ssh/id_ed25519_sk.pub
-### Commit signing with git CLI
+# Standard key
+pbcopy < ~/.ssh/bw-signing.pub
+```
-- After configuring commit signing, you can sign a commit by using the `-S` flag:
+In **GitHub → Settings → SSH and GPG keys → New SSH key**, add the same public key twice: once as an
+**Authentication Key** and once as a **Signing Key**.
- ```bash
- git commit -S
- ```
+### Test authentication
-- To avoid using the `-S` flag every time, you can sign all commits and tags by default:
+```bash
+ssh -T git@github.com
+```
- ```bash
- git config --global commit.gpgSign true
- git config --global tag.gpgSign true
- ```
+You should see:
-### Commit signing with Visual Studio Code
+```
+Hi ! You've successfully authenticated, but GitHub does not provide shell access.
+```
-1. Open **Preferences** → **Settings**
-2. Search for **“commit signing”**
-3. Enable commit signing
+For hardware keys, you'll be prompted for your FIDO2 PIN and a physical touch. If this doesn't work,
+stop here and troubleshoot before continuing.
- 
+### Verify commit signing
-
- macOS: GPG Key Passphrase Prompt Issue
+```bash
+git commit --allow-empty -m "test signed commit"
+git log --show-signature -1
+```
-Some macOS users have had issues with VS Code and the gpg-agent not prompting for the GPG Key
-Passphrase in order to sign commits when using the VS Code git GUI. This is illustrated by VS Code
-displaying an error popup message: `Git: gpg failed to sign the data`.
+`git log` should show "Good signature." Push the commit to GitHub and confirm the **Verified** badge
+appears next to the commit.
-A [workaround](https://github.com/microsoft/vscode/issues/43809#issuecomment-828773909) for this
-issue is to configure your gpg-agent to use
-[pinentry](https://www.gnupg.org/related_software/pinentry/index.html) for macOS in order to force a
-secure prompt. Run the following in a terminal of your choice:
+## Git client setup
-1. Install pinentry-mac:
+### VS Code
- ```bash
- brew install pinentry-mac
- ```
+1. Open **Preferences → Settings**
+2. Search for **"commit signing"**
+3. Enable **Git: Enable Commit Signing**
-2. Configure gpg-agent to use pinentry-mac:
+### SourceTree
+
+Refer to Atlassian's guide:
+[Setup GPG to sign commits within SourceTree](https://confluence.atlassian.com/sourcetreekb/setup-gpg-to-sign-commits-within-sourcetree-765397791.html).
+
+## What to expect day-to-day
+
+**Hardware keys:** Every `git push` and `git commit` will prompt for your FIDO2 PIN and a physical
+touch. This is by design; no one can push or sign commits with your identity without physical access
+to your security key and knowledge of the PIN. The prompts become second nature quickly, but expect
+each operation to take a couple of extra seconds.
+
+**Standard SSH keys:** If you stored your passphrase in the macOS Keychain, commits and pushes will
+work without any prompts. Otherwise, you'll be prompted for your passphrase when the key is first
+used in a session.
+
+## Store your passphrase in the macOS Keychain
+
+This section applies to **standard SSH keys only** (not hardware-backed keys, which require a touch
+on every operation by design).
+
+Add your SSH key to the ssh-agent and store your passphrase in the Keychain:
+
+```bash
+ssh-add --apple-use-keychain ~/.ssh/bw-signing
+ssh-add -l # verify the key was added
+```
+
+This needs to be re-run after every restart. To automate it, create a LaunchAgent:
+
+1. Create the LaunchAgents directory if it doesn't exist:
```bash
- echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf
+ mkdir -p ~/Library/LaunchAgents
```
-3. Restart gpg-agent:
+2. Create the plist file:
```bash
- killall gpg-agent
+ USER_NAME=$(whoami)
+
+ cat > ~/Library/LaunchAgents/com.ssh-add-bw-signing.plist <
+
+
+
+ Label
+ com.ssh-add-bw-signing
+ ProgramArguments
+
+ /usr/bin/ssh-add
+ --apple-use-keychain
+ /Users/${USER_NAME}/.ssh/bw-signing
+
+ RunAtLoad
+
+
+
+ PLIST
```
-**Note**: Note: you might have to restart VS Code for this to take effect, but you should now be
-prompted for your GPG Key Passphrase as needed. If this does not solve your issue, please follow the
-[GPG Key Troubleshooting](#gpg-key-troubleshooting) guide below.
+3. Validate, enable, and test:
-
-
-### Commit signing with SourceTree
+ ```bash
+ plutil -lint ~/Library/LaunchAgents/com.ssh-add-bw-signing.plist
-Refer to
-[Setup GPG to sign commits within SourceTree](https://confluence.atlassian.com/sourcetreekb/setup-gpg-to-sign-commits-within-sourcetree-765397791.html).
+ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.ssh-add-bw-signing.plist
+ launchctl enable gui/$(id -u)/com.ssh-add-bw-signing
-## GPG Key Troubleshooting
+ # Kick-start it now (only works if the key isn't loaded yet)
+ launchctl kickstart -k gui/$(id -u)/com.ssh-add-bw-signing
+ ssh-add -l # verify the key was added
+ ```
-If you see the following error:
+4. Restart your computer and run `ssh-add -l` to confirm the key loads automatically.
-```text
-error: gpg failed to sign the data
-```
+## Cleanup
-Make sure you’ve added the following to your shell config:
+Remove any old SSH keys from GitHub that are no longer in use. Compare the SHA256 fingerprints shown
+in GitHub's UI against your local keys:
```bash
-export GPG_TTY=$(tty)
+for f in ~/.ssh/*.pub; do echo "=== $f ==="; ssh-keygen -l -f "$f"; done
```
-- For **zsh**, add it to `~/.zshrc`
-- For **bash**, add it to `~/.bashrc`
+## Troubleshooting
+
+### Hardware key issues
+
+**Commit hangs with no PIN prompt.** Git is using the system `ssh-keygen` instead of Homebrew's. Run
+`which ssh-keygen`; it should print `/opt/homebrew/bin/ssh-keygen`. If not, fix your PATH and
+re-source your shell. Also confirm the wrapper script at `~/.ssh/ssh-keygen-sign-wrapper` exists and
+is executable.
-After updating the file, restart your terminal for the change to take effect.
+**`ssh -T git@github.com` returns "Permission denied."** Check that `~/.ssh/config` has the correct
+`IdentityFile` path. Run `ssh -vT git@github.com` to see which keys SSH is offering; the verbose
+output will show whether your FIDO key is being tried.
-
- More help with this error
+**"Key enrollment failed" or no touch prompt during key generation.** The YubiKey may not be
+recognized. Try unplugging and re-plugging it, then run `ykman fido info` to confirm the FIDO2
+application is accessible. If `ykman` can't see it, try a different USB port or check for
+interfering processes (`gpg-agent`, `yubikey-agent`).
-See this
-[troubleshooting guide](https://gist.github.com/paolocarrasco/18ca8fe6e63490ae1be23e84a7039374).
+**Authentication works but suddenly stops.** The macOS SSH agent may have cached a stale FIDO key
+handle. Confirm `IdentityAgent none` is set in `~/.ssh/config` for the `github.com` host. If the
+problem persists, clear the agent with `ssh-add -D` and retry.
-
+**YubiKey PIN locked out.** After 8 consecutive wrong PIN attempts, the FIDO2 PIN locks. Recovery
+requires a full FIDO reset (`ykman fido reset`), which wipes all resident credentials on the key.
+You'll need to generate a new key pair and re-register it on GitHub.
[password-generation]: https://bitwarden.com/help/generator/#password-types
[github-verification]: