Documentation
¶
Overview ¶
Package attest builds and verifies in-toto attestations wrapped in DSSE envelopes, re-implemented on internal/sig (no in-toto or sigstore libraries). An attestation is a signed statement *about* an artifact: "this digest has this SBOM", "this digest was built by this pipeline" (SLSA provenance), "this digest is not affected by CVE-X" (VEX), or — for the agentic era — "agent X, running prompt hash Y, produced this digest" (an agent-action attestation).
The unit that ties everything together is the in-toto Statement: a subject (name + digest) plus a typed predicate. Signing wraps the Statement JSON in a DSSE envelope with the in-toto payload type; verifying unwraps it, checks the signature against a trust root and policy, and then — critically — checks that the statement's subject digest matches the artifact actually under test. Skipping that last check is how a valid attestation for image A gets replayed onto image B, so the verify path treats a subject mismatch as a hard failure.
Index ¶
- Constants
- func HashPrompt(prompt []byte) string
- func SBOMPredicateType(format string) string
- func Sign(st *Statement, signers ...sig.Signer) (*sig.Envelope, error)
- type ActionInfo
- type Agent
- type AgentAction
- type BuildDefinition
- type BuildMeta
- type Builder
- type OpenVEX
- type PromptRef
- type Requirement
- type ResourceDescriptor
- type Result
- type RunDetails
- type SLSAProvenance
- type Statement
- func NewAgentActionStatement(subjectName, subjectDigest string, action AgentAction) (*Statement, error)
- func NewSBOMStatement(subjectName, subjectDigest, format string, sbomJSON []byte) (*Statement, error)
- func NewStatement(subjectName, subjectDigest, predicateType string, predicate any) (*Statement, error)
- func ParseStatement(data []byte) (*Statement, error)
- type Subject
- type VEXStatement
- type VEXStatus
- type VEXVuln
- type VSA
- type VSAPolicy
- type VSAVerifier
- type VerdictResult
Constants ¶
const ( PredicateSLSAProvenance = "https://slsa.dev/provenance/v1" PredicateVSA = "https://slsa.dev/verification_summary/v1" PredicateOpenVEX = "https://openvex.dev/ns/v0.2.0" PredicateCycloneDX = "https://cyclonedx.org/bom" PredicateSPDX = "https://spdx.dev/Document" // PredicateAgentAction is this project's own predicate for attesting an // automated (AI-agent) infrastructure change. It is intentionally namespaced // under docker-security.dev to signal it is a local extension, not a standard. PredicateAgentAction = "https://docker-security.dev/attestations/agent-action/v0.1" )
Predicate type URIs for the predicates this package understands.
const InTotoPayloadType = "application/vnd.in-toto+json"
InTotoPayloadType is the DSSE payload type for in-toto attestations.
const InTotoStatementType = "https://in-toto.io/Statement/v1"
InTotoStatementType is the type URI for an in-toto v1 Statement.
Variables ¶
This section is empty.
Functions ¶
func HashPrompt ¶
HashPrompt returns the hex SHA-256 of a prompt's bytes, the value to store in PromptRef.SHA256. Callers hash the prompt themselves rather than passing it here-then-elsewhere, so the raw prompt never lingers in the attestation.
func SBOMPredicateType ¶
SBOMPredicateType returns the in-toto predicate type URI for an SBOM format name ("cyclonedx" or "spdx"). Unknown formats map to CycloneDX, which is the project's default SBOM encoding.
Types ¶
type ActionInfo ¶
type ActionInfo struct {
// Type is the action class (e.g. "build", "deploy", "patch", "config-change").
Type string `json:"type"`
// Tool is the tool or API the agent invoked.
Tool string `json:"tool,omitempty"`
// Target is what the action affected (e.g. an image ref or resource name).
Target string `json:"target,omitempty"`
}
ActionInfo describes what the agent did.
type Agent ¶
type Agent struct {
// ID is a stable identifier for the agent/automation (e.g.
// "ci-bot@corp.example" or a service account).
ID string `json:"id"`
// Model names the model that drove the agent, if any (e.g. "claude-opus-4").
Model string `json:"model,omitempty"`
// Version is the agent software version.
Version string `json:"version,omitempty"`
}
Agent identifies the automated actor.
type AgentAction ¶
type AgentAction struct {
Agent Agent `json:"agent"`
Prompt PromptRef `json:"prompt"`
Action ActionInfo `json:"action"`
Timestamp time.Time `json:"timestamp"`
}
AgentAction is the predicate for an attested automated action.
type BuildDefinition ¶
type BuildDefinition struct {
// BuildType is a URI naming the build process convention.
BuildType string `json:"buildType"`
// ExternalParameters are the top-level, externally supplied inputs (e.g. the
// source repo and ref).
ExternalParameters map[string]string `json:"externalParameters,omitempty"`
// ResolvedDependencies pins the materials the build consumed.
ResolvedDependencies []ResourceDescriptor `json:"resolvedDependencies,omitempty"`
}
BuildDefinition describes the build's inputs.
type BuildMeta ¶
type BuildMeta struct {
InvocationID string `json:"invocationId,omitempty"`
StartedOn *time.Time `json:"startedOn,omitempty"`
FinishedOn *time.Time `json:"finishedOn,omitempty"`
}
BuildMeta carries per-invocation metadata.
type Builder ¶
type Builder struct {
ID string `json:"id"`
}
Builder identifies the build platform. Its ID is the value provenance policy keys on ("was this built by our trusted builder?").
type OpenVEX ¶
type OpenVEX struct {
Context string `json:"@context"`
ID string `json:"@id"`
Author string `json:"author"`
Timestamp time.Time `json:"timestamp"`
Version int `json:"version"`
Statements []VEXStatement `json:"statements"`
}
OpenVEX is a minimal OpenVEX document: a set of statements about how specific products relate to specific vulnerabilities. It lets a verifier honor a vendor's "not affected" assertion instead of failing on a raw CVE match.
type PromptRef ¶
type PromptRef struct {
// SHA256 is the hex SHA-256 of the exact prompt/instruction bytes.
SHA256 string `json:"sha256"`
// Summary is an optional short, non-sensitive human description.
Summary string `json:"summary,omitempty"`
}
PromptRef references the instruction the agent acted on, by hash.
type Requirement ¶
type Requirement struct {
// ExpectedDigest is the "sha256:<hex>" the statement's subject must match.
// Required — an empty expected digest is a programming error, not "any".
ExpectedDigest string
// PredicateType, if set, is the exact predicate type that must be present.
PredicateType string
// Policy constrains the acceptable signer identity/issuer.
Policy sig.Policy
}
Requirement describes what a caller demands of an attestation.
type ResourceDescriptor ¶
type ResourceDescriptor struct {
URI string `json:"uri,omitempty"`
Digest map[string]string `json:"digest,omitempty"`
}
ResourceDescriptor names a material/dependency with its digest.
type Result ¶
type Result struct {
// Signer is the trust-root outcome (which key/identity vouched).
Signer sig.VerifyResult
// Statement is the verified in-toto statement (predicate available raw).
Statement *Statement
}
Result reports a successful attestation verification.
type RunDetails ¶
type RunDetails struct {
Builder Builder `json:"builder"`
Metadata BuildMeta `json:"metadata,omitempty"`
Byproducts []struct{} `json:"byproducts,omitempty"`
}
RunDetails describes the builder and this specific run.
type SLSAProvenance ¶
type SLSAProvenance struct {
BuildDefinition BuildDefinition `json:"buildDefinition"`
RunDetails RunDetails `json:"runDetails"`
}
SLSAProvenance is a trimmed SLSA v1 provenance predicate: who built the artifact, from what, and how. It answers "did this come from our pipeline?".
type Statement ¶
type Statement struct {
Type string `json:"_type"`
Subject []Subject `json:"subject"`
PredicateType string `json:"predicateType"`
Predicate json.RawMessage `json:"predicate"`
}
Statement is an in-toto v1 statement. The predicate is held as raw JSON so a verifier can check the type and subject without needing to understand every predicate schema — unknown predicate shapes still verify cryptographically.
func NewAgentActionStatement ¶
func NewAgentActionStatement(subjectName, subjectDigest string, action AgentAction) (*Statement, error)
NewAgentActionStatement builds a signed-ready in-toto statement attesting that an agent produced the artifact identified by subjectDigest. It validates that the prompt hash is a well-formed SHA-256 so a caller cannot accidentally emit an attestation with an empty or bogus prompt reference.
func NewSBOMStatement ¶
func NewSBOMStatement(subjectName, subjectDigest, format string, sbomJSON []byte) (*Statement, error)
NewSBOMStatement binds a serialized SBOM document to an image digest as an in-toto statement. sbomJSON must be a valid JSON document (an SPDX or CycloneDX BOM); it becomes the statement's predicate verbatim.
func NewStatement ¶
func NewStatement(subjectName, subjectDigest, predicateType string, predicate any) (*Statement, error)
NewStatement assembles a statement binding a subject digest to a typed predicate. subjectDigest must be a full "sha256:<hex>" string; the value is stored split into {"sha256": "<hex>"} per the in-toto schema. A malformed digest is rejected so we never emit an attestation about "nothing".
func ParseStatement ¶
ParseStatement decodes and shape-checks an in-toto statement.
func (*Statement) DecodePredicate ¶
DecodePredicate unmarshals the statement's predicate into v. It is a convenience for callers that, after verification, want the typed predicate (e.g. to read a provenance builder ID or a VEX status).
func (*Statement) Marshal ¶
Marshal serializes the statement as canonical JSON (the bytes that get signed inside the DSSE envelope).
func (*Statement) SubjectDigest ¶
SubjectDigest returns the first subject's "sha256:<hex>" digest, or "" if the statement carries no sha256 subject digest.
type Subject ¶
Subject is the artifact an attestation is about: a name plus one or more digests keyed by algorithm (e.g. {"sha256": "<hex>"}).
type VEXStatement ¶
type VEXStatement struct {
Vulnerability VEXVuln `json:"vulnerability"`
Products []string `json:"products"`
Status VEXStatus `json:"status"`
// Justification explains a not_affected status (e.g.
// "vulnerable_code_not_in_execute_path").
Justification string `json:"justification,omitempty"`
}
VEXStatement is one product/vuln/status assertion.
type VEXVuln ¶
type VEXVuln struct {
Name string `json:"name"` // e.g. "CVE-2024-0001"
}
VEXVuln names a vulnerability.
type VSA ¶
type VSA struct {
Verifier VSAVerifier `json:"verifier"`
TimeVerified time.Time `json:"timeVerified"`
ResourceURI string `json:"resourceUri"`
Policy VSAPolicy `json:"policy"`
VerificationResult VerdictResult `json:"verificationResult"`
// VerifiedLevels lists the properties that passed (e.g. "SIGNED",
// "SLSA_PROVENANCE", "SBOM_PRESENT").
VerifiedLevels []string `json:"verifiedLevels"`
}
VSA is a Verification Summary Attestation: a single, signed "we checked this and here is the verdict" that a downstream (deploy) system — or an orchestration agent — can trust without re-running every underlying check.
type VSAPolicy ¶
type VSAPolicy struct {
URI string `json:"uri,omitempty"`
}
VSAPolicy names the policy the verdict was computed under.
type VSAVerifier ¶
type VSAVerifier struct {
ID string `json:"id"`
}
VSAVerifier identifies who performed the verification.
type VerdictResult ¶
type VerdictResult string
VerdictResult is the pass/fail outcome recorded in a VSA.
const ( VerdictPassed VerdictResult = "PASSED" VerdictFailed VerdictResult = "FAILED" )