Skip to content

Commit cbc873b

Browse files
authored
Use caller token for same-repository publication (#1758)
* Authorize same-repository caller token * Use caller token for same-repository publication * Run agent-task workflow contracts in CI * Fetch pinned workflow helpers in contract CI
1 parent ca1cc53 commit cbc873b

9 files changed

Lines changed: 141 additions & 25 deletions

.github/scripts/run-agent-task/build-codebox-task-request.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ const request = {
8787
requires_pr: booleanEnv("SUCCESS_REQUIRES_PR"),
8888
},
8989
access: {
90+
caller_repo: requiredString("CALLER_REPO").toLowerCase(),
9091
access_token_repos: repositoryList("ACCESS_TOKEN_REPOS"),
91-
require_access_token: booleanEnv("REQUIRE_ACCESS_TOKEN"),
9292
allowed_repos: parseJson("ALLOWED_REPOS", [], "array"),
9393
},
9494
limits: {
@@ -115,6 +115,9 @@ if (request.access.allowed_repos.some((repository) => typeof repository !== "str
115115
request.access.allowed_repos = [...new Set(request.access.allowed_repos.map((repository) => repository.toLowerCase()))]
116116
request.access.access_token_repos = [...new Set(request.access.access_token_repos.map((repository) => repository.toLowerCase()))]
117117
request.target_repo = request.target_repo.toLowerCase()
118+
if (!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(request.access.caller_repo)) {
119+
throw new Error("CALLER_REPO must be an OWNER/REPO value.")
120+
}
118121
if (!request.access.allowed_repos.includes(request.target_repo)) {
119122
throw new Error("ALLOWED_REPOS must explicitly include TARGET_REPO.")
120123
}

.github/scripts/run-agent-task/execute-native-agent-task.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,11 @@ function accessFailure(request) {
118118
const allowed = Array.isArray(access.allowed_repos) ? access.allowed_repos : []
119119
const tokenRepos = Array.isArray(access.access_token_repos) ? access.access_token_repos : []
120120
const target = string(request.target_repo)
121+
const caller = string(access.caller_repo)
121122
if (!allowed.includes(target) || !tokenRepos.includes(target)) return "Target repository is not explicitly authorized by allowed_repos and access_token_repos."
122-
if (access.require_access_token === true && process.env.ACCESS_TOKEN_CONFIGURED !== "true") return "A configured ACCESS_TOKEN is required but unavailable."
123+
if (!caller) return "Caller repository is required for publication authorization."
124+
if (target !== caller && process.env.EXPLICIT_ACCESS_TOKEN_CONFIGURED !== "true") return "An explicit ACCESS_TOKEN is required for cross-repository publication."
125+
if (!string(process.env.GITHUB_TOKEN)) return "No effective GitHub token is available for runner workspace tools."
123126
return ""
124127
}
125128

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Agent Task Contracts
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- ".github/scripts/run-agent-task/**"
7+
- ".github/workflows/agent-task-contracts.yml"
8+
- ".github/workflows/run-agent-task.yml"
9+
- "contracts/agent-task-workflow-request.fixture.json"
10+
- "contracts/run-agent-task-reusable-workflow-interface.v1.json"
11+
- "docs/agent-task-reusable-workflow.md"
12+
- "package-lock.json"
13+
- "package.json"
14+
- "tests/agent-task-*.test.ts"
15+
- "tests/redaction.test.ts"
16+
- "tests/production-boundary-enforcement.test.ts"
17+
- "tests/runtime-tool-policy.test.ts"
18+
push:
19+
paths:
20+
- ".github/scripts/run-agent-task/**"
21+
- ".github/workflows/agent-task-contracts.yml"
22+
- ".github/workflows/run-agent-task.yml"
23+
- "contracts/agent-task-workflow-request.fixture.json"
24+
- "contracts/run-agent-task-reusable-workflow-interface.v1.json"
25+
- "docs/agent-task-reusable-workflow.md"
26+
- "package-lock.json"
27+
- "package.json"
28+
- "tests/agent-task-*.test.ts"
29+
- "tests/redaction.test.ts"
30+
- "tests/production-boundary-enforcement.test.ts"
31+
- "tests/runtime-tool-policy.test.ts"
32+
33+
jobs:
34+
contracts:
35+
runs-on: ubuntu-latest
36+
steps:
37+
- uses: actions/checkout@v4
38+
with:
39+
fetch-depth: 0
40+
- uses: actions/setup-node@v4
41+
with:
42+
node-version: 22
43+
cache: npm
44+
- run: npm ci
45+
- run: npm run build
46+
- run: npm run test:agent-task-contracts
47+
- run: npm run test:redaction
48+
- run: npm run test:production-boundary-enforcement
49+
- run: npm run test:runtime-tool-policy
50+
51+
workflow-lint:
52+
runs-on: ubuntu-latest
53+
steps:
54+
- uses: actions/checkout@v4
55+
- uses: docker://rhysd/actionlint:1.7.7
56+
with:
57+
args: .github/workflows/run-agent-task.yml

.github/workflows/run-agent-task.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,6 @@ name: Run Agent Task (reusable)
6363
description: Comma-separated repositories for access-token scoping.
6464
type: string
6565
default: ""
66-
require_access_token:
67-
description: Whether the run requires the configured access token.
68-
type: boolean
69-
default: false
7066
allowed_repos:
7167
description: JSON array of repositories the run may access.
7268
type: string
@@ -125,7 +121,7 @@ name: Run Agent Task (reusable)
125121
MODEL_PROVIDER_SECRET_5:
126122
required: false
127123
ACCESS_TOKEN:
128-
description: GitHub token for target-repository publication only; it is never used to fetch external packages.
124+
description: Optional explicit GitHub token for an authorized cross-repository target. Same-repository publication uses the caller token.
129125
required: false
130126
EXTERNAL_PACKAGE_SOURCE_POLICY:
131127
description: Trusted versioned JSON policy authorizing external native package repositories and exact standalone .agent.json paths.
@@ -151,7 +147,7 @@ jobs:
151147
runs-on: ubuntu-latest
152148
env:
153149
# Advance this only in a subsequent workflow commit after helper changes land.
154-
WP_CODEBOX_HELPER_REVISION: 54c2f9a7bc3cd1fe20055d496c83efcfb99afb41
150+
WP_CODEBOX_HELPER_REVISION: d9e329e7c3bb852b857870a26d8f3853feef751d
155151
permissions:
156152
contents: write
157153
pull-requests: write
@@ -206,6 +202,7 @@ jobs:
206202
WORKLOAD_LABEL: ${{ inputs.workload_label }}
207203
COMPONENT_ID: ${{ inputs.component_id }}
208204
TARGET_REPO: ${{ inputs.target_repo }}
205+
CALLER_REPO: ${{ github.repository }}
209206
PROMPT: ${{ inputs.prompt }}
210207
WRITABLE_PATHS: ${{ inputs.writable_paths }}
211208
PROVIDER: ${{ inputs.provider }}
@@ -220,7 +217,6 @@ jobs:
220217
DRIFT_CHECKS: ${{ inputs.drift_checks }}
221218
SUCCESS_REQUIRES_PR: ${{ inputs.success_requires_pr }}
222219
ACCESS_TOKEN_REPOS: ${{ inputs.access_token_repos }}
223-
REQUIRE_ACCESS_TOKEN: ${{ inputs.require_access_token }}
224220
ALLOWED_REPOS: ${{ inputs.allowed_repos }}
225221
MAX_TURNS: ${{ inputs.max_turns }}
226222
TIME_BUDGET_MS: ${{ inputs.time_budget_ms }}
@@ -249,7 +245,7 @@ jobs:
249245
# Runner workspace tools resolve GitHub credentials from this standard
250246
# environment variable. It is never written to task inputs or artifacts.
251247
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN || github.token }}
252-
ACCESS_TOKEN_CONFIGURED: ${{ secrets.ACCESS_TOKEN != '' }}
248+
EXPLICIT_ACCESS_TOKEN_CONFIGURED: ${{ secrets.ACCESS_TOKEN != '' }}
253249
EXTERNAL_PACKAGE_SOURCE_POLICY: ${{ secrets.EXTERNAL_PACKAGE_SOURCE_POLICY }}
254250
run: node .wp-codebox-workflow/.github/scripts/run-agent-task/execute-native-agent-task.mjs
255251

contracts/agent-task-workflow-request.fixture.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@
3434
"requires_pr": false
3535
},
3636
"access": {
37+
"caller_repo": "automattic/example-target",
3738
"access_token_repos": [
3839
"automattic/example-target"
3940
],
40-
"require_access_token": false,
4141
"allowed_repos": [
4242
"automattic/example-target"
4343
]

contracts/run-agent-task-reusable-workflow-interface.v1.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
"drift_checks": { "required": false, "type": "string", "default": "[]" },
1818
"success_requires_pr": { "required": false, "type": "boolean", "default": false },
1919
"access_token_repos": { "required": false, "type": "string", "default": "" },
20-
"require_access_token": { "required": false, "type": "boolean", "default": false },
2120
"allowed_repos": { "required": false, "type": "string", "default": "[]" },
2221
"max_turns": { "required": false, "type": "number", "default": 12 },
2322
"time_budget_ms": { "required": false, "type": "number", "default": 600000 },

docs/agent-task-reusable-workflow.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ jobs:
1818
success_requires_pr: true
1919
access_token_repos: Automattic/example-target
2020
allowed_repos: '["Automattic/example-target"]'
21-
require_access_token: true
2221
output_projections: '{"pr_url":"outputs.artifact_result.result.outputs.runner_workspace_publication.pull_request.url"}'
2322
secrets:
2423
EXTERNAL_PACKAGE_SOURCE_POLICY: ${{ secrets.EXTERNAL_PACKAGE_SOURCE_POLICY }}
@@ -58,13 +57,17 @@ and [29281470159](https://github.com/Automattic/build-with-wordpress/actions/run
5857
- `success_requires_pr`: require a successful, published runner-workspace pull request for `target_repo`.
5958
- `access_token_repos`: comma-separated repositories available to the supplied access token.
6059
- `allowed_repos`: JSON repository allowlist. It and `access_token_repos` must explicitly include `target_repo`.
61-
- `require_access_token`: require the reusable workflow's `ACCESS_TOKEN` secret.
6260
- `output_projections`: JSON object mapping output names to dot-delimited paths in the native result. Every projection must resolve.
6361

6462
## Access And Publication
6563

66-
`ACCESS_TOKEN` is passed only as `GITHUB_TOKEN` to native agent execution and is
67-
not serialized into task input, result, or artifact data. GitHub runner tools
64+
For a target equal to the caller repository, the workflow passes the caller's
65+
built-in `github.token` as `GITHUB_TOKEN` to native agent execution. An
66+
`ACCESS_TOKEN` secret is not required in that case. For a target in another
67+
repository, `ACCESS_TOKEN` is required explicitly and must be scoped by both
68+
`access_token_repos` and `allowed_repos`. The caller token is never inferred to
69+
have cross-repository access. The effective token is not serialized into task
70+
input, result, or artifact data. GitHub runner tools
6871
receive the normalized `allowed_repos` policy explicitly through the runtime and
6972
fail closed for every PR, issue, and comment operation outside that set. The
7073
checkout does not persist credentials. Verification, dependency, and drift

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"generate:fanout-aggregation-contract": "tsx scripts/generate-fanout-aggregation-contract-fixture.ts",
8686
"smoke": "tsx scripts/run-smoke.ts",
8787
"test:redaction": "tsx tests/redaction.test.ts",
88-
"test:agent-task-contracts": "tsx tests/agent-task-contracts.test.ts && npm run test:agent-task-workflow-interface",
88+
"test:agent-task-contracts": "tsx tests/agent-task-contracts.test.ts && npm run test:agent-task-workflow-interface && tsx tests/agent-task-reusable-workflow.test.ts",
8989
"test:agent-task-workflow-interface": "tsx tests/run-agent-task-reusable-workflow-interface.test.ts",
9090
"test:agent-task-runtime-package-staging": "tsx tests/agent-task-runtime-package-staging.test.ts",
9191
"test:external-native-package-materialization": "tsx tests/external-native-package-materialization.test.ts",

tests/agent-task-reusable-workflow.test.ts

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ assert.match(workflow, /output_projections:/)
2323
assert.match(workflow, /verification_commands:/)
2424
assert.match(workflow, /drift_checks:/)
2525
assert.match(workflow, /access_token_repos:/)
26-
assert.match(workflow, /require_access_token:/)
26+
assert.doesNotMatch(publicWorkflowSurface, /require_access_token:/)
2727
assert.match(workflow, /projected_outputs_json:/)
2828
assert.match(workflow, /ACCESS_TOKEN:/)
2929
assert.match(workflow, /GITHUB_TOKEN: \$\{\{ secrets\.ACCESS_TOKEN \|\| github\.token \}\}/)
30-
assert.match(workflow, /ACCESS_TOKEN_CONFIGURED: \$\{\{ secrets\.ACCESS_TOKEN != '' \}\}/)
30+
assert.match(workflow, /CALLER_REPO: \$\{\{ github\.repository \}\}/)
31+
assert.match(workflow, /EXPLICIT_ACCESS_TOKEN_CONFIGURED: \$\{\{ secrets\.ACCESS_TOKEN != '' \}\}/)
3132
assert.doesNotMatch(workflow, /homeboy|require_app_token|require_homeboy_app_token|REQUIRE_HOMEBOY_APP_TOKEN|Extra-Chill\/homeboy-action|agent-task run-plan/i)
3233
assert.doesNotMatch(workflow, /docs-agent|wp-codebox\/docs-agent-runner-recipe\/v1|recipe_path|recipe_json|wp_codebox_ref/i)
3334
assert.doesNotMatch(workflow, /datamachine-agent-ci|runtime-agent-full-run|Extra-Chill\/homeboy-extensions/)
@@ -50,8 +51,8 @@ assert.doesNotMatch(workflow, new RegExp(foreignCallerSha))
5051
assert.match(workflow, /Validate pinned WP Codebox helper revision/)
5152

5253
const requiredHelperFiles = {
53-
".github/scripts/run-agent-task/build-codebox-task-request.mjs": "a0b9052bf63b0d5b096568c21a1e7333b7474b35834ffd1bc0d748fb0cfd0859",
54-
".github/scripts/run-agent-task/execute-native-agent-task.mjs": "b67910e538c6fb231c25dee43d0ff2e06e521e08108f8570e0389b022f9f8ccc",
54+
".github/scripts/run-agent-task/build-codebox-task-request.mjs": "ed1fbc144428bfbf222810a8a467390e8cd5b45daa0f3e64e03162949d6c84df",
55+
".github/scripts/run-agent-task/execute-native-agent-task.mjs": "324c6d12dd01880bc9e4cd880ea6c713cb1bfd630b4925c53d78af7283e4a459",
5556
".github/scripts/run-agent-task/prepare-agent-task-upload.mjs": "93511e4174e705f55ff014ba68ac52fdaca771ce3f19f3921cceb661e69569da",
5657
}
5758
for (const [path, digest] of Object.entries(requiredHelperFiles)) {
@@ -70,7 +71,8 @@ assert.match(docs, /Automattic\/wp-codebox\/.github\/workflows\/run-agent-task.y
7071
assert.match(docs, /external_package_source/)
7172
assert.match(docs, /runner_workspace/)
7273
assert.match(docs, /access_token_repos/)
73-
assert.match(docs, /require_access_token/)
74+
assert.match(docs, /built-in `github\.token` as `GITHUB_TOKEN`/)
75+
assert.match(docs, /target in another\nrepository, `ACCESS_TOKEN` is required explicitly/)
7476
assert.match(docs, /success_requires_pr/)
7577
assert.match(docs, /intentional exposed-workflow breaking change/)
7678
assert.match(docs, /wp-codebox\/reusable-workflow-interface\/v1/)
@@ -110,6 +112,7 @@ await execFileAsync("node", [new URL("../.github/scripts/run-agent-task/build-co
110112
WORKLOAD_LABEL: "Run example maintenance",
111113
COMPONENT_ID: "example-ci-driver",
112114
TARGET_REPO: "Automattic/example-target",
115+
CALLER_REPO: "Automattic/example-target",
113116
PROMPT: "Update the configured surface.",
114117
WRITABLE_PATHS: "README.md,docs/**",
115118
PROVIDER: "openai",
@@ -120,7 +123,6 @@ await execFileAsync("node", [new URL("../.github/scripts/run-agent-task/build-co
120123
DRIFT_CHECKS: "[]",
121124
SUCCESS_REQUIRES_PR: "false",
122125
ACCESS_TOKEN_REPOS: "Automattic/example-target",
123-
REQUIRE_ACCESS_TOKEN: "false",
124126
ALLOWED_REPOS: '["Automattic/example-target"]',
125127
MAX_TURNS: "12",
126128
TIME_BUDGET_MS: "600000",
@@ -152,6 +154,7 @@ await execFileAsync("node", [new URL("../.github/scripts/run-agent-task/execute-
152154
AGENT_TASK_REQUEST_PATH: requestPath,
153155
AGENT_TASK_WORKSPACE: tmp,
154156
WP_CODEBOX_WORKFLOW_ROOT: new URL("..", import.meta.url).pathname,
157+
GITHUB_TOKEN: "test-caller-token",
155158
EXTERNAL_PACKAGE_SOURCE_POLICY: '{"version":1,"repositories":{"automattic/example-agent-packages":["packages/example-agent.agent.json"]}}',
156159
},
157160
})
@@ -164,6 +167,55 @@ assert.equal(result.runtime_input_path, ".codebox/native-agent-task-input.json")
164167
assert.deepEqual(result.verification, [])
165168
assert.doesNotMatch(JSON.stringify(result), /homeboy|agent-task-plan|run-plan/i)
166169

170+
const executeNativeAgentTask = new URL("../.github/scripts/run-agent-task/execute-native-agent-task.mjs", import.meta.url).pathname
171+
const executeAccessCase = async (candidate: Record<string, unknown>, environment: Record<string, string>) => {
172+
await writeFile(requestPath, `${JSON.stringify(candidate, null, 2)}\n`)
173+
return execFileAsync("node", [executeNativeAgentTask], {
174+
cwd: tmp,
175+
env: {
176+
...process.env,
177+
GITHUB_OUTPUT: outputPath,
178+
AGENT_TASK_REQUEST_PATH: requestPath,
179+
AGENT_TASK_WORKSPACE: tmp,
180+
WP_CODEBOX_WORKFLOW_ROOT: new URL("..", import.meta.url).pathname,
181+
EXTERNAL_PACKAGE_SOURCE_POLICY: '{"version":1,"repositories":{"automattic/example-agent-packages":["packages/example-agent.agent.json"]}}',
182+
...environment,
183+
},
184+
})
185+
}
186+
187+
// Hosted run 29293335972 supplied github.token with write permissions but no
188+
// named ACCESS_TOKEN. This is the exact same-repository environment.
189+
const callerToken = "caller-token-from-run-29293335972"
190+
await executeAccessCase(request, { GITHUB_TOKEN: callerToken, EXPLICIT_ACCESS_TOKEN_CONFIGURED: "false" })
191+
const sameRepositoryResult = JSON.parse(await readFile(resultPath, "utf8"))
192+
assert.equal(sameRepositoryResult.access.authorized, true)
193+
assert.doesNotMatch(JSON.stringify(sameRepositoryResult), new RegExp(callerToken))
194+
195+
await assert.rejects(
196+
executeAccessCase(request, { GITHUB_TOKEN: "", EXPLICIT_ACCESS_TOKEN_CONFIGURED: "false" }),
197+
)
198+
assert.match(JSON.parse(await readFile(resultPath, "utf8")).access.error, /No effective GitHub token/)
199+
200+
const crossRepositoryRequest = {
201+
...request,
202+
target_repo: "automattic/another-target",
203+
access: { ...request.access, allowed_repos: ["automattic/another-target"], access_token_repos: ["automattic/another-target"] },
204+
}
205+
await assert.rejects(
206+
executeAccessCase(crossRepositoryRequest, { GITHUB_TOKEN: callerToken, EXPLICIT_ACCESS_TOKEN_CONFIGURED: "false" }),
207+
)
208+
assert.match(JSON.parse(await readFile(resultPath, "utf8")).access.error, /explicit ACCESS_TOKEN is required for cross-repository publication/)
209+
210+
const targetMismatchRequest = {
211+
...request,
212+
target_repo: "automattic/another-target",
213+
}
214+
await assert.rejects(
215+
executeAccessCase(targetMismatchRequest, { GITHUB_TOKEN: callerToken, EXPLICIT_ACCESS_TOKEN_CONFIGURED: "true" }),
216+
)
217+
assert.match(JSON.parse(await readFile(resultPath, "utf8")).access.error, /Target repository is not explicitly authorized/)
218+
167219
const malformedRequest = { ...request, verification_commands: [{ description: "Missing command" }] }
168220
await writeFile(requestPath, `${JSON.stringify(malformedRequest, null, 2)}\n`)
169221
await assert.rejects(execFileAsync("node", [new URL("../.github/scripts/run-agent-task/execute-native-agent-task.mjs", import.meta.url).pathname], {
@@ -174,6 +226,7 @@ await assert.rejects(execFileAsync("node", [new URL("../.github/scripts/run-agen
174226
AGENT_TASK_REQUEST_PATH: requestPath,
175227
AGENT_TASK_WORKSPACE: tmp,
176228
WP_CODEBOX_WORKFLOW_ROOT: new URL("..", import.meta.url).pathname,
229+
GITHUB_TOKEN: "test-caller-token",
177230
EXTERNAL_PACKAGE_SOURCE_POLICY: '{"version":1,"repositories":{"automattic/example-agent-packages":["packages/example-agent.agent.json"]}}',
178231
},
179232
}), /verification_commands\[0\]\.command/)
@@ -187,15 +240,16 @@ await execFileAsync("npm", ["run", "test:php-runner-workspace-tools"], { cwd: ne
187240

188241
const outputs = await readFile(outputPath, "utf8")
189242
assert.match(outputs, /job_status<<__WP_CODEBOX_OUTPUT__\nskipped\n__WP_CODEBOX_OUTPUT__/)
190-
assert.match(outputs, /credential_mode<<__WP_CODEBOX_OUTPUT__\nrunner-(provider|default)-credentials\n__WP_CODEBOX_OUTPUT__/)
243+
assert.match(outputs, /credential_mode<<__WP_CODEBOX_OUTPUT__\nrunner-access-token\n__WP_CODEBOX_OUTPUT__/)
244+
assert.doesNotMatch(outputs, /caller-token-from-run-29293335972/)
191245
assert.match(outputs, /request_path<<__WP_CODEBOX_OUTPUT__\n\.codebox\/agent-task-request\.json\n__WP_CODEBOX_OUTPUT__/)
192246
assert.match(outputs, /result_path<<__WP_CODEBOX_OUTPUT__\n\.codebox\/agent-task-workflow-result\.json\n__WP_CODEBOX_OUTPUT__/)
193247

194248
// Uploads come only from a fail-closed staging directory. Policy data remains
195249
// secret even though public package bytes may be present in runtime input.
196250
const artifactsPath = join(tmp, ".codebox", "agent-task-artifacts")
197251
await mkdir(artifactsPath, { recursive: true })
198-
await writeFile(join(artifactsPath, "safe.txt"), "secret-agent-value")
252+
await writeFile(join(artifactsPath, "safe.txt"), "secret-agent-value secret-github-value")
199253
await writeFile(join(artifactsPath, "oversize.txt"), `secret-agent-value${"x".repeat(4 * 1024 * 1024)}`)
200254
await writeFile(join(artifactsPath, "binary.bin"), Buffer.from([0, ...Buffer.from("secret-agent-value")]))
201255
const outsideArtifact = join(tmp, "outside-secret.txt")
@@ -208,6 +262,7 @@ await execFileAsync("node", [new URL("../.github/scripts/run-agent-task/prepare-
208262
})
209263
const uploadArtifactsPath = join(tmp, ".codebox", "agent-task-upload", ".codebox", "agent-task-artifacts")
210264
assert.match(await readFile(join(uploadArtifactsPath, "safe.txt"), "utf8"), /\[REDACTED\]/)
265+
assert.doesNotMatch(await readFile(join(uploadArtifactsPath, "safe.txt"), "utf8"), /secret-github-value/)
211266
assert.doesNotMatch(await readFile(join(tmp, ".codebox", "agent-task-upload", ".codebox", "agent-task-request.json"), "utf8"), /secret-agent-value|secret-github-value|\{"private":"policy"\}/)
212267
for (const name of ["oversize.txt", "binary.bin", "linked-secret.txt"]) {
213268
await assert.rejects(readFile(join(uploadArtifactsPath, name), "utf8"), /ENOENT/)

0 commit comments

Comments
 (0)