enforce 16MB limit on predicate size (#80)

Signed-off-by: Brian DeHamer <bdehamer@github.com>
This commit is contained in:
Brian DeHamer
2024-06-03 09:41:25 -07:00
committed by GitHub
parent 9e752e3d76
commit 4fa34e85c5
5 changed files with 92 additions and 13 deletions
+11 -4
View File
@@ -81,12 +81,14 @@ See [action.yml](action.yml)
# URI identifying the type of the predicate.
predicate-type:
# JSON string containing the value for the attestation predicate. Must
# supply exactly one of "predicate-path" or "predicate".
# String containing the value for the attestation predicate. String length
# cannot exceed 16MB. Must supply exactly one of "predicate-path" or
# "predicate".
predicate:
# Path to the file which contains the JSON content for the attestation
# predicate. Must supply exactly one of "predicate-path" or "predicate".
# Path to the file which contains the content for the attestation predicate.
# File size cannot exceed 16MB. Must supply exactly one of "predicate-path"
# or "predicate".
predicate-path:
# Whether to push the attestation to the image registry. Requires that the
@@ -124,6 +126,11 @@ processed in batches 50. After the initial group of 50, each subsequent batch
will incur an exponentially increasing amount of delay (capped at 1 minute of
delay per batch) to avoid overwhelming the attestation API.
### Predicate Limits
Whether supplied via the `predicate` or `predicatePath` input, the predicate
string cannot exceed 16MB.
## Examples
### Identify Subject by Path
+31
View File
@@ -78,6 +78,20 @@ describe('subjectFromInputs', () => {
})
})
describe('when specifying a predicate path that does not exist', () => {
const predicateType = 'https://example.com/predicate'
const predicatePath = 'foo'
it('returns the predicate', () => {
const inputs: PredicateInputs = {
...blankInputs,
predicateType,
predicatePath
}
expect(() => predicateFromInputs(inputs)).toThrow(/file not found/)
})
})
describe('when specifying a predicate value', () => {
const predicateType = 'https://example.com/predicate'
const content = '{}'
@@ -95,4 +109,21 @@ describe('subjectFromInputs', () => {
})
})
})
describe('when specifying a predicate value exceeding the max size', () => {
const predicateType = 'https://example.com/predicate'
const content = JSON.stringify({ a: 'a'.repeat(16 * 1024 * 1024) })
it('throws an error', () => {
const inputs: PredicateInputs = {
...blankInputs,
predicateType,
predicate: content
}
expect(() => predicateFromInputs(inputs)).toThrow(
/predicate string exceeds maximum/
)
})
})
})
+5 -3
View File
@@ -30,13 +30,15 @@ inputs:
required: true
predicate:
description: >
String containing the value for the attestation predicate. Must supply
exactly one of "predicate-path" or "predicate".
String containing the value for the attestation predicate. String length
cannot exceed 16MB. Must supply exactly one of "predicate-path" or
"predicate".
required: false
predicate-path:
description: >
Path to the file which contains the content for the attestation predicate.
Must supply exactly one of "predicate-path" or "predicate".
File size cannot exceed 16MB. Must supply exactly one of "predicate-path"
or "predicate".
required: false
push-to-registry:
description: >
Generated Vendored
+18 -3
View File
@@ -80209,6 +80209,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.predicateFromInputs = void 0;
const fs_1 = __importDefault(__nccwpck_require__(57147));
const MAX_PREDICATE_SIZE_BYTES = 16 * 1024 * 1024;
// Returns the predicate specified by the action's inputs. The predicate value
// may be specified as a path to a file or as a string.
const predicateFromInputs = (inputs) => {
@@ -80222,9 +80223,23 @@ const predicateFromInputs = (inputs) => {
if (predicatePath && predicate) {
throw new Error('Only one of predicate-path or predicate may be provided');
}
const params = predicatePath
? fs_1.default.readFileSync(predicatePath, 'utf-8')
: predicate;
let params = predicate;
if (predicatePath) {
if (!fs_1.default.existsSync(predicatePath)) {
throw new Error(`predicate file not found: ${predicatePath}`);
}
/* istanbul ignore next */
if (fs_1.default.statSync(predicatePath).size > MAX_PREDICATE_SIZE_BYTES) {
throw new Error(`predicate file exceeds maximum allowed size: ${MAX_PREDICATE_SIZE_BYTES} bytes`);
}
params = fs_1.default.readFileSync(predicatePath, 'utf-8');
}
else {
if (predicate.length > MAX_PREDICATE_SIZE_BYTES) {
throw new Error(`predicate string exceeds maximum allowed size: ${MAX_PREDICATE_SIZE_BYTES} bytes`);
}
params = predicate;
}
return { type: predicateType, params: JSON.parse(params) };
};
exports.predicateFromInputs = predicateFromInputs;
+27 -3
View File
@@ -7,6 +7,9 @@ export type PredicateInputs = {
predicate: string
predicatePath: string
}
const MAX_PREDICATE_SIZE_BYTES = 16 * 1024 * 1024
// Returns the predicate specified by the action's inputs. The predicate value
// may be specified as a path to a file or as a string.
export const predicateFromInputs = (inputs: PredicateInputs): Predicate => {
@@ -24,9 +27,30 @@ export const predicateFromInputs = (inputs: PredicateInputs): Predicate => {
throw new Error('Only one of predicate-path or predicate may be provided')
}
const params = predicatePath
? fs.readFileSync(predicatePath, 'utf-8')
: predicate
let params: string = predicate
if (predicatePath) {
if (!fs.existsSync(predicatePath)) {
throw new Error(`predicate file not found: ${predicatePath}`)
}
/* istanbul ignore next */
if (fs.statSync(predicatePath).size > MAX_PREDICATE_SIZE_BYTES) {
throw new Error(
`predicate file exceeds maximum allowed size: ${MAX_PREDICATE_SIZE_BYTES} bytes`
)
}
params = fs.readFileSync(predicatePath, 'utf-8')
} else {
if (predicate.length > MAX_PREDICATE_SIZE_BYTES) {
throw new Error(
`predicate string exceeds maximum allowed size: ${MAX_PREDICATE_SIZE_BYTES} bytes`
)
}
params = predicate
}
return { type: predicateType, params: JSON.parse(params) }
}