Update dependency copier to v9.14.1 [SECURITY]#279
Open
renovate[bot] wants to merge 1 commit intomainfrom
Open
Update dependency copier to v9.14.1 [SECURITY]#279renovate[bot] wants to merge 1 commit intomainfrom
renovate[bot] wants to merge 1 commit intomainfrom
Conversation
c02b087 to
f1f67f1
Compare
abf6131 to
f1f67f1
Compare
f1f67f1 to
abf6131
Compare
abf6131 to
9ddde51
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
==9.3.1→==9.14.1GitHub Vulnerability Alerts
CVE-2025-55201
Impact
Copier's current security model shall restrict filesystem access through Jinja:
{% include ... %}, which is limited by Jinja to reading files from the subtree of the local template clone in our case.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,--trustflag. As it turns out, a safe template can currently read and write arbitrary files because we expose a fewpathlib.Pathobjects in the Jinja context which have unconstrained I/O methods. This effectively renders our security model w.r.t. filesystem access useless.Arbitrary read access
Imagine, e.g., a malicious template author who creates a template that reads SSH keys or other secrets from well-known locations, perhaps "masks" them with Base64 encoding to reduce detection risk, and hopes for a user to push the generated project to a public location like github.com where the template author can extract the secrets.
Reproducible example:
Read known file:
Read unknown file(s) via globbing:
Arbitrary write access
Imagine, e.g., a malicious template author who creates a template that overwrites or even deletes files to cause havoc.
Reproducible examples:
Overwrite known file:
Overwrite unknown file(s) via globbing:
Delete unknown file(s) via globbing:
Delete unknown files and directories via tree walking:
CVE-2025-55214
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,--trustflag. 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 builtinpathjoinJinja filter and its builtin_copier_conf.sepvariable, 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:
Write access via generated absolute path
Reproducible example:
POSIX:
Windows (PowerShell):
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(orPYTHONOPTIMIZE=x) removes asserts, so these guards may be ineffective. In addition, this scenario will prompt for overwrite confirmation or require the--overwriteflag for non-interactive mode; yet malicious file writes might go unnoticed.CVE-2026-23968
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,--trustflag. As it turns out, a safe template can currently include arbitrary files/directories outside the local template clone location by using symlinks along with_preserve_symlinks: false(which is Copier's default setting).Imagine, e.g., a malicious template author who creates a template that reads SSH keys or other secrets from well-known locations and hopes for a user to push the generated project to a public location like github.com where the template author can extract the secrets.
Reproducible example:
Illegally include a file in the generated project via symlink resolution:
Illegally include a directory in the generated project via symlink resolution:
Patches
n/a
Workarounds
n/a
References
n/a
CVE-2026-23986
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,--trustflag. As it turns out, a safe template can currently write to arbitrary directories outside the destination path by using directory a symlink along with_preserve_symlinks: trueand a generated directory structure whose rendered path is inside the symlinked directory. 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.Note
At the time of writing, the exploit is non-deterministic, as Copier walks the template's file tree using
os.scandirwhich yields directory entries in arbitrary order.Reproducible example (may or may not work depending on directory entry yield order):
Patches
n/a
Workarounds
n/a
References
n/a
CVE-2026-34726
Summary
Copier's
_subdirectorysetting 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:
_subdirectorytemplate_copy_rootreturnsself.template.local_abspath / subdirRelevant code:
The effective sink is:
There is no check that the resulting path stays inside the template directory.
The documentation for
_subdirectorydescribes it as: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
templateorpoetry, but not...PoC
PoC 1:
_subdirectory: ..escapes to the parent directoryExpected output includes:
This shows Copier is rendering from
root/rather than fromroot/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:
..--UNSAFECVE-2026-34730
Summary
Copier's
_external_datafeature allows a template to load YAML files using template-controlled paths. The documentation describes these values as relative paths from the subproject destination, so relative paths themselves appear to be part of the intended feature model.However, the current implementation also allows destination-external reads, including:
../secret.yml/tmp/secret.ymland then exposes the parsed contents in rendered output.
This is possible without
--UNSAFE, which makes the behavior potentially dangerous when Copier is run against untrusted templates. I am not certain this is unintended behavior, but it is security-sensitive and appears important to clarify.Details
The relevant flow is:
_external_dataload_answersfile_data(dst_path, rendered_path, warn_on_missing=True)load_answersfile_data()opensPath(dst_path, answers_file)directly_external_data.<name>during renderingRelevant code:
The sink is:
There is no containment check to ensure the resulting path stays inside the subproject destination.
This is notable because Copier already blocks other destination-escape paths. Normal render-path traversal outside the destination is expected to raise
ForbiddenPathError, and that behavior is explicitly covered by existing tests in https://github.com/copier-org/copier/blob/7aa7021bd73797c982492bac3535515d4484fdb7/tests/test_copy.py#L1289-L1332._external_datadoes not apply an equivalent containment check.The public documentation describes
_external_datavalues as relative paths "from the subproject destination" in https://github.com/copier-org/copier/blob/7aa7021bd73797c982492bac3535515d4484fdb7/docs/configuring.md#L944-L1005, with examples using.copier-answers.ymland.secrets.yaml. That clearly supports relative-path usage, but it does not clearly communicate that a template may escape the destination with../...or read arbitrary absolute paths. Because this behavior also works without--UNSAFE, it seems worth clarifying whether destination-external reads are intended, and if so, whether they should be documented as security-sensitive behavior.PoC
PoC 1:
_external_datareads outside the destination with../Expected output:
PoC 2:
_external_datareads an absolute pathExpected output:
Impact
If untrusted templates are in scope, a malicious template can read attacker-chosen YAML-parseable local files that are accessible to the user running Copier and expose their contents in rendered output.
Practical impact:
yaml.safe_load--UNSAFERelease Notes
copier-org/copier (copier)
v9.14.1Compare Source
Refactor
YieldExtensionself-containedSecurity
--trustfor_external_datapaths outside subproject root_subdirectorypath outside template rootv9.14.0Compare Source
Feat
--answers-fileflag tocheck-updatecommandFix
HEADcheck-updatecommand help outputv9.13.1Compare Source
Fix
v9.13.0Compare Source
Feat
check-updateto check for new template version (#2463)Refactor
run_*functions instead of internalWorker.run_*methodsv9.12.0Compare Source
Feat
Phaseenum at package levelFix
update algorithm
during updates
Refactor
settingsmodule and its symbols**kwargswith explicit parameters inrun_{copy,recopy,update}functionsv9.11.3Compare Source
Fix
template
conflicts (#2432)
pathspecv1.0.0+v9.11.2Compare Source
Fix
(#2427)
Security
v9.11.1Compare Source
Fix
_copier_confvariable
v9.11.0Compare Source
Feat
clean (#2369)
Fix
chmodis not allowedRefactor
v9.10.3Compare Source
Fix
excluded paths
_excludelist in new template version whenupdating
v9.10.2Compare Source
Fix
v9.10.1Compare Source
Fix
v9.10.0Compare Source
Feat
copier.yml(#2251)Fix
v9.9.1Compare Source
Security
pathlib.PurePathv9.9.0Compare Source
Feat
Fix
core.fsmonitor=true(#2151)v9.8.0Compare Source
Feat
:current:for referring to the current templateref
Fix
_copier_conf.answers_filevia Jinjacontext hook
v9.7.1Compare Source
Refactor
_toolsinstead oftoolsv9.7.0Compare Source
Feat
TaskErrorexception on task errorsInteractiveSessionErrorwhen prompting in non-interactive environmentFix
<CONFIG_ROOT>/copieras settings directory on Windows (#2071)when: falsequestionsRefactor
_prefixv9.6.0Compare Source
Feat
_copier_operationvariable (#1733)_copier_phasecontext variableFix
--data-file$fileif$file.tmplexists when subdirectory is usedRefactor
v9.5.0Compare Source
Feat
defaultsvalues (fix #235)Fix
.gitignorefile(#1886)
v9.4.1Compare Source
Fix
preserve_symlinks: falsefor directories (#1820)v9.4.0Compare Source
Fix
--skip-answeredis usedRefactor
keep_trailing_newlinemore idiomaticallyPerf
Configuration
📅 Schedule: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.