T09 · Insecure Skill Coding Practices
- Location
modules/validation-patterns.md:47- Finding
Unrestricted Path Traversal in Reference Validation
- Content
View full analysis
Vulnerability Details
File Location:
modules/validation-patterns.md, lines 47–55
Vulnerability Type: Path traversal and local file-existence disclosure
Risk Level: LowVulnerable Code:
python def validate_references(skill_path: Path, references: list[str]) -> dict: """Validate that referenced files exist.""" results = {'valid': [], 'missing': []} for ref in references: ref_path = skill_path.parent / ref if ref_path.exists(): results['valid'].append(ref) else: results['missing'].append(ref) return resultsTechnical Analysis
The validation template treats each reference as a trusted relative path. It does not reject absolute paths, remove
..path components, resolve symbolic links, or verify that the resolved target remains inside the expected skill directory.In Python, joining a
pathlib.Pathwith an absolute path discards the preceding base path. Relative references containing../can likewise escapeskill_path.parent. CallingPath.exists()on the resulting path therefore creates a local file-existence oracle outside the validator's intended scope.This is a documentation template rather than directly executable project code, so exploitation requires another component to adopt the template and pass attacker-controlled references to it.
Attack Path
- A validator implements the documented
validate_references()template. - An attacker supplies a skill or document containing a crafted reference, such as
../../.env,../../../etc/passwd, or an absolute path. - The validator joins the reference with
skill_path.parentwithout containment validation. Path.exists()checks the external target.- The function places the supplied reference in either
validormissing. - If these results are returned or displayed, the attacker learns whether the probed local path exists.
Impact As
...[truncated 356 chars]
- A validator implements the documented
- Remediation
View remediation
Remediation Suggestions
- Reject absolute references before constructing a candidate path.
- Resolve both the trusted root and candidate path using
Path.resolve(). - Confirm that the resolved candidate is contained within the trusted root using
Path.is_relative_to()on supported Python versions. - Decide explicitly whether symbolic links are permitted. If not, reject references whose path components traverse symlinks.
- Return a validation error for out-of-bound references without probing or exposing the external target's existence.
- Add tests for absolute paths,
../traversal, nested traversal, and symlink-based escapes.
Example hardened implementation:
python from pathlib import Path def validate_references(skill_path: Path, references: list[str]) -> dict: """Validate references while enforcing the skill-directory boundary.""" root = skill_path.parent.resolve() results = { "valid": [], "missing": [], "invalid": [], } for ref in references: supplied = Path(ref) if supplied.is_absolute(): results["invalid"].append(ref) continue candidate = (root / supplied).resolve() if not candidate.is_relative_to(root): results["invalid"].append(ref) continue if candidate.exists(): results["valid"].append(ref) else: results["missing"].append(ref) return results
