T09 · Insecure Skill Coding Practices
- Location
scripts/map_findings_to_owasp.py:128- Finding
Dry-Run Mode Performs Filesystem Writes and Can Overwrite Existing Files
- Content
View full analysis
Vulnerability Details
File Location:
scripts/map_findings_to_owasp.py, lines 29, 76-104, and 128
Vulnerability Type: Dry-run contract violation resulting in unintended filesystem modification
Risk Level: MediumVulnerable Code
python parser.add_argument("--dry-run", action="store_true", help="Run without side effects.")python def render(result: dict, output_path: Path, fmt: str) -> None: output_path.parent.mkdir(parents=True, exist_ok=True) if fmt == "json": output_path.write_text(json.dumps(result, indent=2), encoding="utf-8") return if fmt == "md": lines = [ f"# {result['summary']}", "", f"- status: {result['status']}", "", "## Findings By Category", ] for category, count in result["details"]["category_counts"].items(): lines.append(f"- {category}: {count}") lines.extend(["", "## Remediation Checklist"]) for category, actions in result["details"]["remediation_checklist"].items(): lines.append(f"- {category}") for action in actions: lines.append(f" - {action}") output_path.write_text("\n".join(lines) + "\n", encoding="utf-8") return with output_path.open("w", newline="", encoding="utf-8") as handle: writer = csv.DictWriter( handle, fieldnames=["id", "severity", "category", "title"], ) writer.writeheader() writer.writerows(result["details"]["mapped_findings"])python render(result, Path(args.output), args.format)Technical Analysis
The command-line interface explicitly describes
--dry-runas running without side effects. However, the flag does not control output behavior. It is only recorded in the generated result, whilerender()is called unconditionally.The
render()function always creates the output file's parent directories and then create ...[truncated 1915 chars]- Remediation
View remediation
Remediation Suggestions
- Prevent all rendering when dry-run mode is active:
python if args.dry_run: print(json.dumps(result, indent=2)) else: render(result, Path(args.output), args.format)-
Prefer making
--outputoptional during dry runs so callers do not need to provide a potentially destructive path. -
If preview output is required, emit it to standard output rather than opening a filesystem destination.
-
Add automated tests confirming that
--dry-run:- Does not create the output file.
- Does not modify an existing output file.
- Does not create missing parent directories.
- Produces preview output only through a documented non-mutating channel.
-
Consider writing normal output atomically through a temporary file in the destination directory followed by a controlled replacement. This reduces corruption risk during interrupted non-dry-run operations.
