T09 · Insecure Skill Coding Practices
- Location
orchestrator.py:73- Finding
User-Controlled Story Identifier Enables Path Traversal and Arbitrary JSON File Overwrite
- Content
View full analysis
- Remediation
View remediation
str: if not STORY_ID_PATTERN.fullmatch(story_id): raise ValueError("Invalid story ID") return story_id ``` 2. Apply validation both to command-line input and to identifiers returned by external agents. 3. Resolve the destination and verify containment before writing: ```python def save(self, output_dir: Path): output_root = output_dir.resolve() safe_id = validate_story_id(self.story_id) state_file = (output_root / f"{safe_id}_state.json").resolve() if output_root not in state_file.parents: raise ValueError("State path escapes output directory") with open(state_file, "w", encoding="utf-8") as f: json.dump(self.__dict__, f, indent=2, default=str) ``` 4. Use atomic writes to prevent partial or corrupted state: - Create a temporary file inside `output_dir`. - Flush and synchronize it. - Replace the final file atomically with `os.replace()`. 5. Run the pipeline under a dedicated, least-privileged account whose write access is restricted to the intended output and data directories. 6. Add tests covering `../`, absolute paths, platform-specific separators, repeated separators, excessively long IDs, and agent-returned malicious IDs. ]]>
