security: path traversal via link_sid in delete_person_company_link #42
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_biz#42
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
delete_person_company_linkconstructs a file path directly from thelink_sidURL parameter without any validation:A
link_sidof../../Cargo.tomlor../../../etc/passwdwould delete arbitrary files on the filesystem that the process has write access to.Fix
Validate
link_sidmatches^[a-zA-Z0-9_-]+$before using it in a path, or use the samesafe_joinhelper as the fix for #41.Affected code
crates/hero_biz_ui/src/services/mod.rs—delete_person_company_linkcrates/hero_biz_ui/src/web/handlers/mod.rs—person_link_deleteFound in
PR #21 review
Implementation Spec for Issue #42
Objective
Prevent a directory traversal attack where a crafted
link_sidURL parameter (e.g.../../Cargo.toml) can be used to delete arbitrary files on the filesystem through theperson_link_deleteHTTP handler.Current State
The service layer is already fully fixed.
validate_path_component()atservices/mod.rs:43-54is called on bothcontextandlink_sidinsidedelete_person_company_linkandlink_dir. No filesystem operation will be performed on a traversal-containing path.The remaining gap is in the HTTP handler
person_link_deleteinhandlers/mod.rs, which discards the error withlet _ = .... This means:HeroBizError::Validationis never surfaced as HTTP 400Requirements
HeroBizError::Validationas HTTP 400, not a silent redirect(StatusCode::BAD_REQUEST, e.to_string()).into_response()services/mod.rs— validation is completevalidate_path_componentmust continue to passFiles to Modify
crates/hero_biz_ui/src/web/handlers/mod.rs— handle theResultfromdelete_person_company_linkImplementation Plan
Step 1: Fix
person_link_deletehandlerFile:
crates/hero_biz_ui/src/web/handlers/mod.rsReplace the
let _ = ...discard with a match that returns HTTP 400 on error:StatusCodeis already imported. No new imports needed.Dependencies: none
Acceptance Criteria
cargo build -p hero_biz_uipasses with no errorscargo test -p hero_biz_uipasses with no regressionsperson_link_deletereturns HTTP 400 whenlink_sidcontains..,/,%2F, spaces, or characters outside[a-zA-Z0-9_-]person_link_deletereturns HTTP 303 redirect on a well-formedlink_sidlet _ = ...discard pattern is removed fromperson_link_deleteNotes
contextandlink_sidHeroBizErrordoes not implementIntoResponse, so per-handler boilerplate is consistent with existing patterns (e.g. line 423)Test Results
All tests in
hero_biz_uipassed successfully.Test suite:
cargo test -p hero_biz_uiTests run:
parser::tests::test_name_fixservices::tests::dot_dot_is_rejectedservices::tests::empty_string_is_rejectedservices::tests::null_byte_is_rejectedservices::tests::path_traversal_sequences_rejectedservices::tests::slash_is_rejectedservices::tests::valid_components_passFix Summary
File changed:
crates/hero_biz_ui/src/web/handlers/mod.rsThe
person_link_deletehandler previously discarded theResultfromdelete_person_company_linkwithlet _ = ..., silently redirecting even when the service rejected a traversal-containinglink_sid. This meant:The service layer (
validate_path_componentadded in #41) was already blocking the filesystem operation. This fix surfaces that rejection at the HTTP layer.Change: replaced the silent discard with an explicit error check — the handler now returns
HTTP 400 Bad Requestwith the validation error message whenlink_sidcontains path traversal characters. A validlink_sidcontinues to redirect as before.Tests: 7/7 pass (
cargo test -p hero_biz_ui), including 6 tests specifically covering path component validation.Closes #42