Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@
**Vulnerability:** The `_collect_files` function in `scanner/cli/vibesec.py` used `os.scandir` without explicitly checking if entries were symbolic links before processing them as directories or files. This could allow for arbitrary file read or path traversal vulnerabilities by processing symlinks that point outside the expected directories.
**Learning:** During static analysis, directory and file collection methods must be robust against maliciously crafted directory structures, specifically symbolic links pointing to sensitive system files.
**Prevention:** Explicitly use `entry.is_symlink()` and check `follow_symlinks=False` on `is_file()` to prevent traversing external links or including them during scan operations.

## 2026-06-11 - Fix Arbitrary File Write via symlink path traversal in `vibesec init`
**Vulnerability:** The `cmd_init` command in `scanner/cli/vibesec.py` created files and directories inside `.cursor/rules` or `VIBESEC_CHECKLIST.md` in the current project root. However, if the project directory contained malicious symlinks (e.g., `.cursor -> /etc` or `.cursor -> /tmp`), the CLI would unknowingly traverse the symlink and write files (e.g., `vibesec.md`) outside the intended directory. This leads to an Arbitrary File Write vulnerability, potentially allowing attackers to overwrite sensitive files or escalate privileges on the victim's machine.
**Learning:** Even simple CLI file operations (like initializing project configurations) are susceptible to Path Traversal via symlinks. When dealing with directory structures that could be maliciously crafted, we cannot trust that `Path(".").resolve() / ".cursor"` stays within the bounds of `Path(".").resolve()`.
**Prevention:** Before performing any filesystem mutation operations (e.g. `mkdir` or `write_text`), ensure the fully resolved path resides strictly within the expected parent boundary. Use `target_file.resolve().is_relative_to(project_root)` as a security check to detect and abort if the path escapes the intended directory.
12 changes: 12 additions & 0 deletions scanner/cli/vibesec.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,12 @@ def cmd_init(args):
config = tool_configs[tool]
if not config.get("shared_only"):
target_file = project_root / config["path"]

# SECURITY: Prevent Arbitrary File Write via symlink path traversal
if not target_file.resolve().is_relative_to(project_root):
print(f"Error: Target path {target_file} escapes the project root. Aborting.", file=sys.stderr)
sys.exit(1)

target_file.parent.mkdir(parents=True, exist_ok=True)
if target_file.is_symlink():
target_file.unlink()
Expand All @@ -333,6 +339,12 @@ def cmd_init(args):
installed.append(str(config["path"]))
# Always create the checklist
checklist_file = project_root / "VIBESEC_CHECKLIST.md"

# SECURITY: Prevent Arbitrary File Write via symlink path traversal
if not checklist_file.resolve().is_relative_to(project_root):
print(f"Error: Checklist path {checklist_file} escapes the project root. Aborting.", file=sys.stderr)
sys.exit(1)

if checklist_file.is_symlink():
checklist_file.unlink()
if not checklist_file.exists():
Expand Down
Loading