fix(storage): reject path traversal in artifact ids - #138
fix(storage): reject path traversal in artifact ids#138glorysr1209-png wants to merge 2 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR hardens artifact storage by validating artifact identifiers (rejecting empty, separators, NUL, and ChangesPath Traversal Prevention
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/vouch/storage.py (1)
217-223: 💤 Low valueRedundant containment checks with mismatched extensions.
_assert_safe_artifact_id("pages", page_id)performs a containment check for{page_id}.yaml, but pages use.md. The subsequent check for.mdis correct, making the.yamlcheck redundant.Consider extracting ID-only validation from
_assert_safe_artifact_idto avoid the redundant path resolution, or parameterizing the extension/suffix.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/vouch/storage.py` around lines 217 - 223, The _page_path method currently calls _assert_safe_artifact_id("pages", page_id) which validates containment using a .yaml suffix while _page_path builds a .md path, causing redundant/mismatched checks; refactor by extracting the ID-only validation from _assert_safe_artifact_id (e.g., _assert_safe_id or is_valid_artifact_id) or modify _assert_safe_artifact_id to accept a suffix/extension parameter (e.g., ext=".md") and use that when called from _page_path, update _page_path to call the new ID-only validator or pass ext=".md", and remove the redundant .md containment resolution so both checks consistently validate the same target path (reference symbols: _page_path, _assert_safe_artifact_id, kb_dir, "pages").
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_storage.py`:
- Around line 232-237: The canary path and the slug_hint disagree: with
slug_hint="../../../pwned" from .vouch/claims/ traversal lands at
store.root.parent/"pwned.yaml" but the test checks store.root/"pwned.yaml". Fix
by making the test and slug_hint consistent—either change slug_hint to
"../../pwned" so approve(pr.id, approved_by="reviewer") would target
store.root/"pwned.yaml", or keep slug_hint="../../../pwned" and update the
canary variable to canary = store.root.parent / "pwned.yaml" so the existence
assertion matches the actual traversal; ensure references to approve, slug_hint,
and canary are updated accordingly.
---
Nitpick comments:
In `@src/vouch/storage.py`:
- Around line 217-223: The _page_path method currently calls
_assert_safe_artifact_id("pages", page_id) which validates containment using a
.yaml suffix while _page_path builds a .md path, causing redundant/mismatched
checks; refactor by extracting the ID-only validation from
_assert_safe_artifact_id (e.g., _assert_safe_id or is_valid_artifact_id) or
modify _assert_safe_artifact_id to accept a suffix/extension parameter (e.g.,
ext=".md") and use that when called from _page_path, update _page_path to call
the new ID-only validator or pass ext=".md", and remove the redundant .md
containment resolution so both checks consistently validate the same target path
(reference symbols: _page_path, _assert_safe_artifact_id, kb_dir, "pages").
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 35522639-cc78-4d33-9d77-19a5afecf686
📒 Files selected for processing (2)
src/vouch/storage.pytests/test_storage.py
Use ../../pwned canary path in the slug_hint test and parameterize artifact suffix checks so page/source paths avoid redundant .yaml probes. Co-authored-by: Cursor <cursoragent@cursor.com>
ReviewSummary: Adds layered path-traversal validation to all artifact-ID path helpers in What works
Suggestions
Verdictapprove — The fix directly addresses all the affected code paths identified in #137, the validation logic is sound for the stated threat model, and the regression test covers the primary attack vector. The suggestions above are minor hardening notes, not correctness issues. |
Summary
Closes #137. Reject artifact IDs containing path separators or
..before writing under.vouch/.Changes
src/vouch/storage.py:_unsafe_artifact_id_reason,_assert_safe_artifact_idon yaml/page/source paths.tests/test_storage.py: regression forslug_hint="../../../pwned"on approve.Test plan
pytest tests/test_storage.py::test_slug_hint_path_traversal_rejected_on_approve(Python 3.11+ / package installed)Summary by CodeRabbit
Bug Fixes
Tests