Summary
When PSModule/GitHub-Script is called with an explicit Token: input (e.g. a GitHub App installation token minted by actions/create-github-app-token), the token value is passed as a named action with: input. This introduces two potential leak vectors compared to passing it only as an environment variable.
Risk level
Medium
Leak vectors
1. Debug log exposure
When ACTIONS_STEP_DEBUG=true (enabled by any repo/org admin, or automatically by some third-party integrations), GitHub Actions logs ##[debug] Input name: TOKEN entries that can include the input value. While actions/create-github-app-token calls core.setSecret() for the token, GitHub's runner-level masking has known gaps:
- Values split across log lines may not be masked
- URL-encoded or base64-encoded forms of the token are not masked automatically
2. result output reflection
PSModule/GitHub-Script returns a result step output. If the action reflects its inputs into the result JSON (common in GitHub Script wrappers), any downstream step reading steps.<id>.outputs.result could access the token value.
Current usage in Process-PSModule
Get-PSModuleSettings/action.yml passes a GitHub App installation token via both channels:
- uses: PSModule/GitHub-Script@8083ec1f733f00357ee4d0db0c6056686e483bc0
env:
GH_TOKEN: ${{ env.GH_TOKEN }} # safe: env var, picked up by gh CLI
with:
Token: ${{ env.GH_TOKEN }} # risk: named input
The env: GH_TOKEN channel is sufficient for gh CLI calls and is the recommended pattern. The with: Token: channel is needed only if the action internally calls core.getInput('token') to pass it to an API client.
Suggested fixes
Option A (preferred) - read token from environment only:
If PSModule/GitHub-Script can be updated to read GH_TOKEN (or GITHUB_TOKEN) from the environment instead of requiring a named Token: input, callers can drop the with: Token: line entirely. This is already how the gh CLI works and avoids the input-leak surface completely.
Option B - mask the token explicitly at entry:
If the named Token: input must remain, call core.setSecret(core.getInput('token')) as the very first line of the action's entrypoint (before any logging or debug output). This ensures masking is applied before the Actions runner emits any debug lines for this step.
Option C - document the risk:
If neither change is feasible, document that callers using sensitive tokens (e.g. GitHub App installation tokens) should not enable ACTIONS_STEP_DEBUG while this action is in use, and that the result output should not be logged or exposed to untrusted steps.
References
Summary
When
PSModule/GitHub-Scriptis called with an explicitToken:input (e.g. a GitHub App installation token minted byactions/create-github-app-token), the token value is passed as a named actionwith:input. This introduces two potential leak vectors compared to passing it only as an environment variable.Risk level
Medium
Leak vectors
1. Debug log exposure
When
ACTIONS_STEP_DEBUG=true(enabled by any repo/org admin, or automatically by some third-party integrations), GitHub Actions logs##[debug] Input name: TOKENentries that can include the input value. Whileactions/create-github-app-tokencallscore.setSecret()for the token, GitHub's runner-level masking has known gaps:2.
resultoutput reflectionPSModule/GitHub-Scriptreturns aresultstep output. If the action reflects its inputs into the result JSON (common in GitHub Script wrappers), any downstream step readingsteps.<id>.outputs.resultcould access the token value.Current usage in Process-PSModule
Get-PSModuleSettings/action.ymlpasses a GitHub App installation token via both channels:The
env: GH_TOKENchannel is sufficient forghCLI calls and is the recommended pattern. Thewith: Token:channel is needed only if the action internally callscore.getInput('token')to pass it to an API client.Suggested fixes
Option A (preferred) - read token from environment only:
If
PSModule/GitHub-Scriptcan be updated to readGH_TOKEN(orGITHUB_TOKEN) from the environment instead of requiring a namedToken:input, callers can drop thewith: Token:line entirely. This is already how theghCLI works and avoids the input-leak surface completely.Option B - mask the token explicitly at entry:
If the named
Token:input must remain, callcore.setSecret(core.getInput('token'))as the very first line of the action's entrypoint (before any logging or debug output). This ensures masking is applied before the Actions runner emits any debug lines for this step.Option C - document the risk:
If neither change is feasible, document that callers using sensitive tokens (e.g. GitHub App installation tokens) should not enable
ACTIONS_STEP_DEBUGwhile this action is in use, and that theresultoutput should not be logged or exposed to untrusted steps.References