From 02ba6e2143771aaefdb542c2222f40db48ef3a0b Mon Sep 17 00:00:00 2001 From: Brandon Mitchell Date: Fri, 5 Sep 2025 14:19:51 -0400 Subject: [PATCH] Descriptor size cannot be negative Signed-off-by: Brandon Mitchell --- descriptor.md | 1 + schema/content-descriptor.json | 2 +- schema/defs-descriptor.json | 5 + schema/descriptor_test.go | 186 +++++++++++++++++++++------------ 4 files changed, 125 insertions(+), 69 deletions(-) diff --git a/descriptor.md b/descriptor.md index e666853bc..6856162b3 100644 --- a/descriptor.md +++ b/descriptor.md @@ -34,6 +34,7 @@ The following fields contain the primary properties that constitute a Descriptor This REQUIRED property specifies the size, in bytes, of the raw content. This property exists so that a client will have an expected size for the content before processing. If the length of the retrieved content does not match the specified length, the content SHOULD NOT be trusted. + The size MUST NOT be negative. - **`urls`** *array of strings* diff --git a/schema/content-descriptor.json b/schema/content-descriptor.json index b2f6deeaf..a5cdcb12a 100644 --- a/schema/content-descriptor.json +++ b/schema/content-descriptor.json @@ -10,7 +10,7 @@ }, "size": { "description": "the size in bytes of the referenced object", - "$ref": "defs.json#/definitions/int64" + "$ref": "defs-descriptor.json#/definitions/size" }, "digest": { "description": "the cryptographic checksum digest of the object, in the pattern ':'", diff --git a/schema/defs-descriptor.json b/schema/defs-descriptor.json index 6d1506232..6fdc86e80 100644 --- a/schema/defs-descriptor.json +++ b/schema/defs-descriptor.json @@ -7,6 +7,11 @@ "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}$" }, + "size": { + "type": "integer", + "minimum": 0, + "maximum": 9223372036854776000 + }, "digest": { "description": "the cryptographic checksum digest of the object, in the pattern ':'", "type": "string", diff --git a/schema/descriptor_test.go b/schema/descriptor_test.go index c3bce28f7..0c8a3716e 100644 --- a/schema/descriptor_test.go +++ b/schema/descriptor_test.go @@ -38,6 +38,18 @@ func TestDescriptor(t *testing.T) { fail: false, }, + // zero length blob + { + descriptor: ` +{ + "mediaType": "application/octet-stream", + "size": 0, + "digest": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +} +`, + fail: false, + }, + // expected failure: mediaType missing { descriptor: ` @@ -236,111 +248,149 @@ func TestDescriptor(t *testing.T) { // expected success: artifactType is present and an IANA compliant value { descriptor: ` - { - "mediaType": "application/vnd.oci.image.manifest.v1+json", - "artifactType": "application/vnd.oci.image.manifest.v1+json", - "size": 7682, - "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" - } - `, +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "artifactType": "application/vnd.oci.image.manifest.v1+json", + "size": 7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, fail: false, }, // expected failure: artifactType does not match pattern (invalid first subtype character) { descriptor: ` - { - "mediaType": "application/vnd.oci.image.manifest.v1+json", - "artifactType": "foo/.bar", - "size": 7682, - "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" - } - `, +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "artifactType": "foo/.bar", + "size": 7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +} +`, fail: true, }, // expected success: data field is present and has base64 content { descriptor: ` - { - "mediaType": "text/plain", - "size": 34, - "data": "aHR0cHM6Ly9naXRodWIuY29tL29wZW5jb250YWluZXJzCg==", - "digest": "sha256:2690af59371e9eca9453dc29882643f46e5ca47ec2862bd517b5e17351325153" - } - `, +{ + "mediaType": "text/plain", + "size": 34, + "data": "aHR0cHM6Ly9naXRodWIuY29tL29wZW5jb250YWluZXJzCg==", + "digest": "sha256:2690af59371e9eca9453dc29882643f46e5ca47ec2862bd517b5e17351325153" +} +`, fail: false, }, + // expected success: test for alternate digest algorithm { - descriptor: `{ - "mediaType": "application/vnd.oci.image.config.v1+json", - "size": 1470, - "digest": "sha256+b64:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.config.v1+json", + "size": 1470, + "digest": "sha256+b64:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" }`, + fail: false, }, + + // expected success: test for alternate digest algorithm { - descriptor: `{ - "mediaType": "application/vnd.oci.image.config.v1+json", - "size": 1470, - "digest": "sha256+b64:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" - }`, + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.config.v1+json", + "size": 1470, + "digest": "sha256+b64:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" +}`, + fail: false, }, + + // expected success: test for alternate digest algorithm { - descriptor: `{ - "mediaType": "application/vnd.oci.image.config.v1+json", - "size": 1470, - "digest": "sha256+foo-bar:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" - }`, + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.config.v1+json", + "size": 1470, + "digest": "sha256+foo-bar:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" +}`, + fail: false, }, + + // expected success: test for alternate digest algorithm { descriptor: ` - { - "mediaType": "application/vnd.oci.image.config.v1+json", - "size": 1470, - "digest": "sha256.foo-bar:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" - }`, +{ + "mediaType": "application/vnd.oci.image.config.v1+json", + "size": 1470, + "digest": "sha256.foo-bar:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" +}`, + fail: false, }, + + // expected success: test for alternate digest algorithm { - descriptor: `{ - "mediaType": "application/vnd.oci.image.config.v1+json", - "size": 1470, - "digest": "multihash+base58:QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8" - }`, + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.config.v1+json", + "size": 1470, + "digest": "multihash+base58:QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8" +}`, + fail: false, }, + + // fail: repeated separators in algorithm { - // fail: repeated separators in algorithm - descriptor: `{ - "mediaType": "application/vnd.oci.image.config.v1+json", - "size": 1470, - "digest": "sha256+foo+-b:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" - }`, + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.config.v1+json", + "size": 1470, + "digest": "sha256+foo+-b:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" +}`, fail: true, }, + + // expected success: test for alternate digest encoding { - descriptor: `{ - "digest": "sha256+b64u:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564", - "size": 1000000, - "mediaType": "application/vnd.oci.image.config.v1+json" - }`, + descriptor: ` +{ + "digest": "sha256+b64u:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564", + "size": 1000000, + "mediaType": "application/vnd.oci.image.config.v1+json" +}`, + fail: false, }, + + // expected success: test for those who cannot use modulo arithmetic to recover padding. { - // test for those who cannot use modulo arithmetic to recover padding. - descriptor: `{ - "digest": "sha256+b64u.unknownlength:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564=", - "size": 1000000, - "mediaType": "application/vnd.oci.image.config.v1+json" - }`, + descriptor: ` +{ + "digest": "sha256+b64u.unknownlength:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564=", + "size": 1000000, + "mediaType": "application/vnd.oci.image.config.v1+json" +}`, }, + + // expected failure: invalid data base64, missing padding { descriptor: ` +{ + "mediaType": "text/plain", + "size": 34, + "data": "aHR0cHM6Ly9naXRodWIuY29tL29wZW5jb250YWluZXJzCg", + "digest": "sha256:2690af59371e9eca9453dc29882643f46e5ca47ec2862bd517b5e17351325153" +}`, + fail: true, + }, + + // expected failure: negative size { - "mediaType": "text/plain", - "size": 34, - "data": "aHR0cHM6Ly9naXRodWIuY29tL29wZW5jb250YWluZXJzCg", - "digest": "sha256:2690af59371e9eca9453dc29882643f46e5ca47ec2862bd517b5e17351325153" - } - `, + descriptor: ` +{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "size": -7682, + "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270" +}`, fail: true, }, } {