Cosign is a popular open-source tool from sigstore used for signing and verifying OCI container images. It's a trusted part of many cloud-native supply chains—including Kubernetes clusters—because it helps protect users from running tampered container images.

But in late 2023, a significant vulnerability was discovered: CVE-2023-46737. This bug lets attackers exploit how Cosign handles attestations fetched from registries, causing a Denial of Service (DoS). In this long read, we’ll break down what went wrong, show some example code, and explain how you can safeguard your pipeline.

What are Attestations?

Attestations are extra bits of metadata you attach to container images. They help describe how, where, or when an image was built. Cosign will fetch these when you run a command like cosign verify-attestation.

Where Did Cosign Go Wrong?

The core issue is a lack of limits. Inside Cosign, the function pkg/cosign.FetchAttestations loops through _all_ attestations returned by the registry, without checking how many there are. If a registry starts spitting out thousands (or more), Cosign will churn away, eating CPU and memory, possibly freezing or crashing.

An attacker who _controls_ a registry, or who can trick Cosign into talking to their registry, can return an arbitrary number of attestations in a single response. Cosign tries to process them all and, depending on the system, can become completely unresponsive.

Ability to Point Cosign at Their Registry

This could be done in a CI pipeline, through a crafted Kubernetes resource (like an AdmissionRequest in Kyverno), or in a supply chain step.

Exploit Steps:

1. Attacker creates a registry that, when asked for attestations (such as with a cosign verify-attestation call), returns an _enormous_ number of fake attestations as a single response.
2. User (or a cluster controller, such as Kyverno) tries to verify a container image from this evil registry.
3. Cosign's verification routine enters a loop, trying to process every attestation, never giving up or limiting itself.
4. System resources are consumed; processes or clusters responsible for verifying images are effectively knocked out, causing a Denial of Service for all other users.

Supply chain attack: Attacker gets their image or registry referenced by a pipeline.

- Kubernetes cluster (using Kyverno): Attacker with access to submit AdmissionRequests can reference an image in a registry they control, taking down admission webhooks.

Patch and Mitigation

The fix is pretty straightforward: _limit_ the number of attestations Cosign will process. For the vast majority of legitimate use cases, that limit can be quite low.

Fixed in Cosign 2.2.1

The patch introduces a cap when processing attestations in the vulnerable function.
If you use Cosign, update to v2.2.1 or newer immediately.

You can see the official advisory here.

Here’s a simplified snippet of the problem in pkg/cosign

// Old vulnerable code:
func FetchAttestations(ctx context.Context, ref string) ([]Attestation, error) {
    attestations, err := registry.FetchAllAttestations(ref) // returns all
    if err != nil {
        return nil, err
    }
    var results []Attestation
    for _, att := range attestations {
        // no checks on len(attestations)!
        results = append(results, att)
    }
    return results, nil
}

There’s no limit! An attacker could return 10,000 attestations, and Cosign would naively loop through all.

Patched code (in spirit)

const maxAttestations = 100 // arbitrary safe upper bound

func FetchAttestations(ctx context.Context, ref string) ([]Attestation, error) {
    attestations, err := registry.FetchAllAttestations(ref)
    if err != nil {
        return nil, err
    }
    if len(attestations) > maxAttestations {
        log.Warnf("Attestation overflow: capping at %d", maxAttestations)
        attestations = attestations[:maxAttestations]
    }
    var results []Attestation
    for _, att := range attestations {
        results = append(results, att)
    }
    return results, nil
}

How Do You Know If You’re At Risk?

- You use Cosign to sign/verify container images.
- You allow users, scripts, or CI/CD jobs to reference arbitrary image registries.

Upgrade Cosign to v2.2.1 or later.

2. Audit your infrastructure: Restrict what registries your CI/CD, admission controllers, and users can interact with.

Learn More and References

- Sigstore Cosign GitHub Advisory
- Cosign Releases
- Kyverno Announcement

The Bottom Line

CVE-2023-46737 is a classic example of how missing a simple check can spiral into a big vulnerability, especially when you’re dealing with untrusted data sources. Always cap, limit, and sanity-check anything coming from “the outside.” And keep your supply chain tools up-to-date.

Secure your pipelines.

Timeline

Published on: 11/07/2023 18:15:09 UTC
Last modified on: 11/14/2023 20:07:50 UTC