BUG BOUNTYFIELD MANUAL
Reusable module
Markdown
0 / 6 checkedChecks last until this page reloads.

GitLab pipelines: contribution, job token and runner boundaries

Trace GitLab execution context, included configuration, downstream inputs, job-token permissions and runner reuse using private synthetic fixtures.

Investigation sequence
  1. 01Pin version and pipeline context
  2. 02Resolve included configuration
  3. 03Map job and downstream authority
  4. 04Compare one private fixture
  5. 05Reset runner and artifacts

At each step: retain the control → record the observation → continue only while the next boundary is understood.

Used in these playbooks#

Scope and fixture contract#

Use an owned GitLab project pair and disposable runner, or owner-supplied configuration exports. Pin GitLab and Runner versions, feature flags, repository commit, pipeline ID, source project, target project and triggering user. Create a private synthetic artifact in project B and one job in A. Control over A's contribution or job must not acquire B's private authority or a release identity beyond the stated integration. Reuse CI and release tracing for artifact provenance and source data flow for executable input.

1. Establish which pipeline really runs#

Trace merge-request source, configuration revision, execution project and trigger actor independently. Fork pipelines ordinarily run with fork resources. A parent member can run a fork merge-request pipeline in the parent context, using fork-controlled configuration with parent resources and that member's permissions. Inspect the exact settings and approval path. Protected variables and runners have additional requirements, including same-project protected branches; do not infer their exposure merely from parent execution. Re-running an older pipeline can retain its original context. GitLab merge request pipelines

Build one row per job: who edits the YAML, who changes included files, which commit is fetched, which scripts execute, and what the resulting identity can do. Package installation, test discovery and generated scripts are executable inputs even when the visible job looks like a harmless test command.

2. Follow configuration and downstream trust#

Resolve include, extends, component inputs, dynamic child configuration and multi-project triggers before judging a job. Capture the merged configuration through an owner-provided export. For remote includes, compare a pinned expected file with a changed inert fixture; supported include:integrity verifies a SHA-256 digest and rejects a mismatch. A mutable reference is a candidate until the lower-trust editor and privileged consumer are connected. GitLab YAML reference

Track forwarded variables and generated child YAML into the receiving pipeline. A downstream job may interpret a value as a shell command, artifact selector, deployment environment or cloud role. Compare the allowed value and one disallowed synthetic value at that exact sink. Preserve the downstream pipeline's own policy and actor, since upstream success does not establish downstream entitlement. Downstream pipelines

3. Separate token restrictions from secret masking#

A job token is limited by its API capabilities and the triggering user's authority. Review the receiving project's allowlist, feature visibility and any fine-grained restrictions together. Allowlisting a project does not independently grant its users new project permissions. Distinguish currently running jobs from expired-token attempts. Review repository-push settings for the deployed GitLab version rather than assuming every job token is permanently read only. GitLab job tokens

Masked and hidden variables address exposure in interfaces; code already authorized to consume a variable can still misuse it. With a dummy value, identify the exact job receiving it, environment scope and later executable consumer. Never print real CI variables to inventory privileges. GitLab CI variables

4. Reproduce one boundary using inert controls#

Candidate Controlled comparison Required evidence
Fork code enters parent authority Trusted base versus inert fork fixture Configuration SHA, execution project, actor and marker-only result
Job A reaches private project B Allowed integration versus disallowed project/actor Exact synthetic resource, token context and accepted/denied response
Runner leaks previous job state Two owned jobs on a disposable runner Known marker survives across a boundary that promises isolation
Publisher consumes wrong artifact Expected producer versus wrong fixture run Digest, selected run and actual trusted consumption

For runners, inspect executor, host/socket mounts, shared working directories, cache policy and whether private images can be reused by unauthorized jobs. Use one predetermined synthetic marker path and one owned image. A shell executor or privileged container is a risk signal; the demonstrated issue is unintended cross-job access. Do not inspect other users' workspaces. Runner isolation guidance

Local command cheat sheet#

These searches read a local clone and execute no CI jobs. Follow results into referenced files; absence of a match is not coverage proof.

rg --files --hidden -g '!.git' -g '*gitlab*' -g '*.yml' -g '*.yaml' ./repo
rg -n --hidden -g '!.git' -g '*.yml' -g '*.yaml' \
  'include:|extends:|trigger:|forward:|id_tokens:|environment:' ./repo
rg -n --hidden -g '!.git' \
  'CI_JOB_TOKEN|CI_PIPELINE_SOURCE|CI_MERGE_REQUEST|privileged|pull_policy' ./repo

Evidence and completion#

  • Pipeline project, configuration revision and triggering actor recorded separately.
  • Parent/fork and protected-resource assumptions verified for the installed version.
  • Included configuration, downstream inputs and executable consumers traced.
  • Token capability, actor permission and receiving-project policy distinguished.
  • Allowed and denied cases use the same private synthetic resource.
  • Job logs contain no usable credentials; fixtures and runner state are removed.

A report should state the lowest actor that can initiate the chain, required maintainer interaction, exact acquired capability and secure comparison. Intended public artifacts, a rejected token, or deliberate shared runner trust do not establish a private boundary failure.

Vulnerability reverse references#

Nearby shared procedures#

Object, function, and property authorization · Authentication, recovery, federation, and session lifecycle · Trace input into queries, commands, and templates · Server-side fetching and network trust boundaries · Browser execution, cross-origin reads, and forged actions · Uploads, downloads, paths, archives, and XML · Workflow invariants, replay, idempotency, and races · REST, GraphQL, gRPC, WebSocket, and SSE permission parity