Skip to content

Commit b53a406

Browse files
fix(storage): verify manifest and config blob digests during scrub (#4212)
Signed-off-by: Artem Muterko <artem@sopho.tech>
1 parent 0dcd962 commit b53a406

2 files changed

Lines changed: 63 additions & 0 deletions

File tree

pkg/storage/scrub.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,10 @@ func CheckManifestAndConfig(
360360
return manifestDesc.Digest, ispec.Manifest{}, zerr.ErrBadManifest
361361
}
362362

363+
if err := imgStore.VerifyBlobDigestValue(imageName, manifestDesc.Digest); err != nil {
364+
return manifestDesc.Digest, ispec.Manifest{}, err
365+
}
366+
363367
configContent, err := imgStore.GetBlobContent(imageName, manifest.Config.Digest)
364368
if err != nil {
365369
return manifest.Config.Digest, ispec.Manifest{}, err
@@ -372,6 +376,10 @@ func CheckManifestAndConfig(
372376
return manifest.Config.Digest, ispec.Manifest{}, zerr.ErrBadConfig
373377
}
374378

379+
if err := imgStore.VerifyBlobDigestValue(imageName, manifest.Config.Digest); err != nil {
380+
return manifest.Config.Digest, ispec.Manifest{}, err
381+
}
382+
375383
return "", manifest, nil
376384
}
377385

pkg/storage/scrub_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,61 @@ func TestAzureCheckAllBlobsIntegrity(t *testing.T) {
136136
})
137137
}
138138

139+
func TestScrubDetectsCorruptedConfigContent(t *testing.T) {
140+
Convey("scrub detects config corruption that stays valid JSON", t, func() {
141+
tdir := t.TempDir()
142+
log := log.NewTestLogger()
143+
metrics := monitoring.NewMetricsServer(false, log)
144+
145+
defer metrics.Stop()
146+
147+
cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{
148+
RootDir: tdir,
149+
Name: "cache",
150+
UseRelPaths: true,
151+
}, log)
152+
driver := local.New(true)
153+
imgStore := local.NewImageStore(tdir, true, true, log, metrics, nil, cacheDriver, nil, nil)
154+
155+
err := imgStore.InitRepo(context.Background(), repoName)
156+
So(err, ShouldBeNil)
157+
158+
storeCtlr := storage.StoreController{}
159+
storeCtlr.DefaultStore = imgStore
160+
161+
image := CreateRandomImage()
162+
163+
err = WriteImageToFileSystem(image, repoName, tag, storeCtlr)
164+
So(err, ShouldBeNil)
165+
166+
// corrupt the config blob on disk while keeping it valid JSON so its
167+
// stored bytes no longer hash to the config digest
168+
corruptedConfig := image.Config
169+
corruptedConfig.Architecture += "-corrupted"
170+
171+
corruptedContent, err := json.Marshal(corruptedConfig)
172+
So(err, ShouldBeNil)
173+
174+
var stillValidJSON ispec.Image
175+
So(json.Unmarshal(corruptedContent, &stillValidJSON), ShouldBeNil)
176+
177+
configDig := image.ConfigDescriptor.Digest.Encoded()
178+
configFile := path.Join(imgStore.RootDir(), repoName, "/blobs/sha256", configDig)
179+
_, err = driver.WriteFile(configFile, corruptedContent)
180+
So(err, ShouldBeNil)
181+
182+
buff := bytes.NewBufferString("")
183+
184+
res, err := storeCtlr.CheckAllBlobsIntegrity(context.Background())
185+
res.PrintScrubResults(buff)
186+
So(err, ShouldBeNil)
187+
188+
space := regexp.MustCompile(`\s+`)
189+
actual := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
190+
So(actual, ShouldContainSubstring, fmt.Sprintf("test 1.0 affected %s bad blob digest", configDig))
191+
})
192+
}
193+
139194
func RunCheckAllBlobsIntegrityTests( //nolint: thelper
140195
t *testing.T, imgStore storageTypes.ImageStore, driver storageTypes.Driver, log log.Logger,
141196
) {

0 commit comments

Comments
 (0)