Actions attestation library for generating signed attestations for workflow artifacts
npx @tessl/cli install tessl/npm-actions--attest@1.6.0Actions attestation library for generating signed attestations for workflow artifacts. This library enables developers to bind subjects (named artifacts with their digests) to predicates (assertions about those subjects) using the in-toto statement format with Sigstore-issued signing certificates.
npm install @actions/attestimport { attest, attestProvenance, buildSLSAProvenancePredicate } from "@actions/attest";
import type { AttestOptions, AttestProvenanceOptions, Attestation, Subject, Predicate } from "@actions/attest";For CommonJS:
const { attest, attestProvenance, buildSLSAProvenancePredicate } = require("@actions/attest");import { attest, attestProvenance } from "@actions/attest";
import * as core from "@actions/core";
// Basic attestation with custom predicate
const ghToken = core.getInput("gh-token");
const attestation = await attest({
subjects: [{
name: "my-artifact-name",
digest: { "sha256": "36ab4667..." }
}],
predicateType: "https://in-toto.io/attestation/release",
predicate: { version: "1.0.0", release: true },
token: ghToken
});
// SLSA provenance attestation
const provenanceAttestation = await attestProvenance({
subjects: [{
name: "my-artifact-name",
digest: { "sha256": "36ab4667..." }
}],
token: ghToken
});
console.log(attestation.attestationID);@actions/attest is built around several key components:
attest() function that combines subjects and predicates into signed attestationsattestProvenance() function that generates SLSA build provenance attestations automaticallyCreates signed attestations for any subject/predicate pair using the in-toto statement format.
/**
* Generates an attestation for the given subject and predicate
* @param options - Attestation configuration options
* @returns Promise resolving to the signed attestation
*/
function attest(options: AttestOptions): Promise<Attestation>;
interface AttestOptions {
/** @deprecated Use 'subjects' instead */
subjectName?: string;
/** @deprecated Use 'subjects' instead */
subjectDigest?: Record<string, string>;
/** Collection of subjects to be attested */
subjects?: Subject[];
/** URI identifying the content type of the predicate being attested */
predicateType: string;
/** Predicate to be attested */
predicate: object;
/** GitHub token for writing attestations */
token: string;
/** Sigstore instance to use for signing */
sigstore?: "public-good" | "github";
/** HTTP headers to include in request to attestations API */
headers?: { [header: string]: string | number | undefined };
/** Whether to skip writing the attestation to the GH attestations API */
skipWrite?: boolean;
}Usage Example:
import { attest } from "@actions/attest";
const customAttestation = await attest({
subjects: [
{ name: "binary.exe", digest: { "sha256": "abc123..." } },
{ name: "config.json", digest: { "sha256": "def456..." } }
],
predicateType: "https://example.com/attestation/security-scan",
predicate: {
scanner: "custom-security-tool",
version: "2.1.0",
passed: true,
vulnerabilities: []
},
token: process.env.GITHUB_TOKEN
});Generates SLSA build provenance attestations using GitHub Actions workflow metadata.
/**
* Attests the build provenance of the provided subject using SLSA predicate
* @param options - Provenance attestation configuration options
* @returns Promise resolving to the signed provenance attestation
*/
function attestProvenance(options: AttestProvenanceOptions): Promise<Attestation>;
interface AttestProvenanceOptions {
/** @deprecated Use 'subjects' instead */
subjectName?: string;
/** @deprecated Use 'subjects' instead */
subjectDigest?: Record<string, string>;
/** Collection of subjects to be attested */
subjects?: Subject[];
/** GitHub token for writing attestations */
token: string;
/** Sigstore instance to use for signing */
sigstore?: "public-good" | "github";
/** HTTP headers to include in request to attestations API */
headers?: { [header: string]: string | number | undefined };
/** Whether to skip writing the attestation to the GH attestations API */
skipWrite?: boolean;
/** Issuer URL responsible for minting the OIDC token */
issuer?: string;
}Usage Example:
import { attestProvenance } from "@actions/attest";
const provenanceAttestation = await attestProvenance({
subjects: [{
name: "dist/app.tar.gz",
digest: { "sha256": "789xyz..." }
}],
token: process.env.GITHUB_TOKEN,
sigstore: "public-good"
});Builds SLSA provenance predicates using GitHub Actions workflow metadata.
/**
* Builds an SLSA provenance predicate using GitHub Actions workflow metadata
* @param issuer - URL for the OIDC issuer (defaults to GitHub Actions token issuer)
* @returns Promise resolving to the SLSA provenance predicate
*/
function buildSLSAProvenancePredicate(issuer?: string): Promise<Predicate>;Usage Example:
import { buildSLSAProvenancePredicate, attest } from "@actions/attest";
// Build custom SLSA predicate and combine with custom attestation
const slsaPredicate = await buildSLSAProvenancePredicate();
const customAttestation = await attest({
subjects: [{ name: "app.jar", digest: { "sha256": "abc123..." } }],
predicateType: slsaPredicate.type,
predicate: {
...slsaPredicate.params,
customField: "additional-metadata"
},
token: process.env.GITHUB_TOKEN
});/** Represents an attestation subject (artifact) */
interface Subject {
/** Name of the subject */
name: string;
/** Digests of the subject - map of digest algorithms to their hex-encoded values */
digest: Record<string, string>;
}
/** Represents an attestation predicate (assertion) */
interface Predicate {
/** URI identifying the content type of the predicate */
type: string;
/** Predicate parameters */
params: object;
}
/** Artifact attestation result */
interface Attestation {
/** Serialized Sigstore bundle containing the provenance attestation, signature, signing certificate and witnessed timestamp */
bundle: SerializedBundle;
/** PEM-encoded signing certificate used to sign the attestation */
certificate: string;
/** ID of Rekor transparency log entry created for the attestation */
tlogID?: string;
/** ID of the persisted attestation (accessible via the GH API) */
attestationID?: string;
}
/** JSON representation of Sigstore bundle (from @sigstore/bundle) */
type SerializedBundle = any;The library throws errors in the following cases:
subjects nor subjectName/subjectDigest are providedskipWrite: true)GITHUB_SERVER_URL environment variable contains invalid URLstry {
const attestation = await attest({
subjects: [{ name: "app", digest: { "sha256": "abc123" } }],
predicateType: "https://example.com/test",
predicate: { test: true },
token: "invalid-token"
});
} catch (error) {
console.error("Attestation failed:", error.message);
// Handle specific error types based on error message
}The library automatically selects the appropriate Sigstore instance:
sigstore option to "public-good" or "github"Public-good instance uses the public Rekor transparency log, while GitHub instance uses GitHub's internal timestamp authority for private repositories.