T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/scaffold_x_growth_project.py:59
- Finding
- Unchecked Overwrite of Files in an Arbitrary Target Directory## Vulnerability Details **File Location**: `scripts/scaffold_x_growth_project.py`, lines 59–61 and 78–89 **Vulnerability Type**: Unrestricted destination path with silent file overwrite **Risk Level**: Medium ### Vulnerable Code ```python def write(path: Path, content: str): path.parent.mkdir(parents=True, exist_ok=True) path.write_text(content) ``` ```python root = Path(args.path) root.mkdir(parents=True, exist_ok=True) write(root / "README.md", README) write( root / ".env.example", ENV_EXAMPLE .replace( "XGROWTH_DRY_RUN=true", f"XGROWTH_DRY_RUN={str(not profile.get('live_publish', False)).lower()}" ) .replace( "XGROWTH_PUBLISH_ENABLED=false", f"XGROWTH_PUBLISH_ENABLED={str(profile.get('live_publish', False)).lower()}" ) ) write(root / "prompts" / "llm-drafting.md", PROMPT) write(root / "config" / "style-rules.md", STYLE) write( root / "docs" / "operator-notes.md", "Fill in operator decisions, niche choices, language rules, community integration, rollout notes, and reply-lane safety rules here.\n\nSuggested live-mode notes:\n- preferred reply sources (mentions only vs broader)\n- what counts as a permanent reply failure\n- whether failed replies should skip or fallback\n- where publish results are logged\n- anti-repetition window (for example last 48h similarity threshold)\n- idempotent slot-key design (stable fields only; never draft text)\n" ) write(root / "scripts" / "doctor.py", DOCTOR) ``` ### Technical Analysis The script accepts a caller-controlled `--path` and creates that directory with `exist_ok=True`. It does not verify that the destination is new, empty, within an approved workspace, or free of symbolic links. The helper then uses `Path.write_text()`, which opens existing files for writing and truncates their previous contents. Consequently, running the scaffold against an existing project can silently replace files such as `README.md`, ` ...[truncated 1827 chars]
- Remediation
- ## Remediation Suggestions 1. **Reject existing or non-empty destinations by default** - Fail if the target already exists and contains files. - Require an explicit `--force` option for intentional replacement. 2. **Validate and constrain the destination** - Resolve the target with `Path.resolve()`. - Reject filesystem roots, home directories, and other sensitive locations. - When used by an Agent, require the resolved path to remain under an approved workspace root. 3. **Reject symbolic links** - Check the destination and relevant parent components for symbolic links before writing. - Revalidate immediately before file creation to reduce time-of-check/time-of-use risk. 4. **Use exclusive creation** - Create files using exclusive mode, such as `open("x")`, when overwrite behavior is not explicitly requested. - If forced overwrite is supported, list affected files and request confirmation first. 5. **Provide backup and preview controls** - Add a `--dry-run` option that reports all files that would be created or replaced. - Back up existing files before an explicitly authorized overwrite. 6. **Validate profile input and fail safely** - Catch malformed JSON and invalid field types. - Validate cadence values and caps before creating any files. - Perform all validation before the first filesystem mutation.
