> 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/software-supply-chain-assurance/use-scs/artifact-security/sign-verify/sign-artifacts.md).

# Sign Artifacts with Harness SCS

Protect your software supply chain by safeguarding your artifacts from being compromised. Attackers may attempt to inject malicious code into your artifacts, aiming to tamper with your software supply chain. One of the primary goals of attackers is to get you to deploy compromised (or "poisoned") artifacts into your environments. In the worst-case scenario, your deployments could become a distribution channel for these poisoned artifacts, putting your customers and users at risk.

As artifacts pass through multiple stages in the software lifecycle, ensuring they remain secure and untampered is critical. Artifact signing provides a reliable way to guarantee that the artifact built at one stage is the exact same artifact consumed or deployed at the next, with no chance of compromise. This process builds trust, ensures integrity, and strengthens the security of your software supply chain.

### Artifact Signing in SCS <a href="#artifact-signing-in-scs" id="artifact-signing-in-scs"></a>

For signing container images, the Artifact Signing step retrieves the artifact from the container registry, signs it using [Cosign](https://docs.sigstore.dev/cosign/signing/overview/) with a private key from a key pair, and generates a signature file `.sig`. Once the signature is successfully generated, it is pushed back to the same container registry alongside the artifact. This signature file is essential for verifying the artifact's integrity and authenticity. For more details on artifact verification, refer to the [Artifact Verification documentation](/software-supply-chain-assurance/use-scs/artifact-security/sign-verify/verify-signed-artifacts.md)

<figure><img src="/files/9PUUdjepmyDuafc6dGCH" alt=""><figcaption></figcaption></figure>

### Artifact Signing step configuration <a href="#artifact-signing-step-configuration" id="artifact-signing-step-configuration"></a>

The Artifact Signing step allows you to sign your artifacts and optionally push the generated signature file `.sig` to the same artifact registry from which the artifact was retrieved.

Artifact Signing step supports both [**container**](#container-images) as well as [**non-container images**](#non-container-images).

<figure><img src="/files/zbtP5P0IPA67I9IwAoAm" alt=""><figcaption></figcaption></figure>

#### Container images <a href="#container-images" id="container-images"></a>

You can search for **Artifact Signing** and add it to either the **Build** , **Deploy**, or **Security** stage of a Harness pipeline

{% hint style="info" %}
At present, Harness does not support artifact signing in the deployment stage, However this is part of our roadmap.
{% endhint %}

Follow the instructions below to configure the Artifact Signing step.

* **Name**: Provide a name for the signing step.
* **Artifact Source**: Select the source container registry (e.g., DockerHub, ACR, ECR, etc.).

{% tabs %}
{% tab title="HAR" %}

* **Registry:** Select the Harness Registry configured for the Harness Artifact Registry where your artifact is stored.
* **Image:** Enter the name of your image with tag or digest, such as `imagename:tag` or `imagename:digest`.
  {% endtab %}

{% tab title="Docker Registry" %}

* **Container Registry:** Select the [Docker Registry connector](/harness-ai/use-harness-platform/connectors/cloud-providers/ref-cloud-providers/docker-registry-connector-settings-reference.md) that is configured for the DockerHub container registry where the artifact is stored.
* **Image:** Enter the name of your image using a tag or digest, example `my-docker-org/repo-name:tag` or `my-docker-org/repo-name@sha256:<digest>`

{% hint style="info" %}
Unlike other artifact sources, JFrog Artifactory requires additional permissions for attestation. The connector’s user or token must have `Read`, `Annotate`, `Create/Deploy`, and `Delete` permissions.
{% endhint %}
{% endtab %}

{% tab title="ECR" %}

* **Container Registry:** Select the [Docker Registry connector](/harness-ai/use-harness-platform/connectors/cloud-providers/ref-cloud-providers/docker-registry-connector-settings-reference.md) that is configured for the Elastic container registry where the artifact is stored.
* **Image:** Enter the name of your image using a tag or digest, example `my-docker-repo/my-artifact:tag`or you can use the digest `my-docker-repo/my-artifact@sha256:<digest>`
* **Artifact Digest:** Specify the digest of your artifact. After building your image using the [Build and Push](#slsa-generation-step-configuration-with-build-and-push-step) step or a [Run](#slsa-generation-step-configuration-with-run-step) step, save the digest in a variable. You can then reference it here using a Harness expression. Refer to the workflows described below for detailed guidance.
* **Region:** The geographical location of your ECR repository, example `us-east-1`
* **Account ID:** The unique identifier associated with your AWS account.
  {% endtab %}

{% tab title="ACR" %}

* **Container Registry:** Select the [Docker Registry connector](/harness-ai/use-harness-platform/connectors/cloud-providers/ref-cloud-providers/docker-registry-connector-settings-reference.md) that is configured for the Azure container registry where the artifact is stored.
* **Image:** Enter your image details in the format `<registry-login-server>/<repository>`. The `<registry-login-server>` is a fully qualified name of your Azure Container Registry. It typically follows the format `<registry-name>.azurecr.io`, where `<registry-name>` is the name you have given to your container registry instance in Azure. Example input: `automate.azurecr.io/<my-repo>:tag` or you can use digest `automate.azurecr.io/<my-repo>@sha256:<digest>`
* **Artifact Digest:** Specify the digest of your artifact. After building your image using the [Build and Push](#slsa-generation-step-configuration-with-build-and-push-step) step or a [Run](#slsa-generation-step-configuration-with-run-step) step, save the digest in a variable. You can then reference it here using a Harness expression. Refer to the workflows described below for detailed guidance.
* **Subscription Id:** Enter the unique identifier that is associated with your Azure subscription.
  {% endtab %}

{% tab title="GAR" %}

* **Container Registry:** Select the [Docker Registry connector](/harness-ai/use-harness-platform/connectors/cloud-providers/ref-cloud-providers/docker-registry-connector-settings-reference.md) that is configured for the Google container registry where the artifact is stored.
* **Image:**: Enter the name of your image using tag or digest, example `repository-name/image:tag` or you can use digest `repository-name/@sha256:<digest>`.
* **Artifact Digest:** Specify the digest of your artifact. After building your image using the [Build and Push](#slsa-generation-step-configuration-with-build-and-push-step) step or a [Run](#slsa-generation-step-configuration-with-run-step) step, save the digest in a variable. You can then reference it here using a Harness expression. Refer to the workflows described below for detailed guidance.
* **Host:** Enter your GAR Host name. The Host name is regional-based. For example, `us-east1-docker.pkg.dev`.
* **Project ID:** Enter the unique identifier of your Google Cloud Project. The Project-ID is a distinctive string that identifies your project across Google Cloud services. Example: `my-gcp-project`.
  {% endtab %}
  {% endtabs %}

#### Non-Container images <a href="#non-container-images" id="non-container-images"></a>

Artifacts are not limited to container images. With the Artifact Signing step, you can also sign non-container images to ensure the integrity and authenticity. Each artifact is uniquely identified by its digest (SHA), which is later used during the verification step.

The following non-container artifact types are supported:

* Helm Charts (`.tgz`)
* YAML Manifests (`.yaml`)
* Java Archives (`.jar`)
* Web Application Archives (`.war`)
* Artifacts that are not listed above will be considered as `Unknown` types.

Follow the instructions below to configure the Artifact Signing step for non-container images:

**Name:** Provide a name for the signing step.

**Artifact Source:** Select the Harness Local Stage as the source of the artifact.

**Workspace Artifact Path:** Provide the exact path to the artifact within the workspace. Ensure that you run a custom step to pull the artifact into the workspace directory.

**Target Detection:** Choose between Auto and Manual

**Auto (default):** Automatically sets the artifact name from the provided path.

**Manual:** Allows you to manually specify the artifact name and version.

<figure><img src="/files/xeIBJONogmrdl4ILn0nw" alt=""><figcaption></figcaption></figure>

#### Sign the artifacts <a href="#sign-the-artifacts" id="sign-the-artifacts"></a>

You can sign artifacts using Cosign with the following signing methods:

* **Keyless** - Uses short-lived, automatically generated keys based on identity to sign artifacts without storing private keys.
* **Key-based** - Uses a user-managed private and public key pair to sign artifacts, requiring secure key storage and handling.
* **Secret Manager** - A secure service used to store, manage, and access sensitive data such as cryptographic keys without exposing them directly in pipelines.

{% tabs %}
{% tab title="Keyless" %}
Keyless signing using Cosign lets you sign artifacts without managing long-lived signing keys. Instead, Cosign uses your workload identity (via OIDC) to obtain a short-lived signing certificate during pipeline execution, which is then used to sign the provenance. The signing key is generated and used only in memory and is not persisted. This reduces the risk of key compromise while ensuring the provenance remains verifiable and trusted. The signed artifact is pushed to the container registry and associated with the image digest, typically referenced using the digest with a `.sig` extension.

To sign artifacts with Keyless signing using cosign, complete the following steps:

1. Click the radio button beside `Keyless` under **Sign with:** to select Keyless signing.
2. Select your preferred OIDC Provider from the dropdown under OIDC Provider. The available options are:
   * [Harness](/software-supply-chain-assurance/use-scs/artifact-security/sign-verify/sign-artifacts.md#harness-oidc)
   * [Non-Harness](/software-supply-chain-assurance/use-scs/artifact-security/sign-verify/sign-artifacts.md#non-harness-oidc)

<figure><img src="/files/s2G0NE8ZOZv2DhTQ4D6q" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This signing method is not supported for SMP at the moment.
{% endhint %}

**Harness OIDC**

Harness OIDC allows you to use the pipeline’s built-in identity for keyless signing. In this approach, Harness acts as the OIDC provider and automatically supplies the identity required during pipeline execution, eliminating the need for external identity configuration.

**Non-Harness OIDC**

Non-Harness OIDC allows you to use an external identity provider for keyless signing. In this approach, the OIDC token is retrieved from a configured connector (such as AWS, Azure, or GCP) during pipeline execution and used to obtain a signing certificate. This option is useful when you want to integrate with your organization’s existing identity and access management system instead of using Harness as the OIDC provider.

To use a Non-Harness OIDC provider, you need to configure the Connector for Keyless Signing. To configure the Connector:

1. Navigate to the **Configuration** page under the **Manage** section from the sidebar navigation of your SCS account. The **General** tab opens by default.
2. Click `Select Connector` next to `Connector for Keyless Signing` to open the `Create or Select an Existing Connector` dialog.
3. Select your required connector from the list of existing connectors. You can search for your created connector or filter connectors by **Project**, **Organization**, and **Account**.
4. Alternatively, click `+ New Connector` to create a new OIDC connector for your preferred cloud provider. For more information, see [Connectors for Cloud Providers](https://app.gitbook.com/s/3F2TpHXhur2QtQnORSM9/use-harness-platform/connectors/cloud-providers/README).
5. Click `Apply Selected`. Once selected, you can view the **Configuration Saved Successfully** toaster message at the top, indicating that the connector has been selected or created successfully.

<figure><img src="/files/8fd3olUT7hgak3RrFr8q" alt=""><figcaption></figcaption></figure>

Once the connector configuration is done successfully, you can perform artifact signing with a Non-Harness OIDC provider.
{% endtab %}

{% tab title="Key-based" %}
To perform Artifact Signing with **Cosign** selected, you need a key pair. Follow the instructions below to generate the key pair.

<details>

<summary>Generate key pairs using Cosign for Artifact Signing</summary>

</details>

* **Private Key**: Input your Private key from the [Harness file secret](/harness-ai/use-harness-platform/secrets/add-file-secrets.md).
* **Password**: Input your Password for the Private key from the [Harness file secret](/harness-ai/use-harness-platform/secrets/add-file-secrets.md).
  {% endtab %}

{% tab title="Secret Manager" %}
In this mode, you can pass your **Cosign keys** using a **Secret Manager**. Currently, SCS supports only the **HashiCorp Vault** secret manager. You can connect your Vault with Harness using the [Harness HashiCorp Vault connector](/harness-ai/use-harness-platform/secrets/secrets-management/add-hashicorp-vault.md). Here are the key points to consider when connecting your Vault:

{% hint style="info" %}
Harness Vault Connector now supports fetching keys from Vault subfolder paths. This feature is behind the FF `SSCA_COSIGN_USING_VAULT_V2`. To enable it contact [Harness Support](mailto:support@harness.io), and also ensure to upgrade your Harness delegate version to `25.10.87000` or higher.
{% endhint %}

1. **Enable the Transit Secrets Engine** on your HashiCorp Vault. This is essential for key management and cryptographic operations.
2. Configure your HashiCorp Vault connector using the following authentication methods [**AppRole**](/harness-ai/use-harness-platform/secrets/secrets-management/add-hashicorp-vault.md#option-app-role), [**Token**](/harness-ai/use-harness-platform/secrets/secrets-management/add-hashicorp-vault.md#option-token), [**JWT Auth**](https://developer.harness.io/docs/platform/secrets/secrets-management/add-hashicorp-vault/#option-jwtoidc-auth) or [**Vault Agent**](/harness-ai/use-harness-platform/secrets/secrets-management/add-hashicorp-vault.md#option-vault-agent).
3. Create a Cosign key pair of type `ecdsa-p256`,`rsa-2048`, or `rsa-4096` in the Transit Secrets Engine. You can do this in two ways:
   * **CLI**: Run the command:

     ```bash
     vault write -f <transit_name>/<key_name> type=ecdsa-p256
     ```
   * **Vault UI**: Create the key pair directly from the Vault interface.
4. Ensure the Vault token generated has the [**required policy**](https://docs.sigstore.dev/cosign/key_management/overview/#hashicorp-vault) applied for Cosign to perform attestation operations.

Configure the following fields in the step to perform the attestation

* **Connector**: Select the HashiCorp Vault connector.
* **Key**: Enter the path to the Transit Secrets Engine in your HashiCorp Vault where the keys are stored.

{% hint style="info" %}
Harness Vault Connector is supported only for Kubernetes and VM infrastructure. Ensure your Harness delegate is on version `25.10.87000` or higher.
{% endhint %}
{% endtab %}
{% endtabs %}

**Attach Signature to Artifact Registry** (Optional): By default, this option is unchecked which means the signature will not be uploaded to the artifact registry and checking this option will push the signature as a `.sig` file to the artifact registry.

{% hint style="info" %}
This option is available only for signing container images.
{% endhint %}

### View signed artifacts <a href="#view-signed-artifacts" id="view-signed-artifacts"></a>

You can easily access the signed artifact details from the Artifacts Overview tab. This section shows the signature and who signed the artifact. Additionally, you can also find the artifact signing as an event in the Chain of Custody, where a new entry is logged every time you sign an artifact. This entry includes a link to the execution results and rekor log entry, allowing you to track the signing activity and cross-check the details.

{% hint style="info" %}
Rekor logs are disabled by default. To enable them, click on **Project Settings**, navigate to **Default Settings**, and disable Airgap mode in Supply Chain Security.
{% endhint %}

<figure><img src="/files/YPJgln7VzW5DwC4eJyzr" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
You are allowed to re-sign the same image multiple times, with each new signing overwriting the previous one. The Artifacts Overview tab will always display the most up-to-date signing details, reflecting the latest signature information for the artifact.
{% endhint %}

### Example pipeline For Artifact Signing <a href="#example-pipeline-for-artifact-signing" id="example-pipeline-for-artifact-signing"></a>

This example demonstrates how to implement artifact signing in the Build stage of the pipeline.

This example **Build** stage has two steps:

* **Build and Push an Image to Docker Registry**: This step builds the cloned codebase and pushes the image to the container registry (DockerHub, ACR, etc.).
* **Artifact Signing**: Pulls the artifact from the registry and signs it with a private key pair and pushes the `.sig` file back to the artifact registry.

<figure><img src="/files/CZFDSqXDUZlZmGM2ExBB" alt=""><figcaption><p>Click to view full size image</p></figcaption></figure>

To replicate the Artifact Signing step you can use the below sample pipeline YAML

<details>

<summary>Sample Pipeline YAML</summary>

```yaml
pipeline:
  name: Artifact Signing
  identifier: ArtifactSigning
  tags: {}
  projectIdentifier: Harness
  orgIdentifier: default
  properties:
    ci:
      codebase:
        connectorRef: Harnessgithub
        build: <+input>
  stages:
    - stage:
        name: Build
        identifier: Build
        description: ""
        type: CI
        spec:
          cloneCodebase: true
          caching:
            enabled: true
          buildIntelligence:
            enabled: true
          execution:
            steps:
              - step:
                  type: BuildAndPushDockerRegistry
                  name: BuildAndPushDockerRegistry_1
                  identifier: BuildAndPushDockerRegistry_1
                  spec:
                    connectorRef: lavakushDockerhub
                    repo: lavakush07/easy-buggy-app
                    tags:
                      - v5
                    caching: true
              - step:
                  type: SscaArtifactSigning
                  name: Artifact Signing_1
                  identifier: ArtifactSigning_1
                  spec:
                    source:
                      type: docker
                      spec:
                        connector: lavakushDockerhub
                        image: lavakush07/easy-buggy-app:v5
                    signing:
                      type: cosign
                      spec:
                        private_key: account.Cosign_Private_Key
                        password: account.Cosign_Password
                    uploadSignature:
                      upload: true
          infrastructure:
            type: KubernetesDirect
            spec:
              connectorRef: account.harness_kubernetes_connector
              namespace: artifact-signing
              automountServiceAccountToken: true
              nodeSelector: {}
              os: Linux
        variables:
          - name: LOG_LEVEL
            type: String
            description: ""
            required: false
            value: TRACE


```

</details>

### Verify Artifact Signing <a href="#verify-artifact-signing" id="verify-artifact-signing"></a>

You can verify the signed artifacts using the Artifact verification step. Go to [configure your pipeline to verify the artifact Signing](/software-supply-chain-assurance/use-scs/artifact-security/sign-verify/verify-signed-artifacts.md) to configure your pipeline for verification.
