Skip to content

fix: prevent secret leakage in git invocations in JS action scripts - #50730

Merged
pelikhan merged 4 commits into
mainfrom
copilot/inspect-git-invocation-js
Aug 6, 2026
Merged

fix: prevent secret leakage in git invocations in JS action scripts#50730
pelikhan merged 4 commits into
mainfrom
copilot/inspect-git-invocation-js

Conversation

Copilot AI commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Three places in actions/setup/js where GitHub tokens could appear unmasked in Actions debug logs (ACTIONS_STEP_DEBUG=true / ACTIONS_RUNNER_DEBUG=true) or always-visible core.warning() output.

Fixes

  • dynamic_checkout.cjsexec.exec writing the Authorization: basic <tokenBase64> extraheader lacked { silent: true }, causing the full command line (including the base64 credential) to echo via core.debug(). The base64 form is never registered with the runner's masking engine, so it appears in plain text.

  • git_auth_helpers.cjsgitExecSilent (purpose-built to suppress credential-bearing command lines) leaked them anyway via its catch block: gitArgs.join(" ") in the error message embedded the Authorization: basic … header value, which then surfaced in core.warning() from the caller.

    // Before — credential value ends up in core.warning()
    throw new Error(`git ${gitArgs.join(" ")} failed: ${stderrBuf.trim() || ...}`);
    
    // After
    throw new Error(`git-config-credential failed: ${stderrBuf.trim() || ...}`);
  • run_operation_update_upgrade.cjs — Token embedded in a git remote add URL with no core.setSecret(token) and no { silent: true }. GH_TOKEN (checked before GITHUB_TOKEN) is only auto-masked when sourced from ${{ secrets.* }}; if set via plain env:, the full URL with token would appear in debug logs.

Scope

All other git invocations in the directory were audited. The remainder use gitAuthEnv/GIT_CONFIG_* env vars, overridePersistedExtraheader, execGitSync (which already redacts ://USER@ in debug output), or already carry silent: true.

- 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>
Copilot AI changed the title fix: mask secrets in git invocations in JS action scripts fix: prevent secret leakage in git invocations in JS action scripts Aug 6, 2026
Copilot AI requested a review from pelikhan August 6, 2026 01:13
Comment thread actions/setup/js/dynamic_checkout.cjs Outdated
// 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 });

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot use silent git exec helper

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Exported gitExecSilent from git_auth_helpers.cjs and replaced the inline exec.exec(..., { silent: true }) call with gitExecSilent in dynamic_checkout.cjs.

@pelikhan

pelikhan commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

@copilot use core.setSecret to also mask secrets

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The 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 actions/setup/js where tokens could leak via debug logs, each fixed with precision (adding silent: true, redacting error messages, and adding core.setSecret()).

Tests included — both affected modules (git_auth_helpers, run_operation_update_upgrade) have test updates to cover the fixes.

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! 🔒

Generated by ✅ Contribution Check · auto · 52.4 AIC · ⊞ 8.7K ·

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@copilot use core.setSecret to also mask secrets

Added core.setSecret(token) and core.setSecret(tokenBase64) in both dynamic_checkout.cjs (before building the extraheader) and git_auth_helpers.cjs (overridePersistedExtraheader, which builds the same base64 credential). run_operation_update_upgrade.cjs already had the core.setSecret(token) call.

@pelikhan
pelikhan marked this pull request as ready for review August 6, 2026 01:30
Copilot AI balanced review requested due to automatic review settings August 6, 2026 01:31
@pelikhan
pelikhan merged commit 9d4bc2d into main Aug 6, 2026
2 checks passed
@pelikhan
pelikhan deleted the copilot/inspect-git-invocation-js branch August 6, 2026 01:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment on lines +114 to +116
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(),
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.85.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants