Skip to content

fix: alerts numeric flags silently produce wrong results on invalid input - #579

Open
teyrebaz33 wants to merge 2 commits into
nansen-ai:mainfrom
teyrebaz33:fix/alerts-numeric-validation
Open

fix: alerts numeric flags silently produce wrong results on invalid input#579
teyrebaz33 wants to merge 2 commits into
nansen-ai:mainfrom
teyrebaz33:fix/alerts-numeric-validation

Conversation

@teyrebaz33

Copy link
Copy Markdown
Contributor

Summary

Fixes #578.

src/commands/alerts.js called Number(optionValue) in several places without checking whether the result was actually a valid number: the shared buildRange() helper (used by 7 numeric range flags on alerts create/update), two standalone --token-age-min/max blocks, and the list handler's --limit/--offset pagination.

A non-numeric value produced NaN, which is neither null nor undefined, so it silently passed the existing "is this flag set" checks. For the range flags, JSON.stringify({min: NaN}) serializes to {"min":null}, so the alert was created with that threshold silently disabled instead of erroring. For --limit, Array.prototype.slice(0, NaN) evaluates the end index as 0, so a typo'd --limit silently returned an empty list. For --offset, a negative value made Array.prototype.slice() count from the end of the array, so --offset -2 silently returned the last 2 alerts.

Fix

Validate with Number.isFinite() (range flags, which can be decimals) / Number.isInteger() (--limit/--offset, which must be whole numbers) and throw a NansenError on failure -- matching the existing buildPagination idiom already used in src/query-options.js and src/commands/research.js. I checked for the same unvalidated-Number() pattern elsewhere in src/commands/ and confirmed research.js's pagination already validates correctly, so this PR's scope (alerts.js only) is complete.

Test plan

  • Added regression tests covering all 9 fixed call sites (non-numeric range flags, non-numeric/negative token-age, non-numeric/negative/zero/non-integer --limit and --offset), plus a test confirming numeric strings (how the real CLI parser passes flag values) still work.
  • npx eslint src/commands/alerts.js src/__tests__/cli.internal.test.js -- clean.
  • npx vitest run src/__tests__/cli.internal.test.js -- 484/484 passed.
  • Full suite (npm test): 2639 passed, 2 skipped, 0 failed.
  • npm install produced only unrelated package-lock.json metadata noise, reverted before committing; package.json itself was not touched.

🤖 Generated with Claude Code

https://claude.ai/code/session_0141eH4NcQy4GXgusCGbG1pm

…nput

`nansen alerts list --limit abc` returned an empty list (slice(0, NaN) -> 0) instead of erroring, and `--offset -2` silently returned the last 2 alerts (negative slice counts from the end) instead of rejecting an invalid offset.

The same unvalidated `Number()` coercion pattern was in `buildRange()`, used by 7 numeric range flags on `alerts create`/`update` (--market-cap-min/max, --usd-min/max, --token-amount-min/max, --fdv-min/max, --inflow/outflow/netflow-*-min/max) plus two standalone --token-age-min/max blocks: a non-numeric value produced NaN, which passed the `!= null` check as "set", but JSON.stringify(NaN) serializes to null, so the alert was silently created with that threshold disabled.

All of these now validate with Number.isFinite/Number.isInteger and throw a clear NansenError, matching the existing buildPagination idiom in query-options.js/research.js.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_0141eH4NcQy4GXgusCGbG1pm
@nansen-pr-reviewer

nansen-pr-reviewer Bot commented Sep 4, 2026

Copy link
Copy Markdown

pr-reviewer Summary for #45f5895

📝 1 finding

Review completed. Please address the findings below.

Findings by Severity

Severity Count
🟡 Medium 1

Review effort: 2/5 (Simple)

Summary

This is a solid, well-scoped bug fix. The validation logic is correct, consistently uses Number.isFinite for decimals and Number.isInteger for pagination integers, and matches the idiom already established in src/query-options.js. The changeset is accurate (patch bump, correct package name), test coverage is thorough with regression tests for every fixed call site, and no pre-existing patterns were broken.

One medium finding worth addressing before merge:

Findings

src/commands/alerts.js — medium

buildSmTokenFlowsData validates --token-age-max but silently drops --token-age-min

The sm-token-flows builder (lines 180–186) only handles options['token-age-max']; there is no corresponding handling of options['token-age-min']. This was already the case on main, so the validation fix correctly guards what was there — but it means a user who passes --token-age-min 7 on an sm-token-flows alert will silently have it ignored (it falls into the "type-specific flag without a handler" path but does not get caught by the no---type guard because --type sm-token-flows is present).

The help text at line 542 lists only --token-age-max for this type, which matches the implementation, so the API likely doesn't support --token-age-min on sm-token-flows. If that's intentional, add a validation guard that throws a clear error when --token-age-min is passed with --type sm-token-flows, instead of silently discarding it. If the API does support it, add the min handling to match buildCommonTokenTransferData.

Suggested fix (if the API doesn't support it): in buildSmTokenFlowsData, after the token-age-max block:

if (options['token-age-min'] !== undefined) {
  throw new NansenError('--token-age-min is not supported for sm-token-flows alerts', ErrorCode.INVALID_PARAMS);
}

Token usage: 912 input, 2,316 output, 336,356 cache read, 33,806 cache write | Usage Guide

New pushes are reviewed automatically with a 10-minute cooldown between reviews. To request a review at any time, comment @nansen-pr-reviewer re-review.

nansen-pr-reviewer[bot]
nansen-pr-reviewer Bot previously approved these changes Sep 4, 2026

@nansen-pr-reviewer nansen-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-approved

This PR was automatically approved because:

  • Claude recommends approval
  • Claude assessed this as a moderate effort change
  • The effort level is within the auto-approval threshold of 2
  • No high or critical issues were detected
  • Review comment contains non-blocking feedback

If you have any concerns, please request a manual review.

Shorten the pagination guard comment in alerts.js and drop two redundant "Before the fix" comments in the regression tests (the `it()` descriptions and error assertions already say what they said). Also fix indentation on the --token-age-min/--token-age-max test body, which had lost its indentation in transit and read as a copy-paste artifact.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_0141eH4NcQy4GXgusCGbG1pm

@nansen-pr-reviewer nansen-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-approved

This PR was automatically approved because:

  • Claude recommends approval
  • Claude assessed this as a moderate effort change
  • The effort level is within the auto-approval threshold of 2
  • No high or critical issues were detected
  • Review comment contains non-blocking feedback

If you have any concerns, please request a manual review.

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.

alerts list --limit/--offset and numeric range flags silently produce wrong results on invalid input

1 participant