# Signed URL accepted without verification

Signed URL or token middleware that skips signature, expiry, path, or method binding

_Area: Web authentication and account takeover. Seen in 3 disclosed reports; 2 confirmed bounties: $500 and $2,000; latest 2024-03-22. Updated 2026-10-25._

## How it works
A signed URL or token is meant to prove that a trusted party authorized one specific request. The assumption that breaks is that the verifier actually checks every part of that proof. If the expiry check returns success on the expired branch, or the signature covers only part of the request, the middleware treats an unauthenticated request as authenticated. The signature becomes decoration rather than a gate.

## Where it shows up
- Middleware with early-return branches in the validity/expiry check; a nil error on the expired path that short-circuits signature verification [E1](https://bugbountylibrary.com/r/h1%3A2337427.md)
- Signatures computed over a path, header, or body but not over identity, permission, or session [E2](https://bugbountylibrary.com/r/h1%3A416983.md)
- Static HMACs that are identical for all users and never expire [E2](https://bugbountylibrary.com/r/h1%3A416983.md)
- Signatures covering only the Authorization header and body while the resource identifier lives in the URL path [E3](https://bugbountylibrary.com/r/h1%3A348090.md)
- HTTP method not bound to the signature, so a captured request can be replayed with a different verb [E3](https://bugbountylibrary.com/r/h1%3A348090.md)

## How to review
Trace the verifier end to end. The invariant: every request that reaches a protected handler must have its signature verified against the signing key, and the signed envelope must cover the method, the full path including resource identifiers, the body, and an expiry that is enforced. Check each branch of the expiry/validity function: an expired or malformed input must return an error, never nil. Confirm the signature is bound to the caller's identity or permission where authorization depends on it, and that it expires. For replay, ask whether a captured signed request can be re-issued after role revocation or with a mutated method or path.

## Variants seen
- Expired PreSignedURL returns nil from the expiry check, skipping signature verification entirely [E1](https://bugbountylibrary.com/r/h1%3A2337427.md)
- Non-expiring static path_hmac as the sole authorization, not tied to session or permission, replayable after staff removal [E2](https://bugbountylibrary.com/r/h1%3A416983.md)
- Signature over headers and body only; unsigned URL path and method let a captured request target other resources [E3](https://bugbountylibrary.com/r/h1%3A348090.md)

## Impact and severity
Unauthenticated file download given a known username and filename [E1](https://bugbountylibrary.com/r/h1%3A2337427.md); removed staff reconnecting integrations and exfiltrating store data [E2](https://bugbountylibrary.com/r/h1%3A416983.md); destructive identity and affiliation deletion via method and path mutation [E3](https://bugbountylibrary.com/r/h1%3A348090.md). Severity is high because the bypass needs no credentials, and worse when the signed artifact never expires or is shared across users.

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A2337427.md
- E2: https://bugbountylibrary.com/r/h1%3A416983.md
- E3: https://bugbountylibrary.com/r/h1%3A348090.md
