Skip to content

[Security advisory] Path-traversal risk in verify_paths_exist (plan_freshness.py:54-74) #1193

@akaszubski

Description

@akaszubski

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    auto-improvementContinuous improvement analyst findingssecuritySecurity and enforcement hardening

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions