Documentation
¶
Overview ¶
Package pack provides APIs to open, validate, and read evidence packs.
An evidence pack is a ZIP archive containing a manifest.json and artifacts. This package enforces structural, size, and digest checks defined by the Evidence Pack specification.
Opening a pack:
p, err := pack.Open("evidence.pack")
if err != nil {
log.Fatal(err)
}
defer p.Close()
Verifying integrity (all digests match):
if err := p.VerifyIntegrity(); err != nil {
log.Fatal("integrity check failed:", err)
}
Reading artifacts:
data, err := p.ReadArtifact("artifacts/config.json")
if err != nil {
log.Fatal(err)
}
Accessing manifest metadata:
m := p.Manifest()
fmt.Printf("Stream: %s\n", m.Stream)
fmt.Printf("Pack Digest: %s\n", m.PackDigest)
fmt.Printf("Artifacts: %d\n", len(m.Artifacts))
Verifying attestations:
verifier, _ := verify.NewSigstoreVerifier(verify.WithIssuer("https://accounts.google.com"))
results, err := p.VerifyAllAttestations(ctx, verifier)
Verifying embedded attestations in merged packs:
results, err := p.VerifyEmbeddedAttestations(ctx, verifier)
for _, r := range results {
fmt.Printf("Source pack %s: verified by %s\n", r.Stream, r.Result.Identity.Subject)
}
For creating packs, see the pack/builder subpackage. For Sigstore verification, see the pack/verify subpackage.
Layer Boundary ¶
This package is Layer 1 (Pack Format) - a foundational layer that defines the evidence pack format. It MUST NOT import:
- internal/component (component management)
- internal/collector (collector execution)
- internal/tool (tool execution)
- internal/dispatch (tool dispatch)
- internal/catalog (discovery)
- internal/cli (presentation)
The pack format is independent of how packs are created or consumed.
Index ¶
- Constants
- func BuildCanonicalArtifactList(manifest *Manifest) []byte
- func ComputeManifestDigest(rawManifest []byte) (canonical string, digest string, err error)
- func HashCanonicalList(canonical []byte) string
- func ValidateManifestBytes(jsonBytes []byte) error
- type Artifact
- type EmbeddedAttestation
- type EmbeddedVerifyResult
- type ExtractOptions
- type ExtractResult
- type Manifest
- type Pack
- func (p *Pack) Close() error
- func (p *Pack) Extract(opts ExtractOptions) (*ExtractResult, error)
- func (p *Pack) HasFile(path string) bool
- func (p *Pack) ListAttestations() []string
- func (p *Pack) Manifest() Manifest
- func (p *Pack) OpenArtifact(path string) (io.ReadCloser, error)
- func (p *Pack) OpenArtifactWithBudget(path string, budget *ReadBudget) (io.ReadCloser, error)
- func (p *Pack) OpenFileUntrusted(path string) (io.ReadCloser, error)
- func (p *Pack) OpenFileUntrustedWithBudget(path string, budget *ReadBudget) (io.ReadCloser, error)
- func (p *Pack) ReadArtifact(path string) ([]byte, error)
- func (p *Pack) ReadArtifactTo(w io.Writer, path string) (int64, error)
- func (p *Pack) ReadArtifactWithBudget(path string, budget *ReadBudget) ([]byte, error)
- func (p *Pack) ReadAttestation(path string) ([]byte, error)
- func (p *Pack) ReadFileUntrusted(path string) ([]byte, error)
- func (p *Pack) ReadFileUntrustedWithBudget(path string, budget *ReadBudget) ([]byte, error)
- func (p *Pack) VerifyAllArtifacts() error
- func (p *Pack) VerifyAllAttestations(ctx context.Context, v verify.Verifier) (map[string]*verify.Result, error)
- func (p *Pack) VerifyAttestation(ctx context.Context, path string, v verify.Verifier) (*verify.Result, error)
- func (p *Pack) VerifyEmbeddedAttestations(ctx context.Context, v verify.Verifier) ([]EmbeddedVerifyResult, error)
- func (p *Pack) VerifyIntegrity() error
- func (p *Pack) VerifyPackDigest() error
- func (p *Pack) Zip() *zip.Reader
- type Provenance
- type ReadBudget
- type Source
- type SourcePack
Constants ¶
const ( SpecVersion = packspec.SpecVersion DSSEPayloadType = packspec.DSSEPayloadType SigstoreBundleMediaType = packspec.SigstoreBundleMediaType )
Re-export constants from packspec for backwards compatibility.
Variables ¶
This section is empty.
Functions ¶
func BuildCanonicalArtifactList ¶
BuildCanonicalArtifactList builds the canonical artifact list per spec. Format: {path}\t{digest}\n for each embedded artifact, sorted by path. Returns the canonical bytes to be hashed.
func ComputeManifestDigest ¶
ComputeManifestDigest computes the manifest_digest per spec. It canonicalizes the raw manifest JSON using JCS (RFC 8785) and returns:
- canonical: the JCS canonical form of the manifest
- digest: the SHA256 hash in "sha256:{hex}" format
- err: any error during canonicalization (e.g., invalid_number)
func HashCanonicalList ¶
HashCanonicalList computes SHA256 of the canonical list and formats as sha256:{hex}. Uses the digest package for consistent formatting.
func ValidateManifestBytes ¶
ValidateManifestBytes validates raw manifest JSON without returning the parsed manifest. Use this to validate manifest bytes at trust boundaries (test fixtures, manual ZIP creation, etc.).
SECURITY: All codepaths that create or ingest manifest.json (builder, merge, tests) should call either ValidateManifestBytes or ParseManifest to ensure structural validity, path safety, and spec compliance.
Types ¶
type Artifact ¶
Type aliases for backwards compatibility. These allow existing code using pack.Manifest, pack.Artifact, etc. to continue working.
type EmbeddedAttestation ¶
type EmbeddedAttestation = packspec.EmbeddedAttestation
Type aliases for backwards compatibility. These allow existing code using pack.Manifest, pack.Artifact, etc. to continue working.
type EmbeddedVerifyResult ¶
type EmbeddedVerifyResult struct {
// SourcePackIndex is the index of the source pack in provenance.source_packs.
SourcePackIndex int
// AttestationIndex is the index of the attestation within the source pack's embedded_attestations.
AttestationIndex int
// Stream is the stream identifier of the source pack.
Stream string
// Result is the verification result.
Result *verify.Result
}
EmbeddedVerifyResult contains the verification result for an embedded attestation.
type ExtractOptions ¶
type ExtractOptions struct {
// OutputDir is the directory to extract artifacts to.
OutputDir string
// Paths specifies specific artifact paths to extract.
// If empty and All is false, returns an error.
Paths []string
// All extracts all artifacts when true.
All bool
// Filter is a glob pattern to match artifact paths.
// Only artifacts matching the pattern are extracted.
Filter string
// Force overwrites existing files when true.
Force bool
// SkipPreVerification skips VerifyIntegrity() before extraction.
// By default (when false), Extract runs VerifyIntegrity() to ensure
// the pack_digest matches the canonical artifact list, preventing
// attacks where extra artifacts are injected into the ZIP.
//
// Set to true only for performance when you've already verified the pack.
SkipPreVerification bool
}
ExtractOptions configures artifact extraction behavior.
func SafeExtractAll ¶
func SafeExtractAll(outputDir string) ExtractOptions
SafeExtractAll returns ExtractOptions configured for secure extraction. This is the recommended way to configure extraction for production use.
Features:
- Extracts all artifacts to the specified directory
- Pre-verifies pack integrity before extraction
- Fails if files already exist (no overwrite)
Example:
p, _ := pack.Open("evidence.pack")
result, err := p.Extract(pack.SafeExtractAll("/tmp/output"))
type ExtractResult ¶
type ExtractResult struct {
// Extracted is the list of file paths that were extracted.
Extracted []string
}
ExtractResult contains information about extracted artifacts.
type Manifest ¶
Type aliases for backwards compatibility. These allow existing code using pack.Manifest, pack.Artifact, etc. to continue working.
func ParseManifest ¶
ParseManifest parses and validates manifest JSON with strict decoding.
Validation includes:
- Required field checks (spec_version, stream, pack_digest, etc.)
- Spec version compatibility
- Timestamp format validation (YYYY-MM-DDTHH:MM:SSZ)
- Artifact path safety (no traversal, Windows collision detection)
- Digest format validation
- Size range checks (non-negative, within limits)
SECURITY: This is the primary entrypoint for manifest parsing. All manifest bytes MUST pass through this function before being trusted.
type Pack ¶
type Pack struct {
// contains filtered or unexported fields
}
Pack represents an evidence pack loaded from a zip archive, containing the manifest and indexed files.
Pack is safe for concurrent read operations.
func Open ¶
Open loads an evidence pack from the specified file path, validating its structure and manifest.
SECURITY: Uses SafeReader to validate ZIP structure before processing: - Entry count limits (DoS prevention) - Compression ratio limits (zip bomb detection) - Path safety (traversal, encoding, reserved names) - Windows path collision detection
func (*Pack) Close ¶
Close releases resources associated with the pack. Close is not safe to call concurrently with active read operations.
func (*Pack) Extract ¶
func (p *Pack) Extract(opts ExtractOptions) (*ExtractResult, error)
Extract extracts artifacts from the pack to the filesystem.
The extraction is performed safely:
- Path traversal attacks are rejected
- Symlinks in the output path are rejected
- Directory creation is race-safe (fd-based on Unix)
- File writes use O_NOFOLLOW to prevent symlink attacks
- Per-operation read budget prevents DoS via decompression bombs
- Pack integrity verified before extraction (unless SkipPreVerification is set)
By default, VerifyIntegrity() is called before extraction to ensure pack_digest matches the canonical artifact list. This prevents attacks where an attacker injects extra artifacts not in the original manifest. Set SkipPreVerification=true only if you've already verified the pack.
func (*Pack) ListAttestations ¶
ListAttestations returns a sorted list of attestation file paths. Attestations are files in the attestations/ directory ending with .sigstore.json.
func (*Pack) Manifest ¶
Manifest returns a COPY of the pack's manifest. Mutations to the returned value do not affect the pack's internal state.
func (*Pack) OpenArtifact ¶
func (p *Pack) OpenArtifact(path string) (io.ReadCloser, error)
OpenArtifact returns a reader that verifies the artifact digest on Close(). This is useful for streaming large artifacts without loading them entirely into memory, while still ensuring integrity.
IMPORTANT: The digest is verified when Close() is called. If you don't read all bytes before closing, truncation attacks won't be detected. Always read to EOF before closing, or use ReadArtifact for smaller artifacts.
The returned reader enforces per-artifact size limits. For pack-wide limits, use OpenArtifactWithBudget.
func (*Pack) OpenArtifactWithBudget ¶
func (p *Pack) OpenArtifactWithBudget(path string, budget *ReadBudget) (io.ReadCloser, error)
OpenArtifactWithBudget returns a reader that verifies digest on Close(), tracking reads against the provided budget.
IMPORTANT: See OpenArtifact for usage notes about digest verification timing.
func (*Pack) OpenFileUntrusted ¶
func (p *Pack) OpenFileUntrusted(path string) (io.ReadCloser, error)
OpenFileUntrusted returns a reader WITHOUT integrity verification. SECURITY: The returned content is UNTRUSTED - it has not been verified against any manifest digest. Use OpenArtifact for verified streaming reads. Callers must close the returned reader.
This reader enforces per-artifact size limits to prevent DoS via decompression bombs. For pack-wide limits, use OpenFileUntrustedWithBudget with a ReadBudget.
func (*Pack) OpenFileUntrustedWithBudget ¶
func (p *Pack) OpenFileUntrustedWithBudget(path string, budget *ReadBudget) (io.ReadCloser, error)
OpenFileUntrustedWithBudget returns a reader WITHOUT integrity verification, tracking reads against the provided budget. SECURITY: The returned content is UNTRUSTED - see OpenFileUntrusted for details. Use OpenArtifactWithBudget for verified streaming reads with budget tracking. Callers must close the returned reader.
If budget is nil, only per-artifact limits are enforced.
func (*Pack) ReadArtifact ¶
ReadArtifact reads an artifact and verifies its digest and size against the manifest.
func (*Pack) ReadArtifactTo ¶
ReadArtifactTo streams an artifact to a writer with integrity verification. This is the recommended method for processing large artifacts without loading them entirely into memory.
The artifact digest is verified after all bytes are written. If verification fails, an error is returned. The caller should handle this by discarding any output already written (e.g., by truncating a file or discarding a buffer).
Example:
f, _ := os.Create("output.json")
defer f.Close()
n, err := p.ReadArtifactTo(f, "artifacts/data.json")
if err != nil {
os.Remove("output.json") // Discard corrupted output
return err
}
func (*Pack) ReadArtifactWithBudget ¶
func (p *Pack) ReadArtifactWithBudget(path string, budget *ReadBudget) ([]byte, error)
ReadArtifactWithBudget reads an artifact with integrity verification, tracking reads against the provided budget.
If budget is nil, only per-artifact limits are enforced.
func (*Pack) ReadAttestation ¶
ReadAttestation reads and returns the contents of an attestation file. Attestations are not integrity-verified since they are not in the manifest. Enforces MaxAttestationSizeBytes limit (1 MB) to prevent memory DoS attacks.
func (*Pack) ReadFileUntrusted ¶
ReadFileUntrusted reads raw file bytes WITHOUT integrity verification. SECURITY: The returned content is UNTRUSTED - it has not been verified against any manifest digest. Use ReadArtifact for verified reads of manifest-declared artifacts. This is useful for attestations and other non-artifact files where the caller will perform their own verification (e.g., Sigstore signature verification).
func (*Pack) ReadFileUntrustedWithBudget ¶
func (p *Pack) ReadFileUntrustedWithBudget(path string, budget *ReadBudget) ([]byte, error)
ReadFileUntrustedWithBudget reads raw file bytes WITHOUT integrity verification, tracking reads against the provided budget. SECURITY: The returned content is UNTRUSTED - see ReadFileUntrusted for details.
If budget is nil, only per-artifact limits are enforced.
func (*Pack) VerifyAllArtifacts ¶
VerifyAllArtifacts verifies all embedded artifact digests and sizes. Enforces aggregate size budget.
SECURITY: This is a low-level function that only verifies individual artifact integrity. It does NOT verify pack_digest, which ensures manifest-level coverage. Use VerifyIntegrity() for complete verification including pack_digest.
Only use this directly when:
- You've already verified pack_digest separately, OR
- You're implementing custom verification logic that handles pack_digest elsewhere
In most cases, prefer VerifyIntegrity() which calls both this and VerifyPackDigest().
func (*Pack) VerifyAllAttestations ¶
func (p *Pack) VerifyAllAttestations(ctx context.Context, v verify.Verifier) (map[string]*verify.Result, error)
VerifyAllAttestations verifies all attestations in the pack. Returns a map of path to result.
SECURITY: If any attestation fails verification, returns nil results with an error. This "fail closed" design prevents callers from accidentally using partial results when some attestations failed. Callers who need individual attestation verification should use VerifyAttestation directly.
func (*Pack) VerifyAttestation ¶
func (p *Pack) VerifyAttestation(ctx context.Context, path string, v verify.Verifier) (*verify.Result, error)
VerifyAttestation verifies a specific attestation against the pack. Performs integrity check, signature verification, and statement semantic validation.
func (*Pack) VerifyEmbeddedAttestations ¶
func (p *Pack) VerifyEmbeddedAttestations(ctx context.Context, v verify.Verifier) ([]EmbeddedVerifyResult, error)
VerifyEmbeddedAttestations verifies all embedded attestations in a merged pack's provenance. Returns results for each embedded attestation across all source packs. For non-merged packs, returns nil with no error.
SECURITY: This function verifies pack integrity first to ensure artifacts haven't been tampered with. Without this check, valid embedded attestations could be returned for a pack with modified artifact contents.
func (*Pack) VerifyIntegrity ¶
VerifyIntegrity verifies complete pack integrity: artifact digests, sizes, and pack_digest.
This is the primary integrity verification API. It ensures:
- All embedded artifacts have correct digests and sizes
- The pack_digest matches the canonical artifact list hash
- Aggregate read budget is not exceeded (DoS prevention)
SECURITY: This is the recommended verification entrypoint. Using VerifyAllArtifacts or VerifyPackDigest individually risks partial verification.
func (*Pack) VerifyPackDigest ¶
VerifyPackDigest verifies pack_digest matches the canonical artifact list hash. Does not verify artifact file contents; use VerifyAllArtifacts for that. SECURITY: Uses constant-time comparison via digest.Equal to prevent timing attacks.
type Provenance ¶
type Provenance = packspec.Provenance
Type aliases for backwards compatibility. These allow existing code using pack.Manifest, pack.Artifact, etc. to continue working.
type ReadBudget ¶
type ReadBudget struct {
// contains filtered or unexported fields
}
ReadBudget tracks cumulative bytes read during an operation to prevent DoS attacks. Create a new ReadBudget for each logical operation (e.g., Extract, Verify). ReadBudget is safe for concurrent use within a single operation.
SECURITY: Each operation should have its own budget to prevent:
- A prior operation's reads from exhausting the budget for subsequent operations
- Long-running processes hitting cumulative limits that make the Pack unusable
Example:
budget := pack.NewReadBudget()
data, err := p.ReadArtifactWithBudget("artifacts/file.json", budget)
func NewReadBudget ¶
func NewReadBudget() *ReadBudget
NewReadBudget creates a new per-operation read budget with the default pack-wide limit.
func NewReadBudgetWithLimit ¶
func NewReadBudgetWithLimit(maxBytes int64) *ReadBudget
NewReadBudgetWithLimit creates a new per-operation read budget with a custom limit.
func (*ReadBudget) BytesRead ¶
func (b *ReadBudget) BytesRead() int64
BytesRead returns the number of bytes read so far.
func (*ReadBudget) Remaining ¶
func (b *ReadBudget) Remaining() int64
Remaining returns the number of bytes remaining in the budget.
type Source ¶
Type aliases for backwards compatibility. These allow existing code using pack.Manifest, pack.Artifact, etc. to continue working.
type SourcePack ¶
type SourcePack = packspec.SourcePack
Type aliases for backwards compatibility. These allow existing code using pack.Manifest, pack.Artifact, etc. to continue working.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package builder creates evidence packs.
|
Package builder creates evidence packs. |
|
Package diff provides comparison utilities for evidence packs.
|
Package diff provides comparison utilities for evidence packs. |
|
Package merge combines multiple evidence packs into a single merged pack.
|
Package merge combines multiple evidence packs into a single merged pack. |
|
Package verify validates Sigstore attestations in evidence packs.
|
Package verify validates Sigstore attestations in evidence packs. |