Skip to content

Do not process images with unprocessable layers#497

Merged
wagoodman merged 1 commit intomainfrom
unprocessable-layers
Jan 8, 2026
Merged

Do not process images with unprocessable layers#497
wagoodman merged 1 commit intomainfrom
unprocessable-layers

Conversation

@wagoodman
Copy link
Copy Markdown
Contributor

@wagoodman wagoodman commented Jan 8, 2026

Today we only check if a layer's media type is supported when we actually process that layer (downloading the contents just after that). If an image has 10 layers and the last one is unprocessable, we've already wasted time pulling and processing the first 9 layers.

This PR fixes this behavior by checking all layer media types upfront in Image.Read() before doing any real work. If any layer can't be processed, fail immediately before we pull any contents.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Jan 8, 2026

Benchmark Test Results

Benchmark results from the latest changes vs base branch
make .tool/task
make[1]: Entering directory '/home/runner/work/stereoscope/stereoscope'
make[1]: Leaving directory '/home/runner/work/stereoscope/stereoscope'
.tool/task show-benchstat
?   	github.com/anchore/stereoscope	[no test files]
?   	github.com/anchore/stereoscope/examples	[no test files]
PASS
ok  	github.com/anchore/stereoscope/internal	0.004s
?   	github.com/anchore/stereoscope/internal/bus	[no test files]
PASS
ok  	github.com/anchore/stereoscope/internal/containerd	0.007s
PASS
ok  	github.com/anchore/stereoscope/internal/docker	0.005s
?   	github.com/anchore/stereoscope/internal/log	[no test files]
PASS
ok  	github.com/anchore/stereoscope/internal/podman	0.005s
?   	github.com/anchore/stereoscope/pkg/event	[no test files]
?   	github.com/anchore/stereoscope/pkg/event/parsers	[no test files]
goos: linux
goarch: amd64
pkg: github.com/anchore/stereoscope/pkg/file
cpu: AMD EPYC 7763 64-Core Processor                
BenchmarkTarIndex-4   	   34800	     33993 ns/op	    5703 B/op	      93 allocs/op
BenchmarkTarIndex-4   	   35041	     34690 ns/op	    5701 B/op	      93 allocs/op
BenchmarkTarIndex-4   	   35272	     33877 ns/op	    5702 B/op	      93 allocs/op
BenchmarkTarIndex-4   	   35278	     34003 ns/op	    5702 B/op	      93 allocs/op
BenchmarkTarIndex-4   	   35071	     33874 ns/op	    5703 B/op	      93 allocs/op
BenchmarkTarIndex-4   	   35192	     34044 ns/op	    5702 B/op	      93 allocs/op
BenchmarkTarIndex-4   	   35439	     33717 ns/op	    5701 B/op	      93 allocs/op
PASS
ok  	github.com/anchore/stereoscope/pkg/file	10.808s
PASS
ok  	github.com/anchore/stereoscope/pkg/filetree	0.005s
?   	github.com/anchore/stereoscope/pkg/filetree/filenode	[no test files]
PASS
ok  	github.com/anchore/stereoscope/pkg/image	0.005s
PASS
ok  	github.com/anchore/stereoscope/pkg/image/containerd	0.008s
PASS
ok  	github.com/anchore/stereoscope/pkg/image/docker	0.005s
PASS
ok  	github.com/anchore/stereoscope/pkg/image/oci	0.005s
PASS
ok  	github.com/anchore/stereoscope/pkg/image/oci/credhelpers	0.006s
?   	github.com/anchore/stereoscope/pkg/image/podman	[no test files]
PASS
ok  	github.com/anchore/stereoscope/pkg/image/sif	0.004s
?   	github.com/anchore/stereoscope/pkg/imagetest	[no test files]
PASS
ok  	github.com/anchore/stereoscope/pkg/tree	0.004s
PASS
ok  	github.com/anchore/stereoscope/pkg/tree/node	0.003s
goos: linux
goarch: amd64
pkg: github.com/anchore/stereoscope/test/integration
cpu: AMD EPYC 7763 64-Core Processor                
BenchmarkSimpleImage_GetImage/docker-archive-4 	    1135	   1063474 ns/op	  275679 B/op	    2257 allocs/op
BenchmarkSimpleImage_GetImage/docker-archive-4 	    1108	   1163777 ns/op	  275586 B/op	    2257 allocs/op
BenchmarkSimpleImage_GetImage/docker-archive-4 	    1102	   1076236 ns/op	  275357 B/op	    2257 allocs/op
BenchmarkSimpleImage_GetImage/docker-archive-4 	    1111	   1068711 ns/op	  275323 B/op	    2256 allocs/op
BenchmarkSimpleImage_GetImage/docker-archive-4 	    1126	   1042554 ns/op	  275248 B/op	    2256 allocs/op
BenchmarkSimpleImage_GetImage/docker-archive-4 	    1147	   1117909 ns/op	  275047 B/op	    2256 allocs/op
BenchmarkSimpleImage_GetImage/docker-archive-4 	    1111	   1163162 ns/op	  274888 B/op	    2256 allocs/op
--- FAIL: BenchmarkSimpleImage_GetImage/podman
    fixture_image_simple_test.go:175: could not get fixture image: unable to detect input for 'stereoscope-fixture-image-simple:04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7', errs: podman not available: no host address
#0 building with "default" instance using docker driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 345B done
#1 DONE 0.0s

#2 [internal] load .dockerignore
#2 transferring context: 2B done
#2 DONE 0.0s

#3 [internal] load build context
#3 transferring context: 209B done
#3 DONE 0.0s

#4 [1/3] ADD file-1.txt /somefile-1.txt
#4 CACHED

#5 [2/3] ADD file-2.txt /somefile-2.txt
#5 CACHED

#6 [3/3] ADD target /
#6 CACHED

#7 exporting to image
#7 exporting layers done
#7 writing image sha256:6b99afec3a94eba68b9e7890168c63c8886a6ee2e64e023a753d7a9f4285371f done
#7 naming to docker.io/library/stereoscope-fixture-image-simple:04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7 done
#7 naming to docker.io/library/stereoscope-fixture-image-simple:latest done
#7 DONE 0.0s
time="2026-01-08T18:32:06Z" level=warning msg="Failed to check deprecations" error="connection error: desc = \"transport: Error while dialing: dial unix /run/containerd/containerd.sock: connect: permission denied\""
ctr: connection error: desc = "transport: Error while dialing: dial unix /run/containerd/containerd.sock: connect: permission denied"
--- FAIL: BenchmarkSimpleImage_GetImage
    image_fixtures.go:193: using existing image tar: 'test-fixtures/cache/stereoscope-fixture-image-simple-04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7.tar' (size: 22528, modified: 2026-01-08 18:31:17.04653699 +0000 UTC, mode: -rw-r--r--)
    image_fixtures.go:241: Build docker image: name="stereoscope-fixture-image-simple" tag="04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7"
    image_fixtures.go:291: saveImage running: docker image save stereoscope-fixture-image-simple:04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7
    image_fixtures.go:286: 
        	Error Trace:	/home/runner/work/stereoscope/stereoscope/pkg/imagetest/image_fixtures.go:286
        	            				/home/runner/work/stereoscope/stereoscope/pkg/imagetest/image_fixtures.go:162
        	            				/home/runner/work/stereoscope/stereoscope/pkg/imagetest/image_fixtures.go:152
        	            				/home/runner/work/stereoscope/stereoscope/pkg/imagetest/image_fixtures.go:33
        	            				/home/runner/work/stereoscope/stereoscope/test/integration/fixture_image_simple_test.go:163
        	            				/opt/hostedtoolcache/go/1.25.5/x64/src/testing/benchmark.go:245
        	            				/opt/hostedtoolcache/go/1.25.5/x64/src/runtime/asm_amd64.s:1693
        	Error:      	Received unexpected error:
        	            	exit status 1
        	Test:       	BenchmarkSimpleImage_GetImage
        	Messages:   	could not import docker image to containerd (shell out)
BenchmarkSimpleImage_FetchSquashedContents/docker-archive-4         	   61426	     19514 ns/op	    2616 B/op	      18 allocs/op
BenchmarkSimpleImage_FetchSquashedContents/docker-archive-4         	   60613	     19714 ns/op	    2616 B/op	      18 allocs/op
BenchmarkSimpleImage_FetchSquashedContents/docker-archive-4         	   60774	     19764 ns/op	    2616 B/op	      18 allocs/op
BenchmarkSimpleImage_FetchSquashedContents/docker-archive-4         	   60672	     19692 ns/op	    2616 B/op	      18 allocs/op
BenchmarkSimpleImage_FetchSquashedContents/docker-archive-4         	   61330	     19545 ns/op	    2616 B/op	      18 allocs/op
BenchmarkSimpleImage_FetchSquashedContents/docker-archive-4         	   60901	     19591 ns/op	    2616 B/op	      18 allocs/op
BenchmarkSimpleImage_FetchSquashedContents/docker-archive-4         	   60723	     19682 ns/op	    2616 B/op	      18 allocs/op
--- FAIL: BenchmarkSimpleImage_FetchSquashedContents
    image_fixtures.go:193: using existing image tar: 'test-fixtures/cache/stereoscope-fixture-image-simple-04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7.tar' (size: 22528, modified: 2026-01-08 18:31:17.04653699 +0000 UTC, mode: -rw-r--r--)
    image_fixtures.go:75: error getting fixture image: 'podman' 'image-simple' with request 'podman:stereoscope-fixture-image-simple:04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7': unable to detect input for 'stereoscope-fixture-image-simple:04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7', errs: podman not available: no host address
FAIL
exit status 1
FAIL	github.com/anchore/stereoscope/test/integration	19.899s
?   	github.com/anchore/stereoscope/test/integration/test-fixtures/registry	[no test files]
FAIL
goos: linux
goarch: amd64
pkg: github.com/anchore/stereoscope/pkg/file
cpu: AMD EPYC 7763 64-Core Processor                
ctr: 
           │ .tmp/benchmark-0fefacc.txt │
           │           sec/op           │
TarIndex-4                  33.99µ ± 2%

           │ .tmp/benchmark-0fefacc.txt │
           │            B/op            │
TarIndex-4                 5.568Ki ± 0%

           │ .tmp/benchmark-0fefacc.txt │
           │         allocs/op          │
TarIndex-4                   93.00 ± 0%

pkg: github.com/anchore/stereoscope/test/integration
                                      │ .tmp/benchmark-0fefacc.txt │
                                      │           sec/op           │
SimpleImage_GetImage/docker-archive-4                  1.076m ± 8%

                                      │ .tmp/benchmark-0fefacc.txt │
                                      │            B/op            │
SimpleImage_GetImage/docker-archive-4                 268.9Ki ± 0%

                                      │ .tmp/benchmark-0fefacc.txt │
                                      │         allocs/op          │
SimpleImage_GetImage/docker-archive-4                  2.256k ± 0%

ctr: connection error: desc = "transport: Error while dialing: dial unix /run/containerd/containerd.sock: connect: permission denied"
                                                   │ .tmp/benchmark-0fefacc.txt │
                                                   │           sec/op           │
SimpleImage_FetchSquashedContents/docker-archive-4                  19.68µ ± 1%

                                                   │ .tmp/benchmark-0fefacc.txt │
                                                   │            B/op            │
SimpleImage_FetchSquashedContents/docker-archive-4                 2.555Ki ± 0%

                                                   │ .tmp/benchmark-0fefacc.txt │
                                                   │         allocs/op          │
SimpleImage_FetchSquashedContents/docker-archive-4                   18.00 ± 0%
goos: linux
goarch: amd64
pkg: github.com/anchore/stereoscope/pkg/file
cpu: AMD EPYC 7763 64-Core Processor                
ctr: 
           │ .tmp/benchmark-0fefacc.txt │
           │           sec/op           │
TarIndex-4                  33.99µ ± 2%

           │ .tmp/benchmark-0fefacc.txt │
           │            B/op            │
TarIndex-4                 5.568Ki ± 0%

           │ .tmp/benchmark-0fefacc.txt │
           │         allocs/op          │
TarIndex-4                   93.00 ± 0%

pkg: github.com/anchore/stereoscope/test/integration
                                      │ .tmp/benchmark-0fefacc.txt │
                                      │           sec/op           │
SimpleImage_GetImage/docker-archive-4                  1.076m ± 8%

                                      │ .tmp/benchmark-0fefacc.txt │
                                      │            B/op            │
SimpleImage_GetImage/docker-archive-4                 268.9Ki ± 0%

                                      │ .tmp/benchmark-0fefacc.txt │
                                      │         allocs/op          │
SimpleImage_GetImage/docker-archive-4                  2.256k ± 0%

ctr: connection error: desc = "transport: Error while dialing: dial unix /run/containerd/containerd.sock: connect: permission denied"
                                                   │ .tmp/benchmark-0fefacc.txt │
                                                   │           sec/op           │
SimpleImage_FetchSquashedContents/docker-archive-4                  19.68µ ± 1%

                                                   │ .tmp/benchmark-0fefacc.txt │
                                                   │            B/op            │
SimpleImage_FetchSquashedContents/docker-archive-4                 2.555Ki ± 0%

                                                   │ .tmp/benchmark-0fefacc.txt │
                                                   │         allocs/op          │
SimpleImage_FetchSquashedContents/docker-archive-4                   18.00 ± 0%

@wagoodman wagoodman marked this pull request as ready for review January 8, 2026 19:34
return nil, err
}

log.WithFields("image", p.imageStr, "time", time.Since(startTime)).Info("completed downloading image")
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this makes it sound like we've pulled the image contents, but in actuality it's just the manifest (that's why this log line changed)

@wagoodman wagoodman added the bug Something isn't working label Jan 8, 2026
@wagoodman wagoodman enabled auto-merge (squash) January 8, 2026 19:51
@wagoodman wagoodman merged commit 7e5d87a into main Jan 8, 2026
7 checks passed
@wagoodman wagoodman deleted the unprocessable-layers branch January 8, 2026 23:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants