GHSA-85v3-4m8g-hrh6

Suggest an improvement
Source
https://github.com/advisories/GHSA-85v3-4m8g-hrh6
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-85v3-4m8g-hrh6/GHSA-85v3-4m8g-hrh6.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-85v3-4m8g-hrh6
Aliases
Published
2026-04-01T22:28:49Z
Modified
2026-07-13T07:26:50Z
Severity
  • 4.4 (Medium) CVSS_V3 - CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N CVSS Calculator
Summary
Copier `_subdirectory` allows template root escape via parent-directory traversal
Details

Summary

Copier's _subdirectory setting is documented as the subdirectory to use as the template root. However, the current implementation accepts parent-directory traversal such as .. and uses it directly when selecting the template root.

As a result, a template can escape its own directory and make Copier render files from the parent directory without --UNSAFE.

Details

The relevant code path is:

  1. the template defines _subdirectory
  2. Copier renders that string
  3. template_copy_root returns self.template.local_abspath / subdir
  4. Copier walks that directory as the template root

Relevant code:

The effective sink is:

subdir = self._render_string(self.template.subdirectory) or ""
return self.template.local_abspath / subdir

There is no check that the resulting path stays inside the template directory.

The documentation for _subdirectory describes it as:

Subdirectory to use as the template root when generating a project.

and explains it as a way to separate template metadata from template source code:

https://github.com/copier-org/copier/blob/7aa7021bd73797c982492bac3535515d4484fdb7/docs/configuring.md#L1582-L1646

That description fits values like template or poetry, but not ...

PoC

PoC 1: _subdirectory: .. escapes to the parent directory

mkdir -p root/template dst
echo 'loot' > root/loot.txt
printf '%s\n' '_subdirectory: ..' > root/template/copier.yml

copier copy --overwrite root/template dst
find dst -maxdepth 3 -type f | sort
cat dst/loot.txt

Expected output includes:

dst/loot.txt
dst/template/copier.yml
loot

This shows Copier is rendering from root/ rather than from root/template/.

Impact

If a user runs Copier on an untrusted template, that template can change the effective template root and make Copier render files from outside the intended template directory.

Practical impact:

  • template-root escape via ..
  • rendering of parent-directory files that were not meant to be part of the template
  • possible without --UNSAFE
Database specific
{
    "cwe_ids":  [
        "CWE-22"
    ],
    "github_reviewed":  true,
    "github_reviewed_at":  "2026-04-01T22:28:49Z",
    "nvd_published_at":  "2026-04-02T19:21:32Z",
    "severity":  "MODERATE"
}
References

Affected packages

PyPI / copier

Package

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
9.14.1

Affected versions

2.*
2.0.0
2.0.1
2.1.0
2.2.1
2.2.2
2.2.3
2.3
2.3.1
2.3.2
2.3.3
2.4.0
2.4.1
2.4.2
2.5.0
2.5.1
3.*
3.0.0a3
3.0.0a5
3.0.0a6
3.0.0a7
3.0.0a8
3.0.0b1
3.0.1
3.0.2
3.0.3
3.0.4
3.0.5
3.0.6
3.1.0
3.2.0
4.*
4.0.0
4.0.1
4.0.2
4.1.0
5.*
5.0.0
5.1.0
6.*
6.0.0a0
6.0.0a2
6.0.0a3
6.0.0a4
6.0.0a5
6.0.0a6
6.0.0a7
6.0.0a9
6.0.0b0
6.0.0
6.1.0
6.2.0
7.*
7.0.1
7.1.0a0
7.1.0
7.2.0
8.*
8.0.0
8.1.0
8.2.0
8.3.0
9.*
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
9.9.1
9.10.0
9.10.1
9.10.2
9.10.3
9.11.0
9.11.1
9.11.2
9.11.3
9.12.0
9.13.0
9.13.1
9.14.0

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-85v3-4m8g-hrh6/GHSA-85v3-4m8g-hrh6.json"