T09 · Insecure Skill Coding Practices
- Location
scripts/template_manager.py:275- Finding
Template Name Path Traversal Enables Arbitrary DOCX File Overwrite and Deletion
- Content
View full analysis
bool: """Delete a template.""" # Check whether the template exists template_path = self.templates_dir / f"{template_name}.docx" if not template_path.exists(): print(f"Template does not exist: {template_name}") return False try: # Delete the file template_path.unlink() # Delete its configuration templates = self.templates_config.get('templates', {}) if template_name in templates: del templates[template_name] self.templates_config['templates'] = templates self._save_config() print(f"Template deleted successfully: {template_name}") return True except Exception as e: print(f"Failed to delete template: {e}") return False ``` Template creation and update use the same unvalidated path as a copy destination: ```python template_path = self.templates_dir / f"{template_name}.docx" # Copy a file into the template directory shutil.copy2(source_file, template_path) ``` Template export also uses the constructed path as a copy source: ```python template_path = self.templates_dir / f"{template_name}.docx" if not template_path.exists(): print(f"Template does not exist: {template_name}") return False try: shutil.copy2(template_path, output_path) ``` ### Technical Analysis The `template_name` argument is supplied through the command-line interface and is interpolated direct ...[truncated 3212 chars]- Remediation
View remediation
str: if not TEMPLATE_NAME_PATTERN.fullmatch(template_name): raise ValueError("Invalid template name") return template_name ``` 2. **Enforce resolved-path containment** Centralize target-path construction and verify that the resolved target remains under the resolved template directory: ```python def get_safe_template_path(self, template_name: str) -> Path: validate_template_name(template_name) base = self.templates_dir.resolve() target = (base / f"{template_name}.docx").resolve() try: target.relative_to(base) except ValueError: raise ValueError("Template path escapes the template directory") if target.parent != base: raise ValueError("Nested template paths are not allowed") return target ``` 3. **Use the centralized helper everywhere** Replace every direct construction of: ```python self.templates_dir / f"{template_name}.docx" ``` in `get_template`, `create_template`, `update_template`, `delete_template`, and `export_template`. 4. **Defend against symbolic-link attacks** Before destructive or overwrite operations, reject symbolic-link targets and ensure the parent directory has not changed: ```python if target.is_symlink(): raise ValueError("Symbolic-link templates are not allowed") ``` Where concurrent untrusted users can modify the directory, use descriptor-relative or other race-resistant filesystem operations supported by the deployment platform. 5. **Validate source and destination files** Confirm that imported and copied source files are regular files with the expected `.docx` extension. A ...[truncated 520 chars]
