Skip to content

Commit c58d52c

Browse files
authored
limit attestation subject count (#53)
Signed-off-by: Brian DeHamer <bdehamer@github.com>
1 parent 9a8c436 commit c58d52c

File tree

5 files changed

+65
-5
lines changed

5 files changed

+65
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ See [action.yml](action.yml)
6565
with:
6666
# Path to the artifact serving as the subject of the attestation. Must
6767
# specify exactly one of "subject-path" or "subject-digest". May contain
68-
# a glob pattern or list of paths.
68+
# a glob pattern or list of paths (total subject count cannot exceed 64).
6969
subject-path:
7070
7171
# SHA256 digest of the subject for the attestation. Must be in the form

__tests__/main.test.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
* Specifically, the inputs listed in `action.yml` should be set as environment
66
* variables following the pattern `INPUT_<INPUT_NAME>`.
77
*/
8-
98
import * as core from '@actions/core'
109
import * as github from '@actions/github'
1110
import { mockFulcio, mockRekor, mockTSA } from '@sigstore/mock'
1211
import * as oci from '@sigstore/oci'
12+
import fs from 'fs/promises'
1313
import nock from 'nock'
14+
import os from 'os'
15+
import path from 'path'
1416
import { MockAgent, setGlobalDispatcher } from 'undici'
1517
import { SEARCH_PUBLIC_GOOD_URL } from '../src/endpoints'
1618
import * as main from '../src/main'
@@ -286,6 +288,52 @@ describe('action', () => {
286288
expect(setFailedMock).not.toHaveBeenCalled()
287289
})
288290
})
291+
292+
describe('when too many subjects are specified', () => {
293+
let dir = ''
294+
295+
beforeEach(async () => {
296+
const filename = 'subject'
297+
const content = 'file content'
298+
299+
// Set-up temp directory
300+
const tmpDir = await fs.realpath(os.tmpdir())
301+
dir = await fs.mkdtemp(tmpDir + path.sep)
302+
303+
// Add files for glob testing
304+
for (let i = 0; i < 65; i++) {
305+
await fs.writeFile(path.join(dir, `${filename}-${i}`), content)
306+
}
307+
308+
// Set the GH context with private repository visibility and a repo owner.
309+
setGHContext({
310+
payload: { repository: { visibility: 'private' } },
311+
repo: { owner: 'foo', repo: 'bar' }
312+
})
313+
314+
// Mock the action's inputs
315+
getInputMock.mockImplementation(
316+
mockInput({
317+
predicate: '{}',
318+
'subject-path': path.join(dir, `${filename}-*`)
319+
})
320+
)
321+
})
322+
323+
afterEach(async () => {
324+
// Clean-up temp directory
325+
await fs.rm(dir, { recursive: true })
326+
})
327+
328+
it('sets a failed status', async () => {
329+
await main.run()
330+
331+
expect(runMock).toHaveReturned()
332+
expect(setFailedMock).toHaveBeenCalledWith(
333+
'Too many subjects specified. The maximum number of subjects is 64.'
334+
)
335+
})
336+
})
289337
})
290338

291339
function mockInput(inputs: Record<string, string>): typeof core.getInput {

action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ inputs:
1010
description: >
1111
Path to the artifact serving as the subject of the attestation. Must
1212
specify exactly one of "subject-path" or "subject-digest". May contain a
13-
glob pattern or list of paths.
13+
glob pattern or list of paths (total subject count cannot exceed 64).
1414
required: false
1515
subject-digest:
1616
description: >

dist/index.js

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ const COLOR_CYAN = '\x1B[36m'
1616
const COLOR_DEFAULT = '\x1B[39m'
1717
const ATTESTATION_FILE_NAME = 'attestation.jsonl'
1818

19+
const MAX_SUBJECT_COUNT = 64
20+
1921
/**
2022
* The main function for the action.
2123
* @returns {Promise<void>} Resolves when the action is complete.
@@ -38,8 +40,14 @@ export async function run(): Promise<void> {
3840
)
3941
}
4042

41-
// Calculate subject from inputs and generate provenance
43+
// Gather list of subjets
4244
const subjects = await subjectFromInputs()
45+
if (subjects.length > MAX_SUBJECT_COUNT) {
46+
throw new Error(
47+
`Too many subjects specified. The maximum number of subjects is ${MAX_SUBJECT_COUNT}.`
48+
)
49+
}
50+
4351
const predicate = predicateFromInputs()
4452
const outputPath = path.join(tempDir(), ATTESTATION_FILE_NAME)
4553

0 commit comments

Comments
 (0)