@@ -120,13 +120,14 @@ analyzeFromDockerArchive systemDepsOnly filters withoutDefaultFilters tarball =
120
120
121
121
-- Analyze Base Layer
122
122
logInfo " Analyzing Base Layer"
123
- baseFs <- context " Building base layer FS" $ mkFsFromChangeset $ baseLayer image
124
123
let imageBaseLayer = baseLayer image
125
124
baseDigest = layerDigest imageBaseLayer
126
- osInfo <-
127
- context " Retrieving OS Information"
128
- . warnThenRecover @ Text " Could not retrieve OS info"
129
- $ runTarballReadFSIO baseFs tarball getOsInfo
125
+ baseFs <- context " Building Base Layer FS" $ mkFsFromChangeset $ baseLayer image
126
+ layersFs <-
127
+ if hasOtherLayers image
128
+ then pure <$> context " Building Other Layers FS" (mkFsFromChangeset (otherLayersSquashed image))
129
+ else pure Nothing
130
+ osInfo <- getOsInfoFromLayers layersFs baseFs tarball
130
131
131
132
when (isNothing osInfo) $
132
133
logInfo " No image system information detected. System dependencies will not be included with this scan."
@@ -163,11 +164,12 @@ analyzeFromDockerArchive systemDepsOnly filters withoutDefaultFilters tarball =
163
164
164
165
let baseScanImageLayer = ContainerScanImageLayer baseDigest baseUnits baseObservations
165
166
166
- if hasOtherLayers image
167
- then do
167
+ case layersFs of
168
+ Nothing -> do
169
+ pure $ mkScan [baseScanImageLayer]
170
+ Just fs -> do
168
171
logInfo " Analyzing Other Layers"
169
172
let squashedDigest = layerDigest . otherLayersSquashed $ image
170
- fs <- context " Building squashed FS from other layers" . mkFsFromChangeset $ otherLayersSquashed image
171
173
otherUnits <-
172
174
context " Analyzing from Other Layers" $
173
175
analyzeLayer systemDepsOnly filters withoutDefaultFilters capabilities osInfo fs tarball
@@ -178,7 +180,6 @@ analyzeFromDockerArchive systemDepsOnly filters withoutDefaultFilters tarball =
178
180
, ContainerScanImageLayer squashedDigest otherUnits otherObservations
179
181
]
180
182
pure scan
181
- else pure $ mkScan [baseScanImageLayer]
182
183
183
184
analyzeLayer ::
184
185
( Has Diagnostics sig m
@@ -338,17 +339,20 @@ listTargetsFromDockerArchive tarball = do
338
339
logWarn " fossa container list-targets only lists targets for experimental-scanner (when analyzed with --experimental-scanner flag)."
339
340
340
341
logInfo " Analyzing Base Layer"
341
- baseFs <- context " Building Base Layer FS" $ mkFsFromChangeset $ baseLayer image
342
- osInfo <-
343
- context " Retrieving OS Information"
344
- . warnThenRecover @ Text " Could not retrieve OS info"
345
- $ runTarballReadFSIO baseFs tarball getOsInfo
342
+
343
+ baseFs <- mkFsFromChangeset $ baseLayer image
344
+ layersFs <-
345
+ if hasOtherLayers image
346
+ then pure <$> context " Building squashed FS from other layers" (mkFsFromChangeset $ otherLayersSquashed image)
347
+ else pure Nothing
348
+ osInfo <- getOsInfoFromLayers layersFs baseFs tarball
349
+
346
350
context " Analyzing From Base Layer" $ listTargetLayer capabilities osInfo baseFs tarball " Base Layer"
347
351
348
- when (hasOtherLayers image) $ do
349
- logInfo " Analyzing Other Layers "
350
- fs <- context " Building squashed FS from other layers " $ mkFsFromChangeset $ otherLayersSquashed image
351
- void . context " Analyzing from Other Layers" $ listTargetLayer capabilities osInfo fs tarball " Other Layers"
352
+ case layersFs of
353
+ Nothing -> pure ()
354
+ Just fs -> do
355
+ void . context " Analyzing from Other Layers" $ listTargetLayer capabilities osInfo fs tarball " Other Layers"
352
356
353
357
listTargetLayer ::
354
358
( Has Diagnostics sig m
@@ -384,3 +388,25 @@ listTargetLayer capabilities osInfo layerFs tarball layerType = do
384
388
run = traverse_ findTargets $ layerAnalyzers osInfo False
385
389
findTargets (DiscoverFunc f) = withDiscoveredProjects f basedir (renderLayerTarget basedir layerType)
386
390
basedir = Path $ toString fixedVfsRoot
391
+
392
+ -- | Retrieves OS information from the layers of a Docker image.
393
+ -- It first checks the squashed layers, then the base layer.
394
+ -- This is because layers are squashed in the order they are applied,
395
+ -- so the last layer is the one that should have the most accurate OS info.
396
+ getOsInfoFromLayers ::
397
+ ( Has Diagnostics sig m
398
+ , Has (Lift IO ) sig m
399
+ ) =>
400
+ Maybe (SomeFileTree TarEntryOffset ) ->
401
+ SomeFileTree TarEntryOffset ->
402
+ Path Abs File ->
403
+ m (Maybe OsInfo )
404
+ getOsInfoFromLayers layersFs baseFs tarball =
405
+ context " Retrieving OS Information" $ do
406
+ layersFSOsInfo <- case layersFs of
407
+ Just fs -> warnThenRecover @ Text " Could not retrieve OS info from other layers, falling back to base layer." $ runTarballReadFSIO fs tarball getOsInfo
408
+ Nothing -> pure Nothing
409
+ if isNothing layersFSOsInfo
410
+ then do
411
+ warnThenRecover @ Text " Could not retrieve OS info from base layer" $ runTarballReadFSIO baseFs tarball getOsInfo
412
+ else pure layersFSOsInfo
0 commit comments