validateSignedObjectStorageUrl in src/services/evidence.ts (lines 147-157) calls getSignedUrlExpiry(referenceUrl) — which fully parses the URL, its query parameters, and computes an expiry timestamp — before calling validateEvidenceUrlSafety(referenceUrl) (the SSRF check) on line 154. While getSignedUrlExpiry doesn't itself perform a network request, ordering the expensive/parsing-heavy work ahead of the security check means a request carrying a URL crafted to make getSignedUrlExpiry's regex/date-parsing logic expensive (e.g. deeply pathological X-Amz-Date/Expires values) does that work before the cheaper SSRF allowlist check has a chance to reject it outright for an internal/blocked host. Reordering so the SSRF check runs first would fail closed faster for any request targeting a disallowed host, regardless of how its query parameters are shaped.
validateSignedObjectStorageUrlinsrc/services/evidence.ts(lines 147-157) callsgetSignedUrlExpiry(referenceUrl)— which fully parses the URL, its query parameters, and computes an expiry timestamp — before callingvalidateEvidenceUrlSafety(referenceUrl)(the SSRF check) on line 154. WhilegetSignedUrlExpirydoesn't itself perform a network request, ordering the expensive/parsing-heavy work ahead of the security check means a request carrying a URL crafted to makegetSignedUrlExpiry's regex/date-parsing logic expensive (e.g. deeply pathologicalX-Amz-Date/Expiresvalues) does that work before the cheaper SSRF allowlist check has a chance to reject it outright for an internal/blocked host. Reordering so the SSRF check runs first would fail closed faster for any request targeting a disallowed host, regardless of how its query parameters are shaped.