gabriel / musehub public
BREAKING task/presign-security-tdd-green #1 / 1
gabriel · 167 days ago · Apr 12, 2026 · Diff

security: harden presigned URL flow against path traversal and auth bypass

- Fix _handle_pydantic_validation to use exc.json() instead of exc.errors() so the response body is always JSON-serializable (Pydantic v2 ValidationError ctx fields contain raw exception objects that json.dumps cannot handle) - Move GET presign read-access check BEFORE the local-backend early return so unauthenticated/unauthorized GET presign requests are rejected even when the active backend is local:// (no presigned URLs to generate) - Add object_id path-traversal validators to WireFilterRequest, WirePresignRequest, WireConfirmObjectsRequest via field_validator - Reduce WirePresignRequest and WireConfirmObjectsRequest max_length from 50_000 to 1_000 to prevent CPU-saturation DoS on presign batches - Fix S3Backend._key() to strip '/' from object_ids (defense-in-depth behind the Pydantic validator layer) - Add ghost-object check in wire_confirm_objects: verify each object actually exists in storage before inserting a musehub_objects DB row - Batch presign HMAC signing in a single asyncio.to_thread dispatch instead of N parallel dispatches (one per object) - Add global PydanticValidationError exception handler so manual model_validate() calls inside route handlers return HTTP 422 not 500 - 11 new TDD security tests (all green): path traversal, auth, DoS limits, ghost registration, GET presign access control

sha256:99d2a4e654ce28e25d5bc3d1c178ad9609158b59706da27216af6bd69656035e sha
+20 ~7 symbols
sha256:d5334c8a42ba84cbbae33ace540feaee190d36e4c8f640a0204f6ee3a75486c4 snapshot
+20
symbols added
~7
symbols modified
0
dead code introduced
Semantic Changes 27 symbols
~ musehub/main.py .py 2 symbols added
+ _handle_pydantic_validation function async_function _handle_pydantic_validation L232–247
+ PydanticValidationError import import PydanticValidationError L230–230
~ musehub/models/wire.py .py 7 symbols added, 3 symbols modified
+ _validate_ids method method _validate_ids L362–363
+ _validate_ids method method _validate_ids L289–290
+ _validate_ids method method _validate_ids L325–326
+ _OBJECT_ID_MAX_LEN variable variable _OBJECT_ID_MAX_LEN L54–54
+ _OBJECT_ID_RE variable variable _OBJECT_ID_RE L53–53
+ _validate_object_ids function function _validate_object_ids L57–68
+ re import import re L31–31
~ musehub/storage/backends.py .py 2 symbols modified
~ tests/test_wire_protocol.py .py 11 symbols added
+ test_confirm_registers_object_that_exists_in_storage function async_function test_confirm_registers_object_that_exists_in_storage L738–785
+ test_confirm_registers_zero_for_nonexistent_objects function async_function test_confirm_registers_zero_for_nonexistent_objects L709–734
+ test_confirm_rejects_non_owner function async_function test_confirm_rejects_non_owner L689–705
+ test_confirm_rejects_over_limit_object_ids function async_function test_confirm_rejects_over_limit_object_ids L830–843
+ test_confirm_rejects_slash_in_object_id function async_function test_confirm_rejects_slash_in_object_id L642–654
+ test_confirm_requires_auth function async_function test_confirm_requires_auth L674–685
+ test_filter_objects_rejects_slash_in_object_id function async_function test_filter_objects_rejects_slash_in_object_id L658–670
+ test_presign_get_rejects_non_owner function async_function test_presign_get_rejects_non_owner L789–809
+ test_presign_rejects_dotdot_in_object_id function async_function test_presign_rejects_dotdot_in_object_id L626–638
+ test_presign_rejects_over_limit_object_ids function async_function test_presign_rejects_over_limit_object_ids L813–826
+ test_presign_rejects_slash_in_object_id function async_function test_presign_rejects_slash_in_object_id L610–622
← Older Oldest on task/presign-security-tdd-green
All commits
Newer → Latest on task/presign-security-tdd-green

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:99d2a4e654ce28e25d5bc3d1c178ad9609158b59706da27216af6bd69656035e --body "your comment"