> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/code-repository/use-harness-code/collaborate-and-develop/signing-commits.md).

# Sign Commits

Use SSH or GPG keys to sign commits and verify authorship in Harness Code Repository.

Commit signing lets you cryptographically prove that you created a commit and that no one has tampered with it. When you sign a commit, Git attaches a digital signature using your private key, and anyone with your public key can verify that the commit is authentic.

Harness Code Repository supports commit signature verification for both SSH and GPG keys. After you add your public key to your Harness user profile, Harness Code verifies signatures on the commits you push and displays a verification badge wherever it shows those commits.

{% hint style="info" %}
Harness recommends SSH signing. Most developers already have an SSH key pair and an SSH agent set up, so signing works with no extra tooling. Choose GPG if your organization requires OpenPGP signatures, or if you need key expiration and revocation, which SSH keys do not support.
{% endhint %}

***

### What you will learn in this topic

By the end of this topic, you will know how to:

* [Confirm that your signature is supported](#supported-signature-formats): Check your signature format and key type against what Harness Code verifies.
* [Set up commit signing](#configure-commit-signing): Add your public key to Harness and configure Git to sign your commits.
* [Read the verification badges](#signature-verification-statuses): Interpret each badge state and find where badges appear.
* [Trace how a signature is verified](#how-harness-code-verifies-a-signature): Follow how Harness Code matches a signature to a Harness user.
* [Review what signing does not do](#limitations): Identify the limits of signature verification today.
* [Resolve signing problems](#troubleshooting): Fix unverified, invalid, expired, and revoked signatures.

***

### Before you begin

* **Repository access:** You need push access to a Harness Code repository. For more information, see [Enable security](/code-repository/use-harness-code/manage-repositories/security.md).
* **Key pair:** You need an SSH or GPG key pair generated on your local machine. For instructions on generating one, see [Manage public keys](/harness-platform/3.0/harness-platform-resources/authentication/manage-public-keys.md).
* **Git version (SSH only):** SSH commit signing requires Git 2.34.0 or later. Check your version with `git --version`.

***

### Supported signature formats

Harness Code verifies the two signature formats that Git produces natively.

| Format             | Verification  | Notes                                                                                                       |
| ------------------ | ------------- | ----------------------------------------------------------------------------------------------------------- |
| SSH (SSHSIG)       | Supported     | OpenSSH signature format version 1 with the `git` namespace, using the `sha256` or `sha512` hash algorithm. |
| GPG (OpenPGP)      | Supported     | Covers signing subkeys, key expiration, and key or identity revocation.                                     |
| S/MIME (X.509)     | Not supported | Signatures produced with `gpg.format=x509` or `smimesign` report as `Unverified`.                           |
| Sigstore (gitsign) | Not supported | Keyless signatures are not recognized.                                                                      |

#### Supported key types

{% tabs %}
{% tab title="SSH Key" %}
Harness accepts SSH keys of the following types:

* `ssh-ed25519`
* `ssh-rsa`
* `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`
* `sk-ssh-ed25519@openssh.com` and `sk-ecdsa-sha2-nistp256@openssh.com` for FIDO or hardware security keys

DSA keys (`ssh-dss`) are not accepted.

{% hint style="info" %}
SSH support is behind the `CODE_SSH_ENABLED` feature flag. Contact [Harness Support](mailto:support@harness.io) to enable it. When the flag is off, **SSH** is not available as a **Key type** in your user profile.
{% endhint %}
{% endtab %}

{% tab title="GPG Key" %}
Harness accepts GPG keys that use RSA, DSA, ElGamal, ECDH, ECDSA, EdDSA, X25519, X448, Ed25519, or Ed448.

Signing subkeys are supported. When you upload a key, Harness stores the primary key and every subkey it contains, and matches a commit signature against the subkey that produced it. Your user profile lists only the primary key.
{% endtab %}
{% endtabs %}

***

### Configure commit signing

Setting up commit signing takes two parts: you add your public key to Harness so that Harness can verify your signatures, and you configure Git locally so that it signs your commits.

Use the **SSH Key** tab unless you have a specific reason to use GPG. SSH signing reuses the key pair and agent you already have, and needs no additional tooling. Use the **GPG Key** tab if your organization mandates OpenPGP signatures, or if you rely on key expiration or revocation.

{% tabs %}
{% tab title="SSH Key" %}
**Step 1: Add your SSH public key to Harness**

Harness verifies your signatures against the public keys on your user profile, so add the key before you push any signed commits.

Copy the contents of your public key file, replacing `~/.ssh/id_ed25519.pub` with your own key path:

```bash
cat ~/.ssh/id_ed25519.pub
```

Then add it to your profile:

1. In Harness, select your avatar to open your **User Profile**, then select the **Public keys** tab.
2. Select **+ Public Key**.
3. In the **Public Key** panel, enter a **Name** for the key. Harness suggests a name and derives an **Id** from it; to change the identifier, select the edit icon next to **Id**.
4. Set **Key type** to **SSH**.
5. Paste the key contents into **Public Key**.
6. Optionally, expand **Metadata** to add a description or tags.
7. Select **Save**.

Harness adds the key to your **Public keys** list and shows its fingerprint.

{% hint style="info" %}
If **SSH** is not available as a **Key type**, the `CODE_SSH_ENABLED` feature flag is off for your account. Contact [Harness Support](mailto:support@harness.io) to enable it.
{% endhint %}

**Step 2: Configure Git to use SSH for signing**

Tell Git to use SSH as the signing format and specify the path to your SSH private key, replacing `~/.ssh/id_ed25519` with your own key path:

```bash
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519
```

**Step 3: Enable commit signing**

To sign all commits by default:

```bash
git config --global commit.gpgsign true
```

Alternatively, sign individual commits by adding the `-S` flag:

```bash
git commit -S -m "Your commit message"
```

**Step 4: Push to Harness Code**

Push your signed commits to your Harness Code repository:

```bash
git push origin main
```

Harness Code verifies the signature against the SSH public keys on your user profile and displays the verification status on the commit listing page.

{% hint style="info" %}
SSH commit signing requires Git 2.34.0 or later. Check your version with `git --version` and upgrade if needed.
{% endhint %}
{% endtab %}

{% tab title="GPG Key" %}
**Step 1: Find your GPG key ID**

List your GPG secret keys:

```bash
gpg --list-secret-keys --keyid-format=long
```

In the output, find the `sec` line. The key ID follows the algorithm and key size. For example, in `sec rsa4096/3AA5C34371567BD2`, the key ID is `3AA5C34371567BD2`.

**Step 2: Add your GPG public key to Harness**

Harness verifies your signatures against the public keys on your user profile, so add the key before you push any signed commits.

Export your public key in ASCII armor format, replacing `3AA5C34371567BD2` with your own key ID:

```bash
gpg --armor --export 3AA5C34371567BD2
```

Copy the entire output, including the `-----BEGIN PGP PUBLIC KEY BLOCK-----` and `-----END PGP PUBLIC KEY BLOCK-----` lines. Then add it to your profile:

1. In Harness, select your avatar to open your **User Profile**, then select the **Public keys** tab.
2. Select **+ Public Key**.
3. In the **Public Key** panel, enter a **Name** for the key. Harness suggests a name and derives an **Id** from it; to change the identifier, select the edit icon next to **Id**.
4. Set **Key type** to **GPG**.
5. Paste the exported block into **Public Key**. The field expects content that begins with `-----BEGIN PGP PUBLIC KEY BLOCK-----`.
6. Optionally, expand **Metadata** to add a description or tags.
7. Select **Save**.

Harness adds the key to your **Public keys** list and shows its name and fingerprint.

{% hint style="info" %}
Make sure the email address on your GPG key matches the email address associated with your Harness account. Harness uses the committer email to match the signature to your user profile, and the GPG key must carry that same email as one of its user IDs.
{% endhint %}

**Step 3: Configure Git to use your GPG key**

Tell Git to use this key for signing, replacing `3AA5C34371567BD2` with your own key ID:

```bash
git config --global user.signingkey 3AA5C34371567BD2
```

**Step 4: Enable commit signing**

To sign all commits by default:

```bash
git config --global commit.gpgsign true
```

Alternatively, sign individual commits by adding the `-S` flag:

```bash
git commit -S -m "Your commit message"
```

**Step 5: Push to Harness Code**

Push your signed commits to your Harness Code repository as you normally would:

```bash
git push origin main
```

Harness Code verifies the signature against the GPG public keys on your user profile and displays the verification status on the commit listing page.
{% endtab %}
{% endtabs %}

For the full key generation and key management flow, including how to delete a key, see [Manage public keys](/harness-platform/3.0/harness-platform-resources/authentication/manage-public-keys.md).

***

### Signature verification statuses

Each signed commit displays a verification badge. Hover over the badge to see the key scheme, the key fingerprint, and the date of verification. Unsigned commits display no badge at all.

| Badge        | Description                                                                                                                                                                                                                                                                                                             |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Verified`   | The signature is valid and matches a public key on the committer's Harness user profile. This confirms that the stated committer created the commit and that it has not been modified since it was signed.                                                                                                              |
| `Unverified` | The commit has a signature that Harness could not verify. Either the key that produced the signature is not on the committer's Harness user profile, the committer email does not match a Harness user, or the signature format is not supported. The commit may be legitimate, but its authorship cannot be confirmed. |
| `Expired`    | The signature is cryptographically valid, but the key had already passed its expiration date when the commit was signed.                                                                                                                                                                                                |
| `Revoked`    | The commit was signed with a key that has since been revoked. A revoked key means the key owner or an administrator explicitly invalidated the key, which can indicate that the key was compromised or is no longer trusted.                                                                                            |
| `Invalid`    | The signature does not match the contents of the commit, the signer identity does not match the committer, or the signature itself is malformed. Treat this commit as untrusted.                                                                                                                                        |

#### Where badges appear

Harness Code shows the verification badge in the following places:

* **Commits page:** The commit list for a repository or a branch.
* **Commit details page:** Next to the commit header.
* **Pull request Commits tab:** The commit list you see when you [review a pull request](/code-repository/use-harness-code/pull-requests/review-pr.md).
* **File last-change bar:** The latest-commit row shown above a file and in the repository file browser.

***

### How Harness Code verifies a signature

The matching logic below explains most unexpected badges.

1. **Harness reads the committer email.** Verification keys off the commit's *committer* email, not the author email. A commit authored by one person and committed by another verifies against the committer's keys. This matches how other Git providers behave, and it means rebased or amended commits verify against whoever created the new commit.
2. **Harness resolves that email to a Harness user.** If no Harness user owns the committer email, the commit reports as `Unverified` regardless of how the signature was produced.
3. **Harness looks up the signing key on that user's profile.** SSH signatures are matched by the SHA-256 fingerprint embedded in the signature. GPG signatures are matched by key ID, including subkey IDs.
4. **Harness checks key validity at the time of signing.** Validity is evaluated against the signature creation time rather than the committer date, because the committer date can be modified locally. A key that expires after a commit was signed leaves that commit `Verified`.
5. **Harness verifies the signature cryptographically.** For GPG, Harness additionally requires one of the key's user IDs to match the committer email. A cryptographically valid signature whose key carries a different email reports as `Invalid`.

Verification results are cached per commit, so a commit is normally verified once. Results of `Unverified` are not cached, which means a commit that could not be matched to a key is re-evaluated automatically after you upload the missing key. Refresh the page to pick up the new status.

#### What happens when a key is revoked

Deleting a key from your profile and revoking a key are different actions:

* **Delete** removes the key from your profile. Commits already verified with that key keep their `Verified` badge.
* **Revoke as compromised** invalidates the cached results for that key, so commits previously shown as `Verified` are re-evaluated and report as `Revoked`. Use this when a private key leaks and you cannot trust anything signed with it. Revocation is available through the Harness keys API; the user profile offers only deletion.

***

### Limitations

* **Harness does not enforce signed commits.** There is no branch rule or push rule that requires a `Verified` signature, so signature status is advisory. For the branch and push rules that are available, see [Enable rules](/code-repository/use-harness-code/manage-repositories/rules.md).
* **Commits created in the Harness UI are not signed.** File edits, pull request merges and squashes, reverts, and cherry-picks performed in Harness Code produce unsigned commits, which display no badge even in a repository whose history is otherwise fully signed.
* **Unsigned commits are not flagged.** An unsigned commit and a commit from a user who never signs look identical, because neither displays a badge.
* **Badges appear on commits only.** Signed annotated tags are verified by the API, but tag, branch, and release views do not display a badge.
* **SSH signing keys are not separated from SSH authentication keys.** Any SSH key on your profile can be used for signature verification, and SSH keys carry no expiration of their own.
* **S/MIME and Sigstore signatures are not verified.** Only the formats listed under Supported signature formats are verified.

***

### Troubleshooting

<details>

<summary>Commits show as Unverified in Harness Code</summary>

Verify the following:

1. **Your public key is uploaded.** Open your **User Profile** in Harness, select the **Public keys** tab, and confirm that your SSH or GPG public key is listed. If the key is missing, add it as described under [Configure commit signing](#configure-commit-signing).
2. **Your email addresses match.** The committer email on the commit must belong to your Harness account, and a GPG key must list that same email as one of its user IDs. To check the email on your GPG key, run `gpg --list-keys --keyid-format=long`. To check the committer email on a commit, run `git log -1 --format='%ce'`.
3. **Git is using the correct key.** Run `git config --global user.signingkey` to verify your signing key configuration.
4. **Your commits are actually signed.** Run `git log --show-signature -1` to verify locally. If the output does not show a signature, enable signing with `git config --global commit.gpgsign true`.
5. **Your signature format is supported.** Harness verifies SSH and GPG signatures only. S/MIME (`gpg.format=x509`) and Sigstore signatures always report as Unverified.

</details>

<details>

<summary>Commits show as Invalid in Harness Code</summary>

An Invalid badge means the signature does not match the commit, the signature is malformed, or the identity on the signing key does not match the committer email.

Check the following:

1. Run `git log --show-signature -1` on the commit to confirm the signature validates locally.
2. Confirm that one of the user IDs on your GPG key uses the same email as the commit's committer email. Run `git log -1 --format='%ce'` to read the committer email and `gpg --list-keys --keyid-format=long` to list the emails on your key.
3. If the commit was rewritten after it was signed, for example by a rebase or an amend that preserved the old signature, re-sign it with `git commit --amend -S --no-edit` and force-push the corrected commit.

</details>

<details>

<summary>Commits show as Expired in Harness Code</summary>

The signing key had already expired when the commit was signed. Harness evaluates key validity as of the signature creation time.

To resolve this:

1. Extend the expiration on your GPG key, or generate a new key pair.
2. Add or re-upload the public key to your Harness user profile.
3. Update `git config --global user.signingkey` to point at the valid key.

Commits already signed with the expired key continue to show as Expired. Re-sign them with `git commit --amend -S --no-edit` if you need them verified.

</details>

<details>

<summary>Commits show as Revoked in Harness Code</summary>

The key used to sign the commits has been explicitly revoked and is no longer considered trustworthy. You cannot reverse a key revocation.

To resolve this:

1. Generate a new SSH or GPG key pair.
2. Add the new public key to your Harness user profile.
3. Update your Git configuration to use the new key.
4. Future commits signed with the new key display as Verified.

If your GPG key was revoked and you need assistance, contact Harness Support.

</details>

<details>

<summary>Commits created in the Harness Code UI show no verification badge</summary>

Harness Code does not sign the commits it creates on your behalf. File edits, pull request merges and squashes, reverts, and cherry-picks performed in the UI produce unsigned commits, and unsigned commits display no badge. To keep a fully signed history, make those changes locally with a signed commit and push them.

</details>

<details>

<summary>SSH signing fails with unsupported value or similar error</summary>

SSH commit signing requires Git version 2.34.0 or later. Check your Git version with `git --version`. If your version is older than 2.34.0, upgrade Git to use SSH signing.

</details>

<details>

<summary>GPG asks for a passphrase but no prompt appears</summary>

Configure the GPG agent to use a terminal-based prompt by running `export GPG_TTY=$(tty)`. Add this line to your shell profile (\~/.bashrc, \~/.zshrc, or equivalent) so it persists across sessions.

</details>

***

### Next steps

You can now sign commits and confirm that Harness Code recognizes them as verified.

* [Manage public keys](/harness-platform/3.0/harness-platform-resources/authentication/manage-public-keys.md): Generate and add SSH or GPG keys to your Harness profile.
* [Commit](/code-repository/use-harness-code/collaborate-and-develop/commit.md): Create and inspect commits in Harness Code.
* [Enable security](/code-repository/use-harness-code/manage-repositories/security.md): Enforce committer email verification alongside signing.

{% @harness-feedback/feedback %}
