> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pipefort.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CICD-SEC-1 — Unsafe YAML tag or multiplying anchor expansion

> The pipeline definition treated as an input, rather than as something a parser is assumed to survive.

| Field      | Value                                                                                                                                                          |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Rule ID    | `cicd-sec-1-yaml-parser-hardening`                                                                                                                             |
| Category   | `CICD-SEC-1`                                                                                                                                                   |
| Severity   | **HIGH** (unsafe tag) · MEDIUM (anchor expansion)                                                                                                              |
| Confidence | HIGH (tag) · MEDIUM (expansion)                                                                                                                                |
| Platforms  | GitHub Actions **and** GitLab CI (one rule ID)                                                                                                                 |
| OWASP      | [CICD-SEC-1: Insufficient Flow Control Mechanisms](https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-01-Insufficient-Flow-Control-Mechanisms) |
| Auto-fix   | ✗ (flag only)                                                                                                                                                  |

## What the check does

Two hazards, both decided on the **parsed document** rather than by
pattern-matching text.

### 1. A foreign YAML tag — HIGH, blocks

```yaml theme={null}
- run: !!python/object/apply:os.system ["id"]     # ← flagged
```

`!!python/object`, `!ruby/object`, `!!php/object` and friends instruct a parser
that honours them to construct a language-specific object — which for several
parsers means **executing code during load**, turning a config file into a
deserialization sink.

Nothing in a CI/CD pipeline definition has a legitimate reason to carry one. If
you did not add it, treat the file as untrusted and find out who did: a foreign
tag in a pipeline definition is an attack shape, not a style choice.

### 2. Multiplying anchor expansion — MEDIUM, warns

```yaml theme={null}
a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]      # ← flagged
```

This is the **billion-laughs** shape. Each level is an anchor whose body is a
list of aliases to the previous anchor, so the expanded size multiplies at every
stage: a few lines of YAML become gigabytes in memory, and the parser itself is
the denial of service.

## Nesting is what the rule keys on, not size

This is the part that makes the second half usable.

**Flat anchor reuse — one template shared by many jobs — is the ordinary,
correct way to share configuration, and it never multiplies** however widely it
is used:

```yaml theme={null}
.defaults: &defaults          # depth 0 — used by 60 jobs, never flagged
  image: alpine:3
  before_script:
    - make deps

build:
  <<: *defaults
  script: [make build]
```

A bomb *requires* an anchor that itself contains aliases to **other anchors**.
So the rule fires only when the alias graph is nested at least two levels deep
*and* the estimated expansion is large. Flat reuse cannot trip it at any scale,
and realistic two-level template inheritance (`.base` → `.withdeps` → jobs) with
small bodies stays far under the threshold.

The expansion figure in the finding is what the parser would actually build,
computed with memoization and saturating arithmetic — so measuring a bomb cannot
become one.

## GitLab's `!reference` is never flagged

```yaml theme={null}
build:
  script:
    - !reference [.tmpl, script]     # ← fine
```

`!reference` is a first-class part of the `.gitlab-ci.yml` language. It is
allowlisted alongside the YAML core schema (`!!str`, `!!int`, `!!bool`, `!!seq`,
`!!map`, …) and `!!merge`, the tag behind the `<<:` merge key.

## Auto-fix

**None.** A foreign tag is either an attack or a mistake, and both want a human.
An expansion threshold is a judgement about intent that a rewrite cannot make.

To resolve the first finding, remove the tag and express the value as plain YAML.
To resolve the second, flatten the anchor graph so no anchor's body contains
aliases to other anchors.

## Related rules

* [CICD-SEC-4 — Obfuscated expression or run script](/rules/cicd-sec-4-obfuscated-expression)
* [CICD-SEC-3 — Unpinned `include:` in GitLab CI](/rules/cicd-sec-3-gl-unpinned-include)
* [CICD-SEC-1 — `pull_request_target` trigger boundary confusion](/rules/cicd-sec-1-pr-target-dual-trigger)
