Skip to content

OCI Artifacts in *ARTIFACT_OUTPUTS are not signed #1575

@bradbeck

Description

@bradbeck

Analysis produced from the following Copilot prompt:

Currently Tekton Chains does not appear to sign an OCI artifact even though it is included in an appropriate ARTIFACT_OUTPUTS with isBuildArtifact set to "true".
Can you explain what the cause of the artfact not being signed.

Root Cause

The OCIArtifact.ExtractObjects() method only recognizes specific result naming patterns and does NOT support the *ARTIFACT_OUTPUTS type-hint.

What OCIArtifact.ExtractObjects() Currently Looks For

The ExtractOCIImagesFromResults() function (called by OCIArtifact) only extracts images from:

  1. *IMAGE_URL / *IMAGE_DIGEST pair - Results with suffixes IMAGE_URL and IMAGE_DIGEST

    • Example: image1_IMAGE_URL + image1_IMAGE_DIGEST
  2. IMAGES result - A comma-separated string of images in format repo@sha256:digest

    • Example: gcr.io/foo/bar@sha256:abc123

What's Missing

The ExtractOCIImagesFromResults() function completely ignores results with the *ARTIFACT_OUTPUTS suffix, even when they have:

  • A valid uri field
  • A valid digest field
  • isBuildArtifact: "true"

The Code Evidence

From pkg/artifacts/signable.go:

func ExtractOCIImagesFromResults(ctx context.Context, results []objects.Result) []interface{} {
    logger := logging.FromContext(ctx)
    objs := []interface{}{}

    // Only looks for IMAGE_URL/IMAGE_DIGEST pairs
    extractor := structuredSignableExtractor{
        uriSuffix:    OCIImageURLResultName,      // "IMAGE_URL"
        digestSuffix: OCIImageDigestResultName,   // "IMAGE_DIGEST"
        isValid:      hasImageRequirements,
    }
    for _, s := range extractor.extract(ctx, results) {
        // Process IMAGE_URL/IMAGE_DIGEST pairs
    }

    // Only looks for IMAGES result
    for _, key := range results {
        if key.Name != OCIImagesResultName {  // Only "IMAGES"
            continue
        }
        // Process IMAGES result
    }

    return objs
}

Notice: There is NO code path that processes *ARTIFACT_OUTPUTS results.

The Disconnect

While the SLSA provenance generation code (in pkg/chains/formats/slsa/extract/extract.go) properly extracts artifacts from *ARTIFACT_OUTPUTS results for provenance subjects, the OCI signing code does not. This creates an asymmetry:

  • Provenance: *ARTIFACT_OUTPUTS artifacts are included in SLSA provenance subjects
  • Signing: *ARTIFACT_OUTPUTS artifacts are NOT extracted for OCI signing

Solution

The ExtractOCIImagesFromResults() function needs to be enhanced to also extract and sign OCI artifacts from *ARTIFACT_OUTPUTS results. This would involve:

  1. Adding support for *ARTIFACT_OUTPUTS result type-hint in ExtractOCIImagesFromResults()
  2. Checking for the isBuildArtifact: "true" flag (or processing all *ARTIFACT_OUTPUTS results)
  3. Extracting the uri and digest fields just like the SLSA provenance extraction does

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions