fix(gitlab): stop leaking the API token on redirect and globbing project paths - #3
Closed
elibosley wants to merge 1 commit into
Closed
Conversation
…ect paths Two narrow hardening fixes on top of the GitLab provider work. gitlab_api/gitlab_api_capture passed --location while supplying the API token through `header = "PRIVATE-TOKEN: ..."`. curl strips only the Authorization header on a cross-host redirect, so a 3xx from a self-managed instance would resend the token to whatever host it named. These are plain /api/v4 GETs against the configured base URL and have no reason to follow a redirect off it, so drop -L. GITLAB_PROJECTS was iterated as `for project in $GITLAB_PROJECTS`, which is subject to pathname expansion as well as word splitting. A plausible entry like `group/*` expands against the process CWD, so the advisory queue/stats/public-visibility scans would query whatever directory names happened to match. Split the list with `read -a` instead and emit only well-formed namespace/project paths. The field is telemetry-only and does not define runner scope, so a malformed entry is skipped rather than failing validation and blocking a fleet. gitlab_stats_refresh reads its project list on fd 3 because its per-project status scan is itself a `while read` on stdin.
elibosley
force-pushed
the
review/gitlab-provider-hardening
branch
from
August 5, 2026 21:03
3a66a1c to
cfb9535
Compare
This was referenced Aug 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Review follow-ups for unraid#44 — two mechanical fixes I could make safely without touching the design. Targets
feat/gitlab-providerso they land in the same PR. Everything else from the review is left for you, notes at the bottom.1. API token could be resent to a redirect target
gitlab_api/gitlab_api_captureusedcurl -fsSLwhile supplying the token throughheader = "PRIVATE-TOKEN: ...". curl strips onlyAuthorizationon a cross-host redirect — custom headers are resent — so a 3xx from a self-managed instance would hand the token to whatever host it named. These are plain/api/v4GETs against the configured base URL, so I just dropped-L.2.
GITLAB_PROJECTSwas glob-expandedfor project in $GITLAB_PROJECTSis subject to pathname expansion as well as word splitting.group/*is a plausible thing to type into a field labelled "Monitored projects", and it would expand against the process CWD — the advisory queue/stats/public-visibility scans would then query whatever directory names happened to match.Added
gitlab_projects_list, which splits withread -a(no globbing) and emits only well-formednamespace/projectpaths. Malformed entries are dropped rather than failinggitlab_validate_settings: the field is telemetry-only and doesn't define runner scope, so it shouldn't be able to block a fleet from starting.gitlab_stats_refreshreads the list on fd 3 because its per-project status scan is itself awhile readon stdin.Tests
Extended
tests/gitlab-policy.shto assert the list drops glob/relative/bare entries and does not expand against the CWD.gitlab-policy,provider-contract,config-parityandexec-csrfpass locally. I could not runtests/run-linux-checks.sh(no Docker on this machine);tests/provider-mocks.shfails on macOS for me at theglrt-shape check because BSD grep caps interval repetition at 255 and the pattern is{10,507}— that reproduces identically on your branch without my changes, so it's just a host limitation of running the suite outside the Linux container.Not addressed here — needs your call
exec.phpis the one I'd most want a second pair of eyes on. The platform path requires$csrf_tokento still be set while$_POST['csrf_token']and$_SERVER['HTTP_X_CSRF_TOKEN']are both unset. If a supported Unraid version also unsets$csrf_token, the standalone fallback then reads an already-removed$_POSTkey and every action — including all the existing GitHub ones — 403s.tests/exec-csrf.shfabricates that state in PHP so it can't confirm it. Worth a manual smoke test on each Unraid version in support, not just the one dev box.volumesentry, andgitlab_validate_settingsrequiresDIND=trueorSHARE_DOCKER_SOCK=true, so there's no configuration where job code lacks Docker access. It's disclosed clearly in the UI and the PR body, and the manager does need a daemon — but the job container doesn't, so a toggle would give operators a materially safer option. Your design call, not something I wanted to change unilaterally.fleet.lockis now held across a full image-update rollover (imageupdate_tick→imageupdate_rollover→drain_and_recreateper slot). WithIMAGE_DRAIN_TIMEOUT=3600and GitLab'sshutdown_timeout=7200that can be hours during which UI Start/Stop/Scale/Recycle fail on the 20sflock -w. The lock is what makes the roll safe so I'd keep it, but the UI probably wants to distinguish "rollover in progress" from a generic busy error.