From b00294f61a971a2c484cc2613eafc0bb1231f5ef Mon Sep 17 00:00:00 2001 From: Sergei Zharinov <zharinov@users.noreply.github.com> Date: Fri, 13 Jan 2023 08:54:01 +0300 Subject: [PATCH] fix(datasource/docker): Validate digest value before calling API (#19780) --- lib/modules/datasource/docker/index.spec.ts | 28 ++++++++++++++------- lib/modules/datasource/docker/index.ts | 3 ++- lib/util/string.ts | 4 +++ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/lib/modules/datasource/docker/index.spec.ts b/lib/modules/datasource/docker/index.spec.ts index 5ccae2c3af..1c2026fc88 100644 --- a/lib/modules/datasource/docker/index.spec.ts +++ b/lib/modules/datasource/docker/index.spec.ts @@ -781,7 +781,8 @@ describe('modules/datasource/docker/index', () => { }); it('supports architecture-specific digest in OCI manifests with media type', async () => { - const currentDigest = 'some-image-digest'; + const currentDigest = + 'sha256:0101010101010101010101010101010101010101010101010101010101010101'; httpMock .scope(authUrl) @@ -855,7 +856,8 @@ describe('modules/datasource/docker/index', () => { }); it('supports architecture-specific digest in OCI manifests without media type', async () => { - const currentDigest = 'some-image-digest'; + const currentDigest = + 'sha256:0101010101010101010101010101010101010101010101010101010101010101'; httpMock .scope(authUrl) @@ -1005,7 +1007,8 @@ describe('modules/datasource/docker/index', () => { }); it('handles error while retrieving image config blob', async () => { - const currentDigest = 'some-image-digest'; + const currentDigest = + 'sha256:0101010101010101010101010101010101010101010101010101010101010101'; httpMock .scope(authUrl) @@ -1058,24 +1061,31 @@ describe('modules/datasource/docker/index', () => { .scope(baseUrl) .get('/', undefined, { badheaders: ['authorization'] }) .reply(200, { token: 'some-token' }) - .head('/library/some-dep/manifests/some-digest') + .head( + '/library/some-dep/manifests/sha256:0101010101010101010101010101010101010101010101010101010101010101' + ) .reply(404, {}); httpMock .scope(baseUrl) .get('/', undefined, { badheaders: ['authorization'] }) .reply(200, '', {}) - .head('/library/some-dep/manifests/some-new-value', undefined, { - badheaders: ['authorization'], - }) + .head( + '/library/some-dep/manifests/sha256:fafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafa', + undefined, + { + badheaders: ['authorization'], + } + ) .reply(401); const res = await getDigest( { datasource: 'docker', depName: 'some-dep', - currentDigest: 'some-digest', + currentDigest: + 'sha256:0101010101010101010101010101010101010101010101010101010101010101', }, - 'some-new-value' + 'sha256:fafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafa' ); expect(res).toBeNull(); }); diff --git a/lib/modules/datasource/docker/index.ts b/lib/modules/datasource/docker/index.ts index 49c98a3802..4e8127e604 100644 --- a/lib/modules/datasource/docker/index.ts +++ b/lib/modules/datasource/docker/index.ts @@ -22,6 +22,7 @@ import type { import { hasKey } from '../../../util/object'; import { regEx } from '../../../util/regex'; import { addSecretForSanitizing } from '../../../util/sanitize'; +import { isDockerDigest } from '../../../util/string'; import { ensurePathPrefix, ensureTrailingSlash, @@ -1018,7 +1019,7 @@ export class DockerDatasource extends Datasource { let digest: string | null = null; try { let architecture: string | null | undefined = null; - if (currentDigest) { + if (currentDigest && isDockerDigest(currentDigest)) { architecture = await this.getImageArchitecture( registryHost, dockerRepository, diff --git a/lib/util/string.ts b/lib/util/string.ts index 4b085d07cb..2ef7ae661d 100644 --- a/lib/util/string.ts +++ b/lib/util/string.ts @@ -55,3 +55,7 @@ export function looseEquals( } return a.localeCompare(b, undefined, { sensitivity: 'base' }) === 0; } + +export function isDockerDigest(input: string): boolean { + return /^sha256:[a-f0-9]{64}$/i.test(input); +} -- GitLab