Skip to content

Commit

Permalink
enforce 16MB limit on predicate size (#80)
Browse files Browse the repository at this point in the history
Signed-off-by: Brian DeHamer <[email protected]>
  • Loading branch information
bdehamer authored Jun 3, 2024
1 parent 9e752e3 commit 4fa34e8
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 13 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
31 changes: 31 additions & 0 deletions __tests__/predicate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = '{}'
Expand All @@ -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/
)
})
})
})
8 changes: 5 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: >
Expand Down
21 changes: 18 additions & 3 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 27 additions & 3 deletions src/predicate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand All @@ -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) }
}

0 comments on commit 4fa34e8

Please sign in to comment.