# Shared storage path traversal

User-controlled names joined into storage paths without encoding or exact-key pinning

_Area: Cloud and container security. Seen in 4 disclosed reports; 2 confirmed bounties: $250 and $2,000; latest 2026-05-21. Updated 2026-10-23._

## How it works
A service builds a storage path (URL, object key, filename) by joining a user-controlled value with a fixed prefix or suffix, then trusts the result to stay inside the caller's namespace. The assumption that breaks: the value is a plain name. In the clearest case, a fixed suffix is appended to a user-supplied S3 path and signed without validation; an encoded `?` truncates the appended suffix and `/.` resolves to the bucket root, so the signature covers the bucket base path rather than one object [E1](https://bugbountylibrary.com/r/h1%3A1485500.md). The backend enforces nothing beyond the string it was handed.

## Where it shows up
- A fixed suffix appended to a user path before signing, with no validation [E1](https://bugbountylibrary.com/r/h1%3A1485500.md)
- Presigned upload policies whose key condition is `starts-with` a prefix rather than an exact key [E2](https://bugbountylibrary.com/r/h1%3A93691.md)
- Filenames built by hyphen-joining namespace and object names, where the delimiter is ambiguous [E3](https://bugbountylibrary.com/r/h1%3A778803.md)

## How to review
Find every place a user value becomes part of a path. The invariant: after resolution, the path must be provably confined to the caller's namespace. Check that names are encoded (not just concatenated), that `..`/`.`/encoded separators cannot survive, that the whole path is signed as one opaque value rather than suffix-appended, and that presigned policies pin the exact key, not a prefix. For joined filenames, confirm the mapping from (namespace, name) to path is injective.

## Variants seen
- Encoded `?` truncating an appended suffix plus `/.` reaching bucket root, then signing and listing the whole bucket [E1](https://bugbountylibrary.com/r/h1%3A1485500.md)
- Prefix-only policy allowing cross-tenant overwrite under a shared prefix — policy confusion, not path resolution [E2](https://bugbountylibrary.com/r/h1%3A93691.md)
- Delimiter collision letting one namespace overwrite another's auth file — injectivity failure, not `../` [E3](https://bugbountylibrary.com/r/h1%3A778803.md)

## Why fixes fail
Prefix checks and string concatenation look like confinement but do not normalize or encode, so encoded separators still escape [E1](https://bugbountylibrary.com/r/h1%3A1485500.md). A `starts-with` policy is not a confinement check at all; it grants the whole prefix [E2](https://bugbountylibrary.com/r/h1%3A93691.md). Hyphen-joined names stay ambiguous until the mapping is made injective [E3](https://bugbountylibrary.com/r/h1%3A778803.md).

## Impact and severity
Ranged from cross-tenant file overwrite [E2](https://bugbountylibrary.com/r/h1%3A93691.md) and auth bypass [E3](https://bugbountylibrary.com/r/h1%3A778803.md) to listing and reading whole buckets [E1](https://bugbountylibrary.com/r/h1%3A1485500.md). Severity rises with shared backends, weak tenant boundaries, and attacker-controlled names reaching signing or upload logic.

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A1485500.md
- E2: https://bugbountylibrary.com/r/h1%3A93691.md
- E3: https://bugbountylibrary.com/r/h1%3A778803.md
