diff --git a/docs/detectors/linux.md b/docs/detectors/linux.md
index b4e1c613f..839363300 100644
--- a/docs/detectors/linux.md
+++ b/docs/detectors/linux.md
@@ -32,10 +32,6 @@ Images present on the filesystem as either an [OCI layout directory](https://spe
- For OCI image layout directories, use the prefix `oci-dir:` followed by the path to the directory, e.g. `oci-dir:/path/to/image`
- For OCI image archives (tarballs), use the prefix `oci-archive:` followed by the path to the archive file, e.g. `oci-archive:/path/to/image.tar`
-#### Docker Archives
-
-Images saved to disk via `docker save` can be referenced using the `docker-archive:` prefix followed by the path to the tarball, e.g. `docker-archive:/path/to/image.tar`.
-
### Scanner Scope
By default, this detector invokes Syft with the `all-layers` scanning scope (i.e. the Syft argument `--scope all-layers`).
diff --git a/src/Microsoft.ComponentDetection.Detectors/linux/ImageReference.cs b/src/Microsoft.ComponentDetection.Detectors/linux/ImageReference.cs
index fcb8c1c34..5ba97f9bd 100644
--- a/src/Microsoft.ComponentDetection.Detectors/linux/ImageReference.cs
+++ b/src/Microsoft.ComponentDetection.Detectors/linux/ImageReference.cs
@@ -21,11 +21,6 @@ internal enum ImageReferenceKind
/// An OCI archive (tarball) file on disk (e.g., "oci-archive:/path/to/image.tar").
///
OciArchive,
-
- ///
- /// A Docker archive (tarball) file on disk created by "docker save" (e.g., "docker-archive:/path/to/image.tar").
- ///
- DockerArchive,
}
///
@@ -35,7 +30,6 @@ internal class ImageReference
{
private const string OciDirPrefix = "oci-dir:";
private const string OciArchivePrefix = "oci-archive:";
- private const string DockerArchivePrefix = "docker-archive:";
///
/// Gets the original input string as provided by the user.
@@ -44,7 +38,7 @@ internal class ImageReference
///
/// Gets the cleaned reference string with any scheme prefix removed.
- /// For Docker images, this is lowercased. For file paths, case is preserved.
+ /// For Docker images, this is lowercased. For OCI paths, case is preserved.
///
public required string Reference { get; init; }
@@ -92,22 +86,6 @@ public static ImageReference Parse(string input)
};
}
- if (input.StartsWith(DockerArchivePrefix, StringComparison.OrdinalIgnoreCase))
- {
- var path = input[DockerArchivePrefix.Length..];
- if (string.IsNullOrWhiteSpace(path))
- {
- throw new ArgumentException($"Input with '{DockerArchivePrefix}' prefix must include a path.", nameof(input));
- }
-
- return new ImageReference
- {
- OriginalInput = input,
- Reference = path,
- Kind = ImageReferenceKind.DockerArchive,
- };
- }
-
#pragma warning disable CA1308
return new ImageReference
{
diff --git a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs
index 41d0747d0..0c762d71c 100644
--- a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs
+++ b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs
@@ -264,7 +264,6 @@ private async Task ResolveImageAsync(
break;
case ImageReferenceKind.OciLayout:
case ImageReferenceKind.OciArchive:
- case ImageReferenceKind.DockerArchive:
var fullPath = this.ValidateLocalImagePath(imageRef);
localImages.TryAdd(fullPath, imageRef.Kind);
break;
@@ -310,21 +309,16 @@ await this.dockerService.InspectImageAsync(image, cancellationToken)
}
///
- /// Validates that a local image path exists on disk. Throws a if it does not.
- /// For OCI layouts, checks for a directory. For OCI archives and Docker archives, checks for a file.
+ /// Validates that a local image path exists on disk. Throws a FileNotFoundException if it does not.
+ /// For OCI layouts, checks for a directory. For OCI archives, checks for a file.
/// Returns the full path to the local image if validation succeeds.
///
private string ValidateLocalImagePath(ImageReference imageRef)
{
var path = Path.GetFullPath(imageRef.Reference);
- var exists = imageRef.Kind switch
- {
- ImageReferenceKind.OciLayout => Directory.Exists(path),
- ImageReferenceKind.OciArchive => System.IO.File.Exists(path),
- ImageReferenceKind.DockerArchive => System.IO.File.Exists(path),
- ImageReferenceKind.DockerImage or _ => throw new InvalidOperationException(
- $"ValidateLocalImagePath does not support image kind '{imageRef.Kind}'."),
- };
+ var exists = imageRef.Kind == ImageReferenceKind.OciLayout
+ ? Directory.Exists(path)
+ : System.IO.File.Exists(path);
if (!exists)
{
@@ -415,11 +409,6 @@ private async Task ScanLocalImageAsync(
?? throw new InvalidOperationException($"Could not determine parent directory for OCI archive path '{localImagePath}'.");
syftContainerPath = $"oci-archive:{LocalImageMountPoint}/{Path.GetFileName(localImagePath)}";
break;
- case ImageReferenceKind.DockerArchive:
- hostPathToBind = Path.GetDirectoryName(localImagePath)
- ?? throw new InvalidOperationException($"Could not determine parent directory for Docker archive path '{localImagePath}'.");
- syftContainerPath = $"docker-archive:{LocalImageMountPoint}/{Path.GetFileName(localImagePath)}";
- break;
case ImageReferenceKind.DockerImage:
default:
throw new InvalidUserInputException(
diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxContainerDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxContainerDetectorTests.cs
index 823dbe395..8e68e88bf 100644
--- a/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxContainerDetectorTests.cs
+++ b/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxContainerDetectorTests.cs
@@ -1127,121 +1127,4 @@ public async Task TestLinuxContainerDetector_OciArchiveImage_DetectsComponentsAs
System.IO.File.Delete(ociArchive);
}
}
-
- [TestMethod]
- public async Task TestLinuxContainerDetector_DockerArchiveImage_DetectsComponentsAsync()
- {
- var componentRecorder = new ComponentRecorder();
-
- // Create a temp file to act as the Docker archive
- var dockerArchiveDir = Path.GetTempPath().TrimEnd(Path.DirectorySeparatorChar);
- var dockerArchiveName = "test-docker-archive-" + Guid.NewGuid().ToString("N") + ".tar";
- var dockerArchive = Path.Combine(dockerArchiveDir, dockerArchiveName);
- await System.IO.File.WriteAllBytesAsync(dockerArchive, []);
-
- try
- {
- var scanRequest = new ScanRequest(
- new DirectoryInfo(Path.GetTempPath()),
- (_, __) => false,
- this.mockLogger.Object,
- null,
- [$"docker-archive:{dockerArchive}"],
- componentRecorder
- );
-
- var syftOutputJson = """
- {
- "distro": { "id": "ubuntu", "versionID": "22.04" },
- "artifacts": [],
- "source": {
- "id": "sha256:abc",
- "name": "/local-image",
- "type": "image",
- "version": "sha256:abc",
- "metadata": {
- "userInput": "/local-image",
- "imageID": "sha256:dockerarchiveimg",
- "tags": ["myapp:v2"],
- "repoDigests": [],
- "layers": [
- { "digest": "sha256:dockerlayer1", "size": 50000 },
- { "digest": "sha256:dockerlayer2", "size": 60000 }
- ],
- "labels": {}
- }
- }
- }
- """;
- var syftOutput = SyftOutput.FromJson(syftOutputJson);
-
- this.mockSyftLinuxScanner.Setup(scanner =>
- scanner.GetSyftOutputAsync(
- It.IsAny(),
- It.IsAny>(),
- It.IsAny(),
- It.IsAny()
- )
- )
- .ReturnsAsync(syftOutput);
-
- var layerMappedComponents = new[]
- {
- new LayerMappedLinuxComponents
- {
- DockerLayer = new DockerLayer { DiffId = "sha256:dockerlayer1", LayerIndex = 0 },
- Components = [new LinuxComponent("ubuntu", "22.04", "libc6", "2.35-0ubuntu3")],
- },
- };
-
- this.mockSyftLinuxScanner.Setup(scanner =>
- scanner.ProcessSyftOutput(
- It.IsAny(),
- It.IsAny>(),
- It.IsAny>()
- )
- )
- .Returns(layerMappedComponents);
-
- var linuxContainerDetector = new LinuxContainerDetector(
- this.mockSyftLinuxScanner.Object,
- this.mockDockerService.Object,
- this.mockLinuxContainerDetectorLogger.Object
- );
-
- var scanResult = await linuxContainerDetector.ExecuteDetectorAsync(scanRequest);
-
- scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
- scanResult.ContainerDetails.Should().ContainSingle();
-
- var containerDetails = scanResult.ContainerDetails.First();
- containerDetails.ImageId.Should().Be("sha256:dockerarchiveimg");
- containerDetails.Tags.Should().ContainSingle().Which.Should().Be("myapp:v2");
-
- var detectedComponents = componentRecorder.GetDetectedComponents().ToList();
- detectedComponents.Should().ContainSingle();
- var detectedComponent = detectedComponents.First();
- detectedComponent.Component.Id.Should().Contain("libc6");
- detectedComponent.ContainerLayerIds.Keys.Should().ContainSingle();
- var containerId = detectedComponent.ContainerLayerIds.Keys.First();
- detectedComponent.ContainerLayerIds[containerId].Should().BeEquivalentTo([0]);
-
- // Verify GetSyftOutputAsync was called with docker-archive: prefix
- this.mockSyftLinuxScanner.Verify(
- scanner =>
- scanner.GetSyftOutputAsync(
- It.Is(s => s.StartsWith("docker-archive:") && s.Contains(dockerArchiveName)),
- It.Is>(binds =>
- binds.Count == 1 && binds[0].Contains(dockerArchiveDir)),
- It.IsAny(),
- It.IsAny()
- ),
- Times.Once
- );
- }
- finally
- {
- System.IO.File.Delete(dockerArchive);
- }
- }
}