Skip to content

fix(sanitize): reject NaN status code from non-numeric strings#1397

Open
francisjohnjohnston-web wants to merge 1 commit into
h3js:mainfrom
francisjohnjohnston-web:fix/sanitize-status-code-nan
Open

fix(sanitize): reject NaN status code from non-numeric strings#1397
francisjohnjohnston-web wants to merge 1 commit into
h3js:mainfrom
francisjohnjohnston-web:fix/sanitize-status-code-nan

Conversation

@francisjohnjohnston-web

@francisjohnjohnston-web francisjohnjohnston-web commented May 25, 2026

Copy link
Copy Markdown

Problem

sanitizeStatusCode can return NaN, defeating its own documented purpose ("Make sure the status code is a valid HTTP status code"):

sanitizeStatusCode("abc") // => NaN

+"abc" is NaN, and both NaN < 100 and NaN > 599 evaluate to false, so the range guard lets NaN through.

This is reachable through HTTPError. Its status is derived from an arbitrary cause:

const status = sanitizeStatusCode(
  (details as ErrorBody)?.status ||
    (details as ErrorInput)?.statusCode ||
    (details?.cause as ErrorBody)?.status ||
    (details?.cause as ErrorInput)?.statusCode,
  500,
);

cause is any caught error, so a non-numeric statusCode/status on it (e.g. a wrapped library error) yields an HTTPError with status: NaN — an invalid HTTP response.

Fix

Rewrite the range guard as a positive check. NaN >= 100 is false, so NaN now correctly falls back to the default:

return statusCode >= 100 && statusCode <= 599 ? statusCode : defaultStatusCode;

Strictly behaviour-preserving for every numeric input in/out of range; only the previously-undefined NaN path changes (now returns the default). The ternary is also smaller than the prior two-statement if/return, so the defineHandler bundle-size budget test stays green.

Tests

Added test/unit/sanitize.test.ts covering valid pass-through, out-of-range fallback, non-numeric-string fallback, and the HTTPError-from-non-numeric-cause regression. Full suite green (1154 passed), tsc 0 errors, oxlint + oxfmt clean.

Summary by CodeRabbit

  • Bug Fixes

    • Improved status code validation to properly reject non-numeric and out-of-range values, ensuring invalid codes fall back to sensible defaults
  • Tests

    • Added unit test coverage for status code validation and error handling with invalid inputs

Review Change Stack

sanitizeStatusCode("abc") returned NaN: `+"abc"` is NaN, and both
`NaN < 100` and `NaN > 599` are false, so the range guard let it
through. This is reachable via HTTPError, whose status is derived from
an arbitrary `cause.status`/`cause.statusCode` — a non-numeric value
there produced an HTTPError with `status: NaN` (an invalid response).

Rewrite the guard as a positive range check: `NaN >= 100` is false, so
NaN now falls back to the default. The ternary form is also smaller than
the previous two-statement if/return, keeping the bundle-size budget.
@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 484dffca-77ed-48ab-97a5-b16121e25c1b

📥 Commits

Reviewing files that changed from the base of the PR and between 84244b4 and bdc0379.

📒 Files selected for processing (2)
  • src/utils/sanitize.ts
  • test/unit/sanitize.test.ts

📝 Walkthrough

Walkthrough

This PR fixes HTTP status code validation in sanitizeStatusCode by switching from inverted bounds logic to explicit positive range validation (100–599), explicitly rejecting NaN and non-numeric inputs. Test coverage validates the fix across numeric, numeric-string, non-numeric, and out-of-range cases, plus integration with HTTPError.

Changes

HTTP Status Code Validation

Layer / File(s) Summary
Status code range validation implementation
src/utils/sanitize.ts
sanitizeStatusCode now validates status codes using positive range logic (>= 100 && <= 599), with comments clarifying that NaN (from non-numeric strings) triggers fallback to defaultStatusCode.
Test coverage for status validation
test/unit/sanitize.test.ts
Tests verify that sanitizeStatusCode passes valid numeric and numeric-string codes, rejects out-of-range and non-numeric inputs by returning defaults, and that HTTPError correctly defaults non-numeric cause.statusCode to 500.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • pi0

Poem

🐰 A status code validation hop,
Where NaN and bad ranges must stop,
With bounds from 100 to 599,
Our tests confirm it's working fine—
No more defaults strewn awry!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main fix: rejecting NaN status codes from non-numeric strings by switching to a positive range check in sanitizeStatusCode.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@francisjohnjohnston-web

Copy link
Copy Markdown
Author

AI Disclosure: This contribution was proposed by Prodia, an autonomous TypeScript evolution system (https://prodia.dev/). Human review was applied before submission. See our full disclosure policy: https://github.com/francisjohnjohnston-web/prodia-dev-33ff1150/blob/main/docs/AI-CONTRIBUTION-POLICY.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant