fix: adds support for OCI images with embedded attestations#760
Draft
fix: adds support for OCI images with embedded attestations#760
Conversation
987ebfb to
c3ae26e
Compare
c3ae26e to
09097f4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds fix for OCI archive extraction deadlock on images with attestation blobs
Problem
OCI archives produced by Docker Desktop with the containerd snapshotter (Docker Engine 25+) can include in-toto attestation blobs (SPDX SBOMs, SLSA provenance) alongside standard image content. These blobs are large JSON files stored in
blobs/sha256/that are not image layers, manifests, or configs.The OCI archive extractor pipes each blob to two consumers in parallel via PassThrough streams:
streamToJson(for JSON classification) andextractImageLayer(for layer extraction). WhenextractImageLayerrejects on a non-layer blob (e.g., "Invalid tar header"), the PassThrough stream is left unconsumed. For blobs exceeding the PassThrough's 16KB internal buffer, the unconsumed stream applies backpressure to the source, which pauses data flow to thejsonStreamconsumer.streamToJsonstalls waiting for data that will never arrive. ThePromise.allnever resolves, and the process hangs silently.Changes
lib/extractor/oci-archive/layer.tsAdded
.destroy()calls on PassThrough streams when their consumer rejects. Destroying the PassThrough unpipes it from the source stream, releasing backpressure and allowing the other consumer to complete.lib/extractor/decompress-maybe.tsgzipStream.write()calls in try-catch blocks to propagate synchronous errors via the transform callback instead of crashing.gzipStream.once("error", ...)handler in theflushmethod alongside the existing"end"handler, preventing the transform from hanging if gzip errors during finalization.asyncfromflush(not needed, was masking the callback pattern).test/fixtures/oci-archives/oci-with-attestations.tar(new)OCI archive fixture containing attestation blobs. The SPDX blob is deliberately sized above the threshold that triggers the deadlock without the fix.
test/lib/extractor/oci-with-attestations.spec.ts(new)Five tests covering OCI extraction with attestation blobs present: layer extraction, fallback path, platform detection, rootfs diff IDs, and layer content extraction via extract actions.
How should this be manually tested?
Detected issue in
eclipse-temurin:17-jdk-alpine, runYou should see the scanner exit, no report and the logs should state no layers were detected.
Run the same test against this branch and the results are returned as expected.