[FIX]: contain deserialized payload artifacts - #106
[FIX]: contain deserialized payload artifacts#106Hinotobi (Hinotoi-agent) wants to merge 8 commits into
Conversation
|
Thanks — updated in I kept the explicit absolute/ Validation: uv run pytest tests/unit/payloads/test_payload_store_security.py -q
# 5 passed
uv run pytest tests/unit/payloads/test_store.py tests/unit/payloads/test_payload_store_security.py -q
# 18 passed
uv run ruff check rampart/payloads/_store.py tests/unit/payloads/test_payload_store_security.py
uv run ruff format --check rampart/payloads/_store.py tests/unit/payloads/test_payload_store_security.py
uv run ty check rampart/payloads/_store.py tests/unit/payloads/test_payload_store_security.py
python -m compileall -q rampart tests
git diff --check |
There was a problem hiding this comment.
Pull request overview
This PR hardens payload collection load-time artifact handling by validating and containing deserialized artifact references so they cannot escape the collection’s artifacts/ directory after normalization and symlink resolution.
Changes:
- Added
PayloadStore._resolve_artifact_path()(and helper containment logic) to validate serialized artifact references during deserialization. - Updated deserialization to use the resolver and fail fast on invalid artifact paths before attempting to read.
- Added regression tests covering traversal, absolute/non-
artifacts/paths, missing artifacts, and symlink escape scenarios.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
rampart/payloads/_store.py |
Adds artifact-path resolution/containment checks and routes deserialization through them. |
tests/unit/payloads/test_payload_store_security.py |
Adds unit regression coverage for invalid serialized artifact paths and symlink escape handling. |
|
Hinotobi (@Hinotoi-agent) would you please fix the build? the checks are failing and Copilot also has recommendations |
Signed-off-by: hinotoi-agent <paperlantern.agent@gmail.com>
|
Fixed the failing build and remaining Copilot recommendation in
Validation:
The prior docs job failed while |
Signed-off-by: hinotoi-agent <paperlantern.agent@gmail.com>
Signed-off-by: hinotoi-agent <paperlantern.agent@gmail.com>
|
Thanks for the work Hinotobi (@Hinotoi-agent)! I've enabled auto-merge on this as it seems GitHub Actions is currently in a major outage so jobs may remain queued for a while...I'll check back in on this at the end of the day to see if its still on hold. |
|
Hinotobi (@Hinotoi-agent) looks like linting failed - can you please fix? |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
tests/unit/payloads/test_payload_store_security.py:23
- The production loader reads JSONL with
encoding='utf-8', but this test writes usingPath.write_text(...)without specifying encoding. To avoid platform-dependent defaults (and align with the code under test), passencoding='utf-8'here.
(collection_dir / "payloads.jsonl").write_text(json.dumps(record) + "\n")
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
rampart/payloads/_store.py:434
- This only verifies that the path exists, so a reference such as
artifacts/subdiris accepted and stored as a binary artifact even thoughPayload.artifactmust point to a file. Consumers such asOneDriveSurface.upload_async()callread_bytes()and will then fail withIsADirectoryError. Checkis_file()here so deserialization rejects directories and other non-file filesystem entries.
if not artifact_path.exists():
msg = f"Missing artifact: {artifact_path}"
raise FileNotFoundError(msg)
Summary
This is the focused follow-up requested in #57 (comment).
It keeps the load-time artifact containment hardening only: when deserializing a persisted payload collection, artifact references now have to remain under the collection's
artifacts/directory after normalization and symlink resolution.What changed
_resolve_artifact_path()inrampart/payloads/_store.pyfor deserialized artifact references..., or do not start withartifacts/.artifacts/directory.Scope notes
Payload.idvalidation.rampart/core/payload_ids.py._copy_file_artifact()orOneDriveSurface.upload_async().Test plan
Host-local:
Results:
5 passed18 passed617 passed, 5 skippedContainer validation:
Result: passed (
18 passed; ruff, ty, and diff whitespace checks passed).