Skip to content

CVE-2017-18342 — PyYAML default `load` resolves arbitrary tags

PyYAML’s yaml.load() resolved !!python/object and friends without an explicit safe loader, making any attacker-controlled YAML a code-execution primitive. The CVE is the formal advisory; the behaviour predates the CVE by the better part of a decade. PyYAML 5.1 added a deprecation warning when Loader= was omitted; PyYAML 6.0 made the omission a TypeError. Most repos have call sites that predate either change.

Affected versions

  • PyYAML ≤ 3.13 — vulnerable, no warning.
  • PyYAML 4.x — never released widely.
  • PyYAML 5.1+ — emits a YAMLLoadWarning when Loader= is omitted; still resolves unsafe tags by default.
  • PyYAML 6.0+ — yaml.load() raises TypeError without an explicit Loader. The behaviour was made safe by removal.

Indicator-of-exposure

Any call site of yaml.load(...) (without Loader=), yaml.load(..., Loader=yaml.Loader), yaml.load(..., Loader=yaml.UnsafeLoader), or yaml.full_load(...) on untrusted input.

Detection:

git grep -n "yaml\\.load\\b\\|yaml\\.full_load\\b\\|Loader=yaml\\.\\(Loader\\|UnsafeLoader\\|FullLoader\\)"

Whether the call is exposed depends on the data flow: attacker-controlled YAML (file upload, HTTP body, partner feed) is exposure; a trusted application config file is not — though the safe shape costs nothing on trusted input either.

Remediation strategy

This CVE has a generic recipe that covers it directly:

This per-CVE recipe overlays the broader generic recipe with two CVE-specific actions:

  1. Pin PyYAML to ≥6.0 (or ≥5.1 with Loader=yaml.SafeLoader on every call) to lock in the safe-default behaviour at the library level.
  2. Re-scan with the SCA tool to confirm CVE-2017-18342 is no longer reported against the post-fix lockfile.

The prompt

You are remediating CVE-2017-18342 (PyYAML default-loader
RCE) in this repository. Output a PR or a TRIAGE.md.

## Step 0 — Inventory

1. List every `yaml.load`, `yaml.full_load`,
   `yaml.load(..., Loader=yaml.Loader)`,
   `yaml.load(..., Loader=yaml.UnsafeLoader)`,
   `yaml.load(..., Loader=yaml.FullLoader)` call.
2. Read the lockfile and confirm the pinned PyYAML version.

## Step 1 — Apply the generic fix pattern

Follow the recipe at
[/prompt-library/general/classic-vulnerable-defaults/pyyaml-load/]
end-to-end. Replace every unsafe call with `yaml.safe_load`,
or install the import-time shim, or both.

## Step 2 — Pin PyYAML

1. Pin PyYAML to ≥6.0 in the lockfile / requirements file.
2. Run the project's test suite to surface any breakage from
   the 5.x → 6.x bump.
3. If the project depends on a transitive consumer of
   PyYAML <6 (`pip-tools` resolves a downgrade), document
   the constraint in the PR body. The agent does not silently
   downgrade.

## Step 3 — Verify

1. Re-run the SCA scanner. CVE-2017-18342 must show as fixed
   or not present.
2. Add the standard PyYAML safe-load test from the generic
   recipe (a payload with `!!python/object/apply:os.system`
   raises `yaml.constructor.ConstructorError`).

## Step 4 — Open the PR

- Branch: `remediate/cve-2017-18342-pyyaml`.
- Title: `[Security][CVE-2017-18342] safe_load + pin PyYAML ≥6`.
- Body: per-call-site list, lockfile diff, SCA before/after,
  test addition, any downstream pin notes.
- Label: `sec-auto-remediation`.

## Stop conditions

- A transitive dependency requires PyYAML <6 and cannot be
  upgraded without a coordinated cross-repo change.
- A custom YAML tag the codebase legitimately uses requires a
  non-Safe loader and the agent cannot determine whether the
  tag's resolver is itself safe.

## Scope

- Do not bundle unrelated CVEs.
- Do not silently re-pin downstream constraints.

Verification — what the reviewer looks for

  • Every call site touched, or shim installed, with a clear rationale per call.
  • PyYAML pinned to ≥6.0.
  • SCA output shows CVE-2017-18342 cleared.
  • Behaviour-preservation test for any custom YAML tag the codebase uses.

Watch for

  • yaml.load_all and yaml.full_load_all. Same problem, same fix.
  • Indirect callers. Some libraries ship their own yaml.load(...) wrapper — fix the library or pin it past the patched version.
  • PyYAML 6.x parser changes. A handful of edge-case documents parse differently in 6.x (octal-number rules, some boolean shortcuts). Run the project’s tests.

Related