Back to Signal Feed
CodeTracked since May 21, 2026

OpenHands blocks conversation path traversal in storage path construction

The PR adds a central allowlist validator inside `openhands.storage.locations.get_conversation_dir()` for `sid` and `user_id`, decoding URL-encoded input and only allowing `[A-Za-z0-9_-]` components before building conversation filesystem paths. This prevents path traversal payloads such as `../`, `/`, `\`, `%2e%2e%2f`, and NUL bytes from producing out-of-root paths while preserving valid UUID-like identifiers.

get_conversation_dirsiduser_idopenhands.storage.locations

What Happened

  • The PR adds a central allowlist validator inside `openhands.storage.locations.get_conversation_dir()` for `sid` and `user_id`, decoding URL-encoded input and only allowing `[A-Za-z0-9_-]` components before building conversation filesystem paths. This prevents path traversal payloads such as `../`, `/`, `\`, `%2e%2e%2f`, and NUL bytes from producing out-of-root paths while preserving valid UUID-like identifiers.
  • The PR adds a central allowlist validator inside `openhands.storage.locations.get_conversation_dir()` for `sid` and `user_id`, decoding URL-encoded input and only allowing `[A-Za-z0-9_-]` components before building conversation filesystem paths. This prevents path traversal payloads such as `../`, `/`, `\`, `%2e%2e%2f`, and NUL bytes from producing out-of-root paths while preserving valid UUID-like identifiers.
  • 1 evidence item attached for review.

What is Different

Before

Scattered source updates, isolated context, and manual follow-up across multiple feeds.

Now

Implemented a storage-layer allowlist path-component check (with URL decoding) for conversation directory construction, closing a gap where unvalidated legacy/internal callers could inject traversal sequences and enabling uniform protection across current and future callers.

Why Track This

Why It Matters

OpenHands operators and developers using the file-backed conversation store can prevent malformed or attacker-supplied conversation IDs from writing or reading outside the allowed conversation directory, reducing the practical risk of cross-conversation file access and storage tampering. The new safeguard is enforced in a central chokepoint (`get_conversation_dir`) via allowlist validation after unquoting input, so affected call paths now fail fast with `ValueError`; watch for any remaining code paths that build additional subpaths after this function, because those can still bypass this specific boundary if not separately validated.

Impact

OpenHands operators and developers using the file-backed conversation store can prevent malformed or attacker-supplied conversation IDs from writing or reading outside the allowed conversation directory, reducing the practical risk of cross-conversation file access and storage tampering. The new safeguard is enforced in a central chokepoint (`get_conversation_dir`) via allowlist validation after unquoting input, so affected call paths now fail fast with `ValueError`; watch for any remaining code paths that build additional subpaths after this function, because those can still bypass this specific boundary if not separately validated.

What To Watch Next

  • Watch whether get_conversation_dir becomes a repeated pattern.
  • Track follow-up changes around AI Security.
  • Compare future signals against this evidence trail.
  • Re-check risk flags: legacy_header_ids_not_blocked_by_route_validation, unvalidated_post_chokepoint_subpath_concatenation.
Open Topic TimelineOpen Technical EventOpen Original Sourcelegacy_header_ids_not_blocked_by_route_validation / unvalidated_post_chokepoint_subpath_concatenation / newly_rejected_encoded_traversal_inputs_need_backward_compat_check

Supporting Evidence