Source: Security-auditor finding on Issue #1175 (STEP 4.8 plan freshness re-verification), retroactively filed via scripts/backfill_1175_security_advisories.sh after #1180 closed the ADVISORY-FINDINGS tracking gap.
Severity: Low
Location: plugins/autonomous-dev/lib/plan_freshness.py:54-74 — function verify_paths_exist()
Finding: The verify_paths_exist() function resolves user-supplied path strings (extracted from plan markdown via the _FILE_PATH_REGEX) under repo_root without normalizing or canonicalizing them. A plan containing path strings like ../../etc/passwd or subdir/../../../sensitive.py would be checked as repo_root / "../../etc/passwd", potentially escaping the repo root.
Attack vector: Low severity because (a) the function only checks .exists() — it does not read file content or expose results to an attacker, and (b) the input source is the plan markdown, which is generated by a trusted planner agent. However, the lack of path canonicalization is a defense-in-depth gap.
Recommendation: Resolve and verify each candidate path stays within repo_root before the .exists() check:
resolved = (repo_root / path_str).resolve()
if not str(resolved).startswith(str(repo_root.resolve())):
# Treat as missing or raise; do not check .exists() on out-of-root paths.
missing.append(path_str)
continue
Acceptance: A regression test in tests/unit/lib/ that asserts a plan containing ../ traversal sequences is rejected (treated as missing) rather than escaping the repo root.
Labels: security, auto-improvement
Source: Security-auditor finding on Issue #1175 (STEP 4.8 plan freshness re-verification), retroactively filed via
scripts/backfill_1175_security_advisories.shafter #1180 closed the ADVISORY-FINDINGS tracking gap.Severity: Low
Location:
plugins/autonomous-dev/lib/plan_freshness.py:54-74— functionverify_paths_exist()Finding: The
verify_paths_exist()function resolves user-supplied path strings (extracted from plan markdown via the_FILE_PATH_REGEX) underrepo_rootwithout normalizing or canonicalizing them. A plan containing path strings like../../etc/passwdorsubdir/../../../sensitive.pywould be checked asrepo_root / "../../etc/passwd", potentially escaping the repo root.Attack vector: Low severity because (a) the function only checks
.exists()— it does not read file content or expose results to an attacker, and (b) the input source is the plan markdown, which is generated by a trusted planner agent. However, the lack of path canonicalization is a defense-in-depth gap.Recommendation: Resolve and verify each candidate path stays within
repo_rootbefore the.exists()check:Acceptance: A regression test in
tests/unit/lib/that asserts a plan containing../traversal sequences is rejected (treated as missing) rather than escaping the repo root.Labels:
security,auto-improvement