Skip to content

safe_outputs job strips git credentials (persist-credentials: false), breaking git push/fetch #40159

Description

@dsyme

Summary

In the safe_outputs job, the checkout steps are generated by the same CheckoutManager generators the agent job uses (GenerateDefaultCheckoutStep / GenerateAdditionalCheckoutSteps). Those generators emit persist-credentials: false, so actions/checkout runs its post-checkout "Removing auth" step and strips the http.<server>/.extraheader credential and the embedded credential helper config from each checkout's .git/config.

That security default is correct for the agent job (the untrusted agent must not be able to read credentials from disk), but it is wrong for the safe_outputs job, which legitimately performs git fetch / git push against the checked-out repositories (e.g. push_to_pull_request_branch, create_pull_request).

Evidence

Failing run (github/github-automation ci-perf):

  • push_to_pull_request_branch failed with: Failed to apply bundle: Failed to fetch bundle: fatal: couldn't find remote ref refs/heads/dsyme/ci-perf/...
  • Step 7 ("Checkout ./github-automation") and the cross-repo checkout of github/github both run persist-credentials: false, triggering actions/checkout's Removing auth / Removing HTTP extra header post-step.

After auth is stripped, the safe_outputs job relies on a fragile combination to re-establish credentials:

  1. a "Configure Git credentials" step that does git -C <path> remote set-url origin https://x-access-token:${GIT_TOKEN}@.../repo.git, and
  2. per-operation GIT_CONFIG_* (http.<server>/.extraheader) env injected by the handler (getGitAuthEnv).

This layering is brittle (token-in-URL vs extraheader precedence, per-remote re-auth, shallow/partial-clone interactions) and is the kind of state that leads to fetch/push failures in the safe_outputs job.

Expected behavior

For the safe_outputs job checkout generation (now unified with the agent job), credentials should be retained (persist-credentials: true, no post-checkout auth removal) because subsequent git push / git fetch are allowed and expected in that job. The agent job must keep persist-credentials: false.

Proposed fix

Add a "keep credentials for push" mode to CheckoutManager that the safe_outputs path (buildSharedPRCheckoutSteps) enables. In that mode the default and additional checkout generators emit persist-credentials: true and skip the credential-cleanup step, so the push-capable token installed at checkout time remains available for the handlers. The agent job is unchanged.

Affected code

  • pkg/workflow/checkout_step_generator.go (GenerateDefaultCheckoutStep, generateCheckoutStepLines)
  • pkg/workflow/checkout_manager.go (CheckoutManager)
  • pkg/workflow/compiler_safe_outputs_steps.go (buildSharedPRCheckoutSteps)

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions