Summary
When compiling a workflow that configures a safe output with github-token from secrets, the generated .lock.yml writes the token value into ${RUNNER_TEMP}/gh-aw/safeoutputs/config.json at runtime via an unquoted heredoc, causing secret materialization on disk.
Why this is a bug
This increases secret exposure surface unnecessarily (debug logs, accidental artifact collection, or other file disclosure paths), even though the safe output processing step already receives a token directly at execution time.
Reproduction
Given workflow frontmatter like:
safe-outputs:
update-project:
project: https://github.com/orgs/github/projects/24263github-token: "${{ secrets.WRITE_PROJECT_PAT }}"gh aw compile generates lockfile logic equivalent to:
cat >"${RUNNER_TEMP}/gh-aw/safeoutputs/config.json"<<EOCONFIG{"update_project":{"github-token":"${WRITE_PROJECT_PAT}", ...}}EOCONFIGwith WRITE_PROJECT_PAT populated from ${{ secrets.WRITE_PROJECT_PAT }}.
Actual behavior
Secret token is expanded and written into config.json on disk in runner temp storage.
Expected behavior
gh-aw should avoid writing secret token values to disk in generated config files.
Prefer passing token only through environment/step inputs at execution time, or referencing secret placeholders that are resolved in-memory by the handler.
Suggested fix
- Avoid unquoted heredoc expansion for secret-bearing fields.
- Omit
github-token from on-disk config when an equivalent runtime env/input token is already provided. - Ensure no safe-output secret values are persisted to temp files by default.
Summary
When compiling a workflow that configures a safe output with
github-tokenfrom secrets, the generated.lock.ymlwrites the token value into${RUNNER_TEMP}/gh-aw/safeoutputs/config.jsonat runtime via an unquoted heredoc, causing secret materialization on disk.Why this is a bug
This increases secret exposure surface unnecessarily (debug logs, accidental artifact collection, or other file disclosure paths), even though the safe output processing step already receives a token directly at execution time.
Reproduction
Given workflow frontmatter like:
gh aw compilegenerates lockfile logic equivalent to:with
WRITE_PROJECT_PATpopulated from${{ secrets.WRITE_PROJECT_PAT }}.Actual behavior
Secret token is expanded and written into
config.jsonon disk in runner temp storage.Expected behavior
gh-awshould avoid writing secret token values to disk in generated config files.Prefer passing token only through environment/step inputs at execution time, or referencing secret placeholders that are resolved in-memory by the handler.
Suggested fix
github-tokenfrom on-disk config when an equivalent runtime env/input token is already provided.