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/24263
github-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}", ...}}
EOCONFIG
with 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.