fix: prevent secret leakage in git invocations in JS action scripts - #50730
Conversation
- dynamic_checkout.cjs: add silent:true to exec that sets Authorization extraheader - git_auth_helpers.cjs: remove credential args from gitExecSilent error message - run_operation_update_upgrade.cjs: call core.setSecret(token) and add silent:true to git remote add with token-in-URL - Update tests to match new error message format and add setSecret mock Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
| // Use extraheader to pass the token without embedding it in the URL (more secure). | ||
| const tokenBase64 = Buffer.from(`x-access-token:${token}`).toString("base64"); | ||
| await exec.exec("git", ["config", `http.${serverUrl}/.extraheader`, `Authorization: basic ${tokenBase64}`]); | ||
| await exec.exec("git", ["config", `http.${serverUrl}/.extraheader`, `Authorization: basic ${tokenBase64}`], { silent: true }); |
There was a problem hiding this comment.
Done. Exported gitExecSilent from git_auth_helpers.cjs and replaced the inline exec.exec(..., { silent: true }) call with gitExecSilent in dynamic_checkout.cjs.
|
@copilot use core.setSecret to also mask secrets |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
Warning Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding. What happenedThe threat detection engine failed to produce results. Review the workflow run logs for details. Great work on closing those credential-leakage gaps in the JS action scripts! 🎯 This PR is well-scoped and security-focused: ✅ Changes are tightly focused — three specific places in ✅ Tests included — both affected modules ( ✅ Thorough audit trail — the body notes that other git invocations were reviewed and already safe, which shows proper diligence. The PR looks ready for review. Nice auditing work on the full scope! 🔒
|
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Added |
There was a problem hiding this comment.
Pull request overview
Prevents GitHub token exposure in JavaScript action Git commands and error messages.
Changes:
- Masks raw and Base64-encoded tokens.
- Silences credential-bearing Git commands.
- Removes credentials from Git failure messages.
Show a summary per file
| File | Description |
|---|---|
dynamic_checkout.cjs |
Secures extraheader configuration. |
git_auth_helpers.cjs |
Sanitizes credential command failures. |
git_auth_helpers.test.cjs |
Updates failure expectation. |
run_operation_update_upgrade.cjs |
Masks token and silences remote creation. |
run_operation_update_upgrade.test.cjs |
Adds setSecret mock. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 5/5 changed files
- Comments generated: 3
- Review effort level: Balanced
| core.setSecret(token); | ||
| const tokenBase64 = Buffer.from(`x-access-token:${token}`).toString("base64"); | ||
| await exec.exec("git", ["config", `http.${serverUrl}/.extraheader`, `Authorization: basic ${tokenBase64}`]); | ||
| core.setSecret(tokenBase64); |
| }); | ||
|
|
||
| await expect(restorePersistedExtraheader(SERVER_URL, [header1, header2])).rejects.toThrow(/^git config --local --add http\.https:\/\/github\.com\/\.extraheader .+ failed/); | ||
| await expect(restorePersistedExtraheader(SERVER_URL, [header1, header2])).rejects.toThrow(/^git-config-credential failed/); |
| warning: vi.fn(), | ||
| error: vi.fn(), | ||
| notice: vi.fn(), | ||
| setSecret: vi.fn(), |
|
🎉 This pull request is included in a new release. Release: |
Three places in
actions/setup/jswhere GitHub tokens could appear unmasked in Actions debug logs (ACTIONS_STEP_DEBUG=true/ACTIONS_RUNNER_DEBUG=true) or always-visiblecore.warning()output.Fixes
dynamic_checkout.cjs—exec.execwriting theAuthorization: basic <tokenBase64>extraheader lacked{ silent: true }, causing the full command line (including the base64 credential) to echo viacore.debug(). The base64 form is never registered with the runner's masking engine, so it appears in plain text.git_auth_helpers.cjs—gitExecSilent(purpose-built to suppress credential-bearing command lines) leaked them anyway via itscatchblock:gitArgs.join(" ")in the error message embedded theAuthorization: basic …header value, which then surfaced incore.warning()from the caller.run_operation_update_upgrade.cjs— Token embedded in agit remote addURL with nocore.setSecret(token)and no{ silent: true }.GH_TOKEN(checked beforeGITHUB_TOKEN) is only auto-masked when sourced from${{ secrets.* }}; if set via plainenv:, the full URL with token would appear in debug logs.Scope
All other
gitinvocations in the directory were audited. The remainder usegitAuthEnv/GIT_CONFIG_*env vars,overridePersistedExtraheader,execGitSync(which already redacts://USER@in debug output), or already carrysilent: true.