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
YAMLLoadWarningwhenLoader=is omitted; still resolves unsafe tags by default. - PyYAML 6.0+ —
yaml.load()raisesTypeErrorwithout an explicitLoader. 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:
- See Classic Vulnerable Defaults → PyYAML
yaml.loadfor the durable fix pattern.
This per-CVE recipe overlays the broader generic recipe with two CVE-specific actions:
- Pin PyYAML to ≥6.0 (or ≥5.1 with
Loader=yaml.SafeLoaderon every call) to lock in the safe-default behaviour at the library level. - 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_allandyaml.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
- Classic Vulnerable Defaults → PyYAML
yaml.load— the durable, tool-agnostic recipe this overlays. - Vulnerable Dependency Remediation — the generic workflow.
- Python pickle — sibling Python deserialization risk.