Penetration test conducted on 2025-02-07 against
0http-bun@1.2.2. 43 vulnerabilities found — 6 Critical, 13 High, 13 Medium, 7 Low, 4 Info. Overall Security Grade: D → B+ — All identified vulnerabilities resolved.
Fixed: 6/6 Critical, 13/13 High, 13/13 Medium, 7/7 Low, 4/4 Info = 43/43 vulnerabilities resolved ✅
- Status: FIXED
- File:
lib/router/sequential.js - Fix applied: Added LRU-style cache eviction with configurable
config.cacheSize(default 1000). When cache exceeds max size, oldest entries are evicted.
- Status: FIXED
- File:
lib/middleware/body-parser.js - Fix applied: Nesting depth scanner now tracks
inString/escapestate to correctly ignore braces inside JSON string literals.
- Status: FIXED —
⚠️ BREAKING CHANGE - File:
lib/middleware/rate-limit.js - Fix applied:
defaultKeyGeneratornow usesreq.ip || req.remoteAddress || 'unknown'— no proxy headers trusted by default. Users behind reverse proxies must supply a customkeyGenerator.
- Status: FIXED
- File:
lib/middleware/rate-limit.js - Fix applied: Removed
req.rateLimitStorebackdoor. Always uses constructor-configured store.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied: Added
crypto.timingSafeEqual()for all API key comparisons with constant-time length mismatch handling.
- Status: FIXED —
⚠️ BREAKING CHANGE - File:
lib/middleware/jwt-auth.js - Fix applied: Default algorithms changed from
['HS256', 'RS256']to['HS256']. Throws error if mixed symmetric+asymmetric algorithms are configured.
- Status: FIXED
- File:
lib/router/sequential.js - Fix applied: Default error handler now returns generic
"Internal Server Error"and logs full error viaconsole.error.
- Status: FIXED
- File:
lib/router/sequential.js - Fix applied: Changed
return this→return routerin arrow functionrouter.use().
- Status: FIXED
- File:
lib/middleware/body-parser.js - Fix applied: Added
readBodyWithLimit()streaming helper that reads body chunks incrementally and aborts immediately when cumulative size exceeds the limit. Replacesawait req.text()+ post-hoc size check in JSON, text, URL-encoded, and custom JSON parser paths.
- Status: FIXED
- File:
lib/middleware/body-parser.js - Fix applied: Custom
jsonParsernow enforces size limits before calling the custom parser function.
- Status: FIXED
- File:
lib/middleware/body-parser.js - Fix applied: Merged the validation and extraction loops into a single pass. Field count, size limits, filename sanitization, and prototype pollution checks all run in one iteration of
formData.entries()instead of two.
- Status: FIXED
- File:
lib/middleware/body-parser.js - Fix applied: Uses
Object.create(null)for body/files objects and added prototype pollution blocklist for field names.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied: Path exclusion now uses exact match or
path + '/'boundary checking.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied: Emits a
console.warndeprecation warning at middleware construction time whentokenQueryis configured, advising migration to Authorization header or customgetToken.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied: Now sets
req.ctx.authErrorandreq.ctx.authAttempted = trueon invalid tokens in optional mode.
- Status: FIXED
- File:
lib/middleware/rate-limit.js - Fix applied: Added
maxKeys(default 10000), periodic cleanup withsetInterval+unref(), and eviction of stale entries.
- Status: FIXED
- File:
lib/middleware/cors.js - Fix applied:
null/missing origins are now rejected before calling validator function or checking array.
- Status: FIXED
- File:
lib/middleware/rate-limit.js - Fix applied:
MemoryStore.incrementchanged fromasyncto synchronous.
- Status: FIXED
- File:
lib/next.js - Fix applied: Async middleware errors now caught via
.catch()on returned promises and forwarded toerrorHandler.
- Status: FIXED
- File:
lib/router/sequential.js - Fix applied:
emptyParamsnow usesObject.freeze({}).
- Status: FIXED
- File:
lib/router/sequential.js - Fix applied: Added URL path normalization (double-slash collapse,
decodeURIComponent, preserves%2F).
- Status: FIXED
- File:
lib/middleware/body-parser.js - Fix applied: Filenames sanitized (strips
.., path separators, null bytes; preservesoriginalName).
- Status: FIXED
- File:
lib/middleware/body-parser.js - Fix applied: Internal JSON parser type changed from
'application/'to'application/json'.
- Status: FIXED —
⚠️ BREAKING CHANGE - File:
lib/middleware/body-parser.js - Fix applied: Now throws
TypeErroron unexpected types instead of silently defaulting.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied: Raw JWT token removed from
req.ctx.jwtandreq.jwt.
- Status: FIXED —
⚠️ BREAKING CHANGE - File:
lib/middleware/jwt-auth.js - Fix applied:
req.ctx.apiKeyandreq.apiKeynow store a masked version (xxxx****xxxx). Raw key is available only viareq[API_KEY_SYMBOL](exportedSymbol.for('0http.apiKey')) to prevent accidental serialization/logging.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied: JWKS URI is validated at construction time. Throws an error if non-HTTPS URI is used when
NODE_ENV=production. Emits aconsole.warnin non-production environments.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied: Unified JWT error messages to
'Invalid or expired token'.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied:
...jwtOptionsspread now applied first, security-critical options override after.
- Status: FIXED
- File:
lib/middleware/rate-limit.js - Fix applied:
excludePathsuses exact or boundary matching.
- Status: FIXED
- File:
lib/middleware/cors.js - Fix applied: CORS headers (methods, allowed headers, credentials, exposed headers) only set when origin is allowed.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied: Removed unreliable
Function.lengtharity check; always calls validators with(apiKey, req).
- Status: FIXED
- File:
lib/router/sequential.js - Fix applied: After parsing query string, dangerous keys (
__proto__,constructor,prototype) are deleted fromreq.query, mirroring the existing protection onreq.params.
- Status: FIXED —
⚠️ BREAKING CHANGE - File:
lib/middleware/body-parser.js - Fix applied: Empty or whitespace-only JSON bodies now set
req.bodytoundefinedinstead of{}, letting the application decide the semantics.
- Status: FIXED
- File:
lib/middleware/body-parser.js - Fix applied: Raw body text now stored via
Symbol.for('0http.rawBody')(RAW_BODY_SYMBOL) instead ofreq._rawBodyText, preventing accidental serialization/logging. Symbol is exported for programmatic access.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied: Added
requiredTokenTypeoption tocreateJWTAuth. After successful JWT verification, validates thetypheader claim (case-insensitive). Rejects tokens with missing or incorrect type when configured.
- Status: FIXED
- File:
lib/middleware/jwt-auth.js - Fix applied: Internal functions removed from module exports.
- Status: FIXED
- File:
lib/middleware/rate-limit.js - Fix applied:
standardHeadersnow acceptstrue(full headers — default, backward compatible),false(no headers), or'minimal'(onlyRetry-Afteron 429 responses). Minimal mode prevents disclosing exact rate limit configuration and usage counters.
- Status: FIXED
- File:
lib/middleware/cors.js - Fix applied:
Vary: Originnow set for all non-wildcard origins (not just function/array).
- ✅ I-1:
'unknown'fallback in rate limiter now generates unique per-request keys to prevent shared bucket DoS; logs a security warning on first occurrence (rate-limit.js) — FIXED - ✅ I-2:
allowedHeadersfunction now resolved once per preflight request instead of 3 times, preventing inconsistency and wasted resources (cors.js) — FIXED - ✅ I-3: Pointless
try/catchblocks that only re-throw in body parser — FIXED (removed) - ✅ I-4: Empty
catchblocks in JWThandleAuthErrornow log errors viaconsole.errorto aid debugging (jwt-auth.js) — FIXED
- Prototype pollution protection on route params is well-implemented with
hasOwnProperty.call()guard fast-querystringuses null-prototype objects for query results- Security test suite exists for prototype pollution scenarios
- Body parser has comprehensive limits (parameter counts, field counts, key lengths)
- JWT error messages are partially sanitized (enumerated messages, not raw errors)
- CORS correctly blocks
credentials: true+origin: '*'combination - Lazy loading of heavy dependencies reduces startup attack surface
parseLimitregex is anchored and bounded (not vulnerable to ReDoS)
| Vulnerability | Breaking Change | Impact |
|---|---|---|
| CRIT-3 | Default rate limit key generator no longer trusts proxy headers | Users behind reverse proxies must supply custom keyGenerator |
| CRIT-6 | Default JWT algorithms changed from ['HS256', 'RS256'] to ['HS256'] |
Users relying on RS256 must explicitly configure algorithms |
| M-5 | parseLimit throws TypeError on invalid types |
Code passing false, null, or objects to parseLimit will throw |
| M-7 | req.ctx.apiKey / req.apiKey now stores masked value |
Code reading raw API key must use req[API_KEY_SYMBOL] instead |
| L-2 | Empty JSON body now sets req.body to undefined instead of {} |
Code checking req.body for empty JSON must handle undefined |
Fix remaining HIGH issues: H-3 (streaming body read), H-5 (single-pass multipart), H-8 (query token deprecation)✅ All HIGH issues fixedFix remaining MEDIUM issues: M-7 (mask API key in context), M-8 (JWKS HTTPS validation)✅ All MEDIUM issues fixedAddress LOW/INFO issues as part of ongoing maintenance✅ All LOW and INFO issues fixed- Write security regression tests for each fix ✅ Completed — 483 tests passing
- Bump version to 1.3.0 with security changelog