Reapply "Add OCI image support to Linux scanner (#1708)" (#1716)#1717
Open
jasonpaulos wants to merge 1 commit intomainfrom
Open
Reapply "Add OCI image support to Linux scanner (#1708)" (#1716)#1717jasonpaulos wants to merge 1 commit intomainfrom
jasonpaulos wants to merge 1 commit intomainfrom
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Reapplies OCI image support for the Linux container detector by allowing --DockerImagesToScan inputs to reference OCI layout directories and OCI archive tarballs, running Syft against those sources, and mapping detected packages back to image layers.
Changes:
- Add
ImageReferenceparsing (Docker image vsoci-dir:/oci-archive:) and updateLinuxContainerDetectorto resolve/scan local OCI inputs via Syft volume binds. - Extend
ILinuxScanner/LinuxScannerto support returning raw Syft output and processing it separately (needed to extract source metadata for OCI inputs). - Extend
IDockerService/DockerServiceto support additional bind mounts and to create emptyContainerDetailsfor non-Docker-inspect image sources; add/expand unit tests and docs.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/Microsoft.ComponentDetection.Detectors.Tests/LinuxScannerTests.cs | Updates mocks for new DockerService overload and adds tests for raw Syft output + layer mapping behavior. |
| test/Microsoft.ComponentDetection.Detectors.Tests/LinuxContainerDetectorTests.cs | Adds comprehensive OCI layout/archive detector tests (path normalization, metadata presence/absence, mixed inputs). |
| test/Microsoft.ComponentDetection.Detectors.Tests/ImageReferenceTests.cs | Adds unit tests for parsing Docker vs OCI references and validating empty-path errors. |
| src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs | Refactors to support “run Syft” vs “process Syft output” paths; adds bind support and a safe fallback when no layers are provided. |
| src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs | Implements OCI scanning flow: validate local paths, bind-mount into Syft container, extract metadata, and record components. |
| src/Microsoft.ComponentDetection.Detectors/linux/ImageReference.cs | Introduces parsing and classification of image inputs (Docker vs OCI directory/archive). |
| src/Microsoft.ComponentDetection.Detectors/linux/ILinuxScanner.cs | Adds new public methods to return raw Syft output and process it separately. |
| src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SyftSourceMetadata.cs | Adds typed model for Syft source.metadata (image ID, layers, tags, labels, etc.). |
| src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SyftSourceLayer.cs | Adds typed model for Syft source layer entries. |
| src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SourceClassExtensions.cs | Adds helper to deserialize the untyped SourceClass.Metadata into SyftSourceMetadata. |
| src/Microsoft.ComponentDetection.Contracts/IDockerService.cs | Adds container-run overload supporting bind mounts and adds GetEmptyContainerDetails(). |
| src/Microsoft.ComponentDetection.Common/DockerService.cs | Implements new IDockerService members and plumbs additional bind mounts into container creation. |
| docs/detectors/linux.md | Documents supported image input types including oci-dir: and oci-archive:. |
Comment on lines
+59
to
+80
| var path = input[OciDirPrefix.Length..]; | ||
| if (string.IsNullOrWhiteSpace(path)) | ||
| { | ||
| throw new ArgumentException($"Input with '{OciDirPrefix}' prefix must include a path.", nameof(input)); | ||
| } | ||
|
|
||
| return new ImageReference | ||
| { | ||
| OriginalInput = input, | ||
| Reference = path, | ||
| Kind = ImageReferenceKind.OciLayout, | ||
| }; | ||
| } | ||
|
|
||
| if (input.StartsWith(OciArchivePrefix, StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| var path = input[OciArchivePrefix.Length..]; | ||
| if (string.IsNullOrWhiteSpace(path)) | ||
| { | ||
| throw new ArgumentException($"Input with '{OciArchivePrefix}' prefix must include a path.", nameof(input)); | ||
| } | ||
|
|
Comment on lines
+221
to
+224
| if (additionalBinds != null) | ||
| { | ||
| binds.AddRange(additionalBinds); | ||
| } |
Comment on lines
59
to
+76
| Task<(string Stdout, string Stderr)> CreateAndRunContainerAsync(string image, IList<string> command, CancellationToken cancellationToken = default); | ||
|
|
||
| /// <summary> | ||
| /// Creates and runs a container with the given image, command, and additional volume binds. | ||
| /// </summary> | ||
| /// <param name="image">The image to run.</param> | ||
| /// <param name="command">The command to run in the container.</param> | ||
| /// <param name="additionalBinds">Additional volume bind mounts to add to the container (e.g., "/host/path:/container/path:ro").</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>A tuple of stdout and stderr from the container.</returns> | ||
| Task<(string Stdout, string Stderr)> CreateAndRunContainerAsync(string image, IList<string> command, IList<string> additionalBinds, CancellationToken cancellationToken = default); | ||
|
|
||
| /// <summary> | ||
| /// Creates an empty <see cref="ContainerDetails"/> with a unique ID assigned. | ||
| /// Used for image types where details are not obtained from Docker inspect (e.g., OCI layout images). | ||
| /// </summary> | ||
| /// <returns>A <see cref="ContainerDetails"/> with only the <see cref="ContainerDetails.Id"/> populated.</returns> | ||
| ContainerDetails GetEmptyContainerDetails(); |
Comment on lines
+35
to
+62
| /// <summary> | ||
| /// Runs the Syft scanner and returns the raw parsed output without processing components. | ||
| /// Use this when the caller needs access to the full Syft output (e.g., to extract source metadata for OCI images). | ||
| /// </summary> | ||
| /// <param name="syftSource">The source argument passed to Syft (e.g., an image hash or "oci-dir:/oci-image").</param> | ||
| /// <param name="additionalBinds">Additional volume bind mounts for the Syft container (e.g., for mounting OCI directories).</param> | ||
| /// <param name="scope">The scope for scanning the image.</param> | ||
| /// <param name="cancellationToken">A token to monitor for cancellation requests.</param> | ||
| /// <returns>A task that represents the asynchronous operation. The task result contains the parsed <see cref="SyftOutput"/>.</returns> | ||
| public Task<SyftOutput> GetSyftOutputAsync( | ||
| string syftSource, | ||
| IList<string> additionalBinds, | ||
| LinuxScannerScope scope, | ||
| CancellationToken cancellationToken = default | ||
| ); | ||
|
|
||
| /// <summary> | ||
| /// Processes parsed Syft output into layer-mapped components. | ||
| /// </summary> | ||
| /// <param name="syftOutput">The parsed Syft output.</param> | ||
| /// <param name="containerLayers">The layers to map components to.</param> | ||
| /// <param name="enabledComponentTypes">The set of component types to include in the results.</param> | ||
| /// <returns>A collection of <see cref="LayerMappedLinuxComponents"/> representing the components found and their associated layers.</returns> | ||
| public IEnumerable<LayerMappedLinuxComponents> ProcessSyftOutput( | ||
| SyftOutput syftOutput, | ||
| IEnumerable<DockerLayer> containerLayers, | ||
| ISet<ComponentType> enabledComponentTypes | ||
| ); |
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.
Reapply #1708 which was reverted in #1716