Skip to content

Commit 31e31cc

Browse files
committed
fix: restore digest validation
1 parent 6cff33c commit 31e31cc

File tree

2 files changed

+41
-9
lines changed

2 files changed

+41
-9
lines changed

lib/extractor/oci-distribution-metadata.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { parseImageReference } from "../image-reference";
1+
import { isValidDigest, parseImageReference } from "../image-reference";
22

33
export interface OCIDistributionMetadata {
44
// Must be a valid host, including port if one was used to pull the image.
@@ -44,14 +44,7 @@ export function constructOCIDisributionMetadata({
4444
imageTag: parsed.tag,
4545
};
4646

47-
// 255 byte limit is enforced by RFC 1035.
48-
if (Buffer.byteLength(metadata.registryHost) > 255) {
49-
return;
50-
}
51-
52-
// 2048 byte limit is enforced by Snyk for platform stability.
53-
// Longer strings may be valid, but nothing close to this limit has been observed by Snyk at time of writing.
54-
if (Buffer.byteLength(metadata.repository) > 2048) {
47+
if (!ociDistributionMetadataIsValid(metadata)) {
5548
return;
5649
}
5750

@@ -60,3 +53,28 @@ export function constructOCIDisributionMetadata({
6053
return;
6154
}
6255
}
56+
57+
function ociDistributionMetadataIsValid(
58+
data: OCIDistributionMetadata,
59+
): boolean {
60+
// 255 byte limit is enforced by RFC 1035.
61+
if (Buffer.byteLength(data.registryHost) > 255) {
62+
return false;
63+
}
64+
65+
// 2048 byte limit is enforced by Snyk for platform stability.
66+
// Longer strings may be valid, but nothing close to this limit has been observed by Snyk at time of writing.
67+
if (Buffer.byteLength(data.repository) > 2048) {
68+
return false;
69+
}
70+
71+
if (!isValidDigest(data.manifestDigest)) {
72+
return false;
73+
}
74+
75+
if (data.indexDigest && !isValidDigest(data.indexDigest)) {
76+
return false;
77+
}
78+
79+
return true;
80+
}

lib/image-reference.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ const imageReferenceRegex = new RegExp(imageReferencePattern);
1313
const imageRegistryPattern = String.raw`^((?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+|\[(?:[a-fA-F0-9:]+)\]|localhost)(?::[0-9]+)?)(?:/|@)`;
1414
const imageRegistryRegex = new RegExp(imageRegistryPattern);
1515

16+
// Digest regex. Anchored to the start and end of the string.
17+
const digestPattern = String.raw`^[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][a-fA-F0-9]{32,}$`;
18+
const digestRegex = new RegExp(digestPattern);
19+
1620
export class ParsedImageReference {
1721
/** Repository path (e.g. nginx, library/nginx) */
1822
public readonly repository: string;
@@ -165,3 +169,13 @@ export function isValidImageReference(reference: string): boolean {
165169
return false;
166170
}
167171
}
172+
173+
/**
174+
* Validate a digest string.
175+
*
176+
* @param digest - Digest string to validate
177+
* @returns true if the digest is valid, false otherwise
178+
*/
179+
export function isValidDigest(digest: string): boolean {
180+
return digestRegex.test(digest);
181+
}

0 commit comments

Comments
 (0)