Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@
**Vulnerability:** `crypto.timingSafeEqual` throws an error if buffers are different lengths, which exposes the application to timing attacks because the error throwing takes a different amount of time than a successful byte-by-byte comparison.
**Learning:** Always check buffer lengths before calling `timingSafeEqual`. To ensure constant time regardless of length, compare the expected buffer to itself when lengths don't match.
**Prevention:** Compare lengths first, and use a dummy `timingSafeEqual(expected, expected)` on mismatch to mitigate timing leaks.
## 2025-02-14 - [Input Length Limits (DoS prevention)]
**Vulnerability:** External input APIs (`packages/functions/src/lookupCharacter.ts`) accepted unbounded string sizes which were then fed into regular expressions (`/^[a-zA-Z0-9\s'-]+$/`), exposing the environment to Regex Denial of Service (ReDoS) and unexpectedly large downstream requests to external APIs like Battle.net.
**Learning:** Checking parameter types isn't enough; lengths must also be strictly bounded to mitigate resource exhaustion or ReDoS attacks.
**Prevention:** Always add a maximum length constraint (e.g., `< 50`) immediately after type validation before applying regex on external endpoints.
6 changes: 6 additions & 0 deletions packages/functions/src/lookupCharacter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ export const lookupCharacter = onCall(
throw new HttpsError('invalid-argument', 'name, realm, and region must be strings');
}

// Security Enhancement: Add input length limits to prevent DoS via ReDoS on the validation pattern
// or passing excessively large strings to Battle.net APIs. WoW names/realms max out well under 50 chars.
if (name.length > 50 || realm.length > 50 || region.length > 50) {
throw new HttpsError('invalid-argument', 'Input exceeds maximum allowed length');
}

// Validate inputs contain only valid WoW name/realm slug characters (letters, digits, hyphens, spaces, apostrophes)
const validPattern = /^[a-zA-Z0-9\s'-]+$/;
if (!validPattern.test(name) || !validPattern.test(realm) || !validPattern.test(region)) {
Expand Down
Loading