T09 · Insecure Skill Coding Practices
- Location
scripts/bootstrap_repo.py:33- Finding
Workspace Path Traversal Through Unsafely Sanitized Path Components
- Content
View full analysis
Vulnerability Details
File Location:
scripts/bootstrap_repo.py:33-39, 130-136
Vulnerability Type: Path traversal and unrestricted filesystem write
Risk Level: MediumVulnerable Code
python def safe_component(value: str, default: str = "paper") -> str: value = value.lower().replace("\\", "/") value = re.sub(r"[^a-z0-9._/-]+", "-", value) value = re.sub(r"/{2,}", "/", value).strip("/") value = re.sub(r"(^|/)-+", r"\1", value) value = re.sub(r"-+(/|$)", r"\1", value) return value or defaultpython safe_slug = safe_component(args.paper_slug, "paper") safe_bucket = safe_component(args.bucket, "main-code") root_dir = Path("paper-repro-workspace") / safe_slug / safe_bucket root_dir.mkdir(parents=True, exist_ok=True) repo_name = repo_name_from_url(repo_url) target_dir = root_dir / repo_nameTechnical Analysis
safe_component()permits forward slashes and periods, including the special path component... Although backslashes are normalized and some characters are removed, the function does not reject absolute paths or traversal components.The resulting values are appended directly to
paper-repro-workspace. Python's path handling resolves embedded..components when filesystem operations are performed. A value such as../../outsidecan therefore causeroot_dir.mkdir()and the latergit clonedestination to escape the intended workspace.The repository name is sanitized separately, but this does not mitigate traversal through
paper_slugorbucket.Attack Path
- An attacker influences the
paper_slugorbucketargument supplied tobootstrap_repo.py. - The attacker supplies a value containing traversal components, such as
../../outside. safe_component()retains the periods and path separators.root_dirresolves outsidepaper-repro-workspace.- The script creates directories at the escaped location.
...[truncated 664 chars]
- An attacker influences the
- Remediation
View remediation
Remediation Suggestions
-
Treat
paper_slugandbucketas single path components and reject all/and\characters. -
Explicitly reject empty components,
., and... -
Reject absolute paths before constructing the destination.
-
Resolve both the workspace and destination, then verify containment:
python workspace = Path("paper-repro-workspace").resolve() target = (workspace / safe_slug / safe_bucket / repo_name).resolve() if target != workspace and workspace not in target.parents: raise ValueError("Destination escapes the workspace") -
Prefer a sanitizer that only permits letters, digits, underscores, periods, and hyphens, without path separators.
-
Add tests for
..,../x,a/../../x, absolute paths, Windows drive paths, and mixed slash forms.
-
