-
-
Notifications
You must be signed in to change notification settings - Fork 222
Description
Summary
I encountered an issue where copier update
fails with ForbiddenPathError
when the destination directory contains symlinks pointing outside the project directory, even though these symlinks represent legitimate use cases.
Steps to Reproduce
- Create a project using copier
- Create a symlink in the destination that points outside the project directory:
ln -s /external/path/.env.local .env.local
- Run
copier update
on the project - Observe
ForbiddenPathError: ".env.local" is forbidden
Expected Behavior
The update should succeed, as the symlink itself is within the project directory and represents a legitimate configuration pattern (e.g., environment files stored securely outside the project).
Actual Behavior
copier.errors.ForbiddenPathError: ".env.local" is forbidden
Root Cause Analysis
The issue appears to be in _main.py
around line 725, where the security check resolves symlinks before validating paths:
if not cwd.joinpath(dst_relpath).resolve().is_relative_to(cwd):
raise ForbiddenPathError(path=dst_relpath)
When a symlink points outside the project, .resolve()
returns the external path, which triggers the forbidden path check even though the symlink itself is legitimately within the project.
Use Case Context
This pattern is common for:
- Environment files (
.env.local
→ external secrets directory) - Configuration files stored outside version control
- Shared resources between projects
The current behavior prevents these legitimate patterns while the security intent (preventing path traversal attacks) could be preserved by checking symlink paths differently.
Environment
- copier version: [latest]
- Python version: 3.13
- OS: macOS (though likely affects all platforms)
Proposed Solution
I have prepared a potential fix that addresses this issue while maintaining existing security protections. The fix distinguishes between existing symlinks and regular files during path validation.
I'd be happy to contribute this fix if it seems like a valid issue to address. Thank you for maintaining this excellent tool!