Skip to content

fix(validation): reject malformed numbers in isNumber and validDecimal - #470

Open
devorun wants to merge 1 commit into
circlefin:masterfrom
devorun:fix/valid-decimal-multiple-dots
Open

devorun wants to merge 1 commit into
circlefin:masterfrom
devorun:fix/valid-decimal-multiple-dots

Conversation

@devorun

@devorun devorun commented Aug 14, 2026

Copy link
Copy Markdown

Summary

Two amount-field validation rules in helpers/validation.ts accept malformed input:

  • isNumber used !isNaN(parseInt(v)). parseInt parses a leading numeric prefix and ignores the rest, so isNumber("12abc") returns true.
  • validDecimal destructured only the second segment of v.split('.'), so validDecimal("1.23.45"), "1.55.99", "100.00.00" all return true — the segment after the second . is silently ignored.

Both rules guard the amount fields on pages/debug/paymentIntents/create.vue, pages/debug/payments/crypto/create.vue, and pages/debug/payments/crypto/presign.vue. A field that passes these rules is later fed to parseFloat, which coerces the malformed value to a different number than the user typed.

Fix

  • isNumber: match the whole string against an optionally-signed integer/decimal number (/^-?\d+(\.\d+)?$/) instead of relying on parseInt. Signed and decimal values keep working; trailing garbage, hex, and scientific-notation strings are rejected.
  • validDecimal: reject any value with more than one . by checking the split length. Integer, exactly-two-decimals, and empty inputs are unchanged.

Tests

Adds helpers/validation.test.ts — the module's first unit test — with 11 cases across both rules (including the regressions above). Importing the module pulls in its ESM-only uuid dependency (used by isUUID), so jest.config.js gets a transformIgnorePatterns entry allowing Jest to transform uuid. npx jest passes (11/11); eslint is clean.

Relationship to #467 / #468

Same class of bug as the AmountInput gap in #467 (PR #468), but in a different, independent validatorhelpers/validation.ts, used by the debug pages — that #468 does not touch.

Two amount-field rules in helpers/validation.ts accepted malformed input:

- isNumber used !isNaN(parseInt(v)); parseInt parses a leading numeric
  prefix and ignores the rest, so "12abc" passed. Match the whole string
  against an (optionally signed) integer/decimal number instead.
- validDecimal destructured only the second segment of v.split('.'), so a
  value with two decimal points like "1.23.45" passed because its second
  segment ("23") is two digits. Reject any value with more than one ".".

Both rules guard the amount fields on the debug paymentIntents and crypto
payment pages, where a downstream parseFloat would otherwise coerce the
malformed value to a different number. Add helpers/validation.test.ts (the
module's first unit test) covering both, and allow Jest to transform the
ESM-only uuid dependency the module imports so the test can load it.
@devorun
devorun force-pushed the fix/valid-decimal-multiple-dots branch from 454d75a to 3033730 Compare August 14, 2026 20:54
@devorun devorun changed the title fix(validation): reject amounts with more than one decimal point fix(validation): reject malformed numbers in isNumber and validDecimal Aug 14, 2026
@devorun

devorun commented Sep 13, 2026

Copy link
Copy Markdown
Author

Friendly ping on this one — it's been open a few weeks with checks green. It tightens the shared isNumber/validDecimal rules that were accepting malformed amounts (e.g. "12abc", "1.23.45"), with unit tests added. Anything needed to get it reviewed?

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