Verify the Signed Artifacts
After you sign the artifact using the Artifact Signing step, it’s crucial to verify that the artifact has not been tampered and was signed by a trusted source. The Artifact Verification process enables you to validate the integrity and authenticity of the signed artifact before it’s deployed.
Artifact Verification in SCS
The artifact verification step ensures the authenticity of the signed artifact by validating it with the corresponding public key. If the public key matches the signed artifact it confirms that the artifact is intact, secure, and originates from a trusted source.
Artifact Verification step configuration
The Artifact Verification step pulls the .sig file from the artifact registry and verifies it with the corresponding public key. In the artifact signing step, if you have chosen not to push the .sig file to the registry, then for the artifact verification .sig file will instead be pulled from the Harness database. This process ensures that the artifact was signed by a trusted entity, thereby confirming its integrity and authenticity.
When adding this step to a deploy stage, ensure it's placed within a container step group and you enable the container based execution.
Artifact Verification step supports both container and non-container images.
Container Images
You can search for Artifact Verification and add it to either the Build , Deploy or Security stage of a Harness pipeline
Follow the instructions below to configure the Artifact Verification step.
-
Name: Provide a name for the verification step.
-
Artifact Source: Select the source container registry (e.g., DockerHub, ACR, ECR, etc.).
- HAR
- Docker Registry
- ECR
- ACR
- GAR
-
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:tagorimagename:digest.
-
Container Registry: Select the Docker Registry connector 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:tagormy-docker-org/repo-name@sha256:<digest>
-
Container Registry: Select the Docker Registry connector 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:tagor you can use the digestmy-docker-repo/my-artifact@sha256:<digest> -
Artifact Digest: Specify the digest of your artifact. After building your image using the Build and Push step or a Run 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.
-
Container Registry: Select the Docker Registry connector 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>:tagor you can use digestautomate.azurecr.io/<my-repo>@sha256:<digest> -
Artifact Digest: Specify the digest of your artifact. After building your image using the Build and Push step or a Run 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.
-
Container Registry: Select the Docker Registry connector 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:tagor you can use digestrepository-name/image@sha256:<digest> -
Artifact Digest: Specify the digest of your artifact. After building your image using the Build and Push step or a Run 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.
Non-Container Images
Artifacts aren't limited to container images. Signed non-container artifacts can also be verified where the unique identifier (digest SHA) generated during the signing step is used to locate and verify the artifact during the verification process.
To configure Artifact Verification for non-container images, provide the following details:
Name: Provide a name for the verification step.
Artifact Source: Select the Harness Local Stage as the source of the artifact.
Workspace Artifact Path: Specify the exact artifact path used during the signing step.
Non-container images can be verified using Cosign or Cosign with Secret Manager, just like container images.
Verify the Artifacts
You can perform artifact verification using Cosign with the following verification methods:
- Keyless - Uses short-lived, automatically generated keys based on identity to verify artifacts without storing private keys.
- Key-based - Uses a user-managed private and public key pair to verify 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.
Based on the verification type you select, click the tab below and specify the configurations for the Artifact Verification step to perform the verification.
- Keyless
- Key-based
- Secret Manager
Keyless verification using Cosign allows you to verify the authenticity and integrity of artifacts without requiring access to a private signing key. During verification, Cosign uses the certificate and signature stored in the attestation bundle to validate that the artifact was signed by a trusted identity and has not been tampered with. It checks the certificate chain against trusted root certificates, verifies the signature using the public key embedded in the certificate, and ensures that the certificate was valid at the time of signing.
In air-gapped environments, transparency log (Tlog) checks are skipped. The transparency log records signing events in a tamper-evident log, enabling independent verification. By default, the airgap setting is enabled, which prevents attestations from being pushed to the Rekor transparency log.
To sign artifacts with Keyless signing using cosign, complete the following steps:
- Click the radio button beside
Keylessunder Verify with: to select Keyless verification. - Select your preferred OIDC Provider from the dropdown under OIDC Provider. The available options are:

Harness OIDC
Harness OIDC allows you to use the pipeline’s built-in identity for keyless verification. In this approach, Harness acts as the OIDC provider and automatically generates an OIDC token during pipeline execution. Cosign uses this token to verify the artifact signature without requiring access to a private key.
The verification process checks the artifact’s signature and certificate using the identity from the OIDC token. It confirms that the artifact was signed by a trusted source, has not been tampered with, and matches the expected artifact. No additional configuration is required when using Harness as the OIDC provider.
Non-Harness OIDC
Non-Harness OIDC allows you to use an external identity provider for keyless verification. In this approach, the OIDC token is retrieved during pipeline execution from a configured connector, such as AWS, Azure, or GCP. This token is then used by Cosign to verify the artifact signature against the identity issued by the external provider.
The verification process checks the artifact’s signature and certificate to ensure that it was signed by a trusted identity, has not been tampered with, and matches the expected artifact. To use a Non-Harness OIDC provider for verification, you must configure the OIDC connector for keyless signing. For setup instructions, see the Non-Harness OIDC section in the Sign Artifact documentation.
To perform the attestation verification with Cosign selected, you need to pass the key from the Harness Secret Manager
- Public Key: Input your Public key from the Harness file secret.
If you used HashiCorp Vault as your Secret Manager for attestation, you can also use it for verifying the attestation.
- Connector: Select the same HashiCorp Vault connector that was used during the attestation process.
- Key: Enter the path to the Transit Secrets Engine in your HashiCorp Vault where your public key is stored. This should be the same path used for the attestation process. Note that HashiCorp Vault does not allow viewing the private key directly.
View Verified Artifacts
Once the artifact is signed and verified, you will be able to see the Artifact Integrity Verification status from the Artifacts Overview tab.
-
If the signed artifact is successfully verified using the public key, the verification status is displayed as Passed, along with the links to the corresponding rekor log entry and the execution results.
-
If the verification fails, the status is displayed as Failed.
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.
Example Pipeline For Artifact Verification
This example demonstrates how to implement artifact Verification in the Build stage of the pipeline.
This example Build stage has three 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
.sigfile back to the artifact registry. -
Artifact Verification: Verifies the signed artifact using the corresponding public key to confirm its source and integrity.
To replicate the Artifact Verification step you can use the below sample pipeline YAML
Sample Pipeline YAML
pipeline:
name: ArtifactVerification
identifier: ArtifactVerification
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
- step:
type: SscaArtifactVerification
name: Artifact Verification_1
identifier: ArtifactVerification_1
spec:
source:
type: docker
spec:
connector: lavakushDockerhub
image: lavakush07/easy-buggy-app:v5
verifySign:
type: cosign
spec:
public_key: account.Cosign_Public_Key
infrastructure:
type: KubernetesDirect
spec:
connectorRef: account.harness_kubernetes_connector
namespace: artifactverification
automountServiceAccountToken: true
nodeSelector: {}
os: Linux
variables:
- name: LOG_LEVEL
type: String
description: ""
required: false
value: TRACE