[FF] dap_git_credential_helper -- Authenticate Duo Agent Platform git operations with a credential helper

Summary

Roll out the feature currently behind the dap_git_credential_helper feature flag.

When enabled, Duo Agent Platform git operations authenticate through a credential helper instead of a token embedded in the origin URL. The flag also turns on FF_GIT_URLS_WITHOUT_TOKENS and drops the sed-based git remote set-url rewrite that previously wrote the OAuth token into .git/config.

Note

Process and guidance live in the docs — this issue is just the commands and a place to track the rollout. "Rolling out" means incrementally enabling the flag on GitLab.com to validate stability — it is not the same as releasing the feature, which happens when the flag is removed. Feature flag controls · Feature flag lifecycle

Preconditions

These must be confirmed before the flag is enabled anywhere, including staging.

  • get_sources dispatch-time token staleness. With the flag on, the Runner's own get_sources clone authenticates with the composite-identity OAuth token instead of job-lifetime CI_JOB_TOKEN. Since get_sources runs at job start, this only fails if the token is already stale or near-expiry at dispatch (e.g. a queueing delay between token mint and job start) - not from the 1h TTL elapsing mid-job. Confirm the queue-to-dispatch gap stays comfortably inside the token TTL before widening beyond canary.

    This is narrower than it may first appear: the broader "1h composite-token TTL vs 2h job timeout" mid-job risk is real, but it is pre-existing and unconditional on this flag - the sed-based path this MR replaces already authenticates the same ongoing git operations (run_command, run_git_command) with this same token today, at full production scale. This flag's rollout percentage does not change exposure to that risk, so it does not block rollout here. Tracked separately in #623427, against the OAuth-token git-auth behaviour in general and decoupled from this rollout.

    Discussion: !243872#note_3673850333, !243872#note_3677581132, !243872#note_3686509543.

  • Runner fleet includes gitlab-org/gitlab-runner!6729 (merged 2026-06-23). That MR makes the credential helper visible to user-authored git commands by writing a per-job seed file and exporting GIT_CONFIG_GLOBAL. Without it, git run outside Runner's own clone (which is how the agent runs git) does not see the helper and fails to authenticate. Confirm the runners serving Duo Agent Platform jobs are on a version containing it.

  • FF_USE_CONCRETE=true is not in play for DAP jobs. !6729 (merged) explicitly defers the step-runner path: setupGlobalGitConfig is scoped to the get_sources stage, so the seed file is deleted before user-script stages run. If DAP executors run concrete, the fix does not apply and this rollout should not proceed.

  • run_git_command (LSP) authenticates successfully. It builds its own inline credential helper reading $GIT_PASSWORD rather than using the installed git config, and previously failed with exit 128 against a credential-free origin. See !243872#note_3557360524.

  • No second remote or host in the coding environment. The credential helper is installed as credential.<gitlab-url>.helper, built from Gitlab.config.gitlab.url — the full instance URL, including any relative-URL path — rather than the bare credential.helper key, so the OAuth password is only offered when git is challenged by the GitLab instance; helpers for other hosts (submodules, LFS, bundle URIs) are unaffected. Path-scoped keys do match without useHttpPath, so on a relative-URL install (https://host/gitlab) the path narrows the scope further, to the GitLab instance path rather than the whole host. The helper's own stdin check still compares protocol://host only, since git never sends a path in the credential request. Submodules are not fetched (the Runner default GIT_SUBMODULE_STRATEGY: none — not pinned by DAP, so a project could override it) and GIT_LFS_SKIP_SMUDGE=1 is set, as a second layer. Raised in !243872#note_3672274449; scoping corrected in !243872#note_3760616037 and !243872#note_3760903580; reconfirm before widening if the coding environment ever gains a second host.

  • fix_pipeline_experimental is off for the projects being enabled. With that flag on for a project or its root ancestor, Ai::Catalog::FoundationalFlow::Definitions::FixPipeline#flow_version_resolver routes Fix Pipeline away from fix_pipeline/v1 1.0.3 (clean) to fix_pipeline/experimental 1.0.0, whose git_setup entry point still runs git remote set-url origin with the token in the URL - defeating the point of the credential helper for those jobs. This cannot be detected from the job script, which finishes before the flow's first component runs. Two experimental flow configs need patching first, tracked in ai-assist#2778.

Historical context: gitlab-org/gitlab-runner#38268 tracked the 17.5 regressions (submodule auth, Windows credential-helper erase, GCM credential caching) that caused FF_GIT_URLS_WITHOUT_TOKENS to be defaulted back off in 17.5.1. It is closed (17.6), so it is not a blocker, but it is a useful checklist of the failure modes to watch for during rollout.

What could go wrong?

Blast radius is limited to Duo Agent Platform workflow jobs; the flag does not affect regular CI. The failure mode is a hard one — git operations fail with exit 128 or could not read Username for 'https://gitlab.com' — so it surfaces immediately rather than degrading silently. There is no data-loss risk. Rollback is a single chatops command and takes effect on the next workflow start; already-running jobs keep the configuration they started with.

The exception is a Runner too old to honour FF_GIT_URLS_WITHOUT_TOKENS: the clone succeeds with the token still embedded in the origin URL, so the security objective is missed with nothing surfacing it. Confirm the fleet version rather than expecting to detect it at runtime.

Rollout

Run all production /chatops in #production and cross-post the results to the team channel. Background: incremental rollout process, feature actors.

Non-production

/chatops gitlab run feature set dap_git_credential_helper 50 --actors --dev --pre --staging --staging-ref
/chatops gitlab run feature set dap_git_credential_helper true --dev --pre --staging --staging-ref

Production — canary projects first:

/chatops gitlab run feature set --project=gitlab-org/gitlab dap_git_credential_helper true
/chatops gitlab run feature set --group=gitlab-org dap_git_credential_helper true

Then percentage rollout (wait ≥15 min between steps, watch dashboards). Do not start this until the preconditions above are confirmed:

/chatops gitlab run feature set dap_git_credential_helper 1 --actors
/chatops gitlab run feature set dap_git_credential_helper 10 --actors
/chatops gitlab run feature set dap_git_credential_helper 25 --actors
/chatops gitlab run feature set dap_git_credential_helper 50 --actors
/chatops gitlab run feature set dap_git_credential_helper 100 --actors

Before global rollout

Confirm the relevant gotchas before going to 100% — see enabling a feature for GitLab.com:

Cleanup

Remove the flag once deemed stable — see cleaning up. Remove the flag and its YAML definition from the codebase, then:

/chatops gitlab run release check https://gitlab.com/gitlab-org/gitlab/-/merge_requests/243872 19.4
/chatops gitlab run feature delete dap_git_credential_helper --dev --pre --staging --staging-ref --production

Rollback

/chatops gitlab run feature set dap_git_credential_helper false                                              # production
/chatops gitlab run feature set dap_git_credential_helper false --dev --pre --staging --staging-ref          # non-production
/chatops gitlab run feature delete dap_git_credential_helper --dev --pre --staging --staging-ref --production  # remove entirely

Related: https://gitlab.com/gitlab-org/gitlab/-/work_items/593467

Edited by Andras Herczeg