T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/skillguard.py:82
- Finding
- Out-of-Scope Symlink Targets Are Read During Scanning<![CDATA[ ## Vulnerability Details **File Location**: `scripts/skillguard.py:82-85`, `scripts/skillguard.py:329-353`, and `scripts/skillguard.py:359-367` **Vulnerability Type**: Improper symlink boundary enforcement **Risk Level**: High ### Vulnerable Code ```python def get_skill_files(skill_path: Path) -> list: files = [] for root, dirs, filenames in os.walk(skill_path): dirs[:] = [d for d in dirs if d not in {"node_modules", ".git", "__pycache__", ".venv", "venv"}] for fname in filenames: files.append(Path(root) / fname) return files ``` ```python def scan_symlinks(files: list, skill_path: Path, result: ScanResult): """Detect symlinks that could point to sensitive files outside the skill directory.""" for f in files: if f.is_symlink(): rel = f.relative_to(skill_path) try: target = f.resolve() except (RuntimeError, OSError): result.add(Finding( severity=SEVERITY_HIGH, category="symlink", message=f"Broken or looping symlink: {rel}", file=str(rel), evidence=f"Raw target: {os.readlink(f)}", )) continue try: target.relative_to(skill_path) severity = SEVERITY_LOW except ValueError: severity = SEVERITY_CRITICAL msg = (f"Symlink escapes skill directory: {rel} -> {target}" if severity == SEVERITY_CRITICAL else f"Internal symlink: {rel} -> {target}") result.add(Finding( severity=severity, category="symlink", message=msg, file=str(rel), evidence=f"Target: {target}", )) ``` ```python for fpath in files: suffix = fpath.suffix.lower() if suffix not in TEXT_EXTENSIONS: continue ...[truncated 2787 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Resolve and validate every path immediately before opening it: ```python root = skill_path.resolve() resolved = fpath.resolve(strict=True) try: resolved.relative_to(root) except ValueError: continue ``` 2. Do not content-scan any symlink by default. Record the symlink as a finding and skip it: ```python if fpath.is_symlink(): continue ``` 3. Perform boundary validation inside `read_file_safe()` as a defense-in-depth measure, rather than relying only on callers. 4. Open files using platform-supported no-follow controls such as `O_NOFOLLOW` where available, then verify the opened file descriptor to reduce time-of-check/time-of-use races. 5. Avoid returning content from external targets in evidence fields. 6. Add regression tests for symlinks targeting: - Files outside the skill root. - SSH keys and cloud credential files. - Relative escape paths. - Chained symlinks. - Targets changed between validation and opening. ]]>
