Summary
LocalDevAccountCreator accepts non-canonical validator IDs in overridePublicKeys because it parses the validator ID with Number(...) and only checks Number.isNaN(...).
As a result, values such as 1.5, 1e0, and 01 are accepted as validator IDs even though they are not canonical integer validator IDs.
Affected File
scripts/genesis/AccountCreator.ts
Observed Behavior
overridePublicKeys entries are parsed from strings in this format:
<validator_id>:<public_key>
The validator ID is currently converted with Number(...). This accepts multiple forms that should likely be rejected for an integer identifier.
Examples observed on current code:
1 ACCEPTED [[1,"0x1111...1111"]]
1.5 ACCEPTED [[1.5,"0x1111...1111"]]
1e0 ACCEPTED [[1,"0x1111...1111"]]
01 ACCEPTED [[1,"0x1111...1111"]]
The parser accepts:
- fractional values, such as
1.5
- scientific notation, such as
1e0
- non-canonical leading-zero values, such as
01
Expected Behavior
overridePublicKeys validator IDs should be canonical non-negative decimal integers.
For example, these should be accepted:
These should be rejected:
1.5
1e0
01
-1
NaN
Infinity
- empty strings
Reproduction
I verified this with a focused repro against the current parser.
Current behavior:
1 ACCEPTED [[1,"0x1111...1111"]]
1.5 ACCEPTED [[1.5,"0x1111...1111"]]
1e0 ACCEPTED [[1,"0x1111...1111"]]
01 ACCEPTED [[1,"0x1111...1111"]]
A negative regression test also fails on current code:
assert.throws(
() => new LocalDevAccountCreator({ overridePublicKeys: `1.5:${key}` }),
/Invalid validator ID/
)
The constructor currently does not throw for 1.5.
Why This Matters
validator_id is used as an identifier, so accepting fractional or alternate numeric encodings can cause ambiguous or unintended mappings.
For example:
1e0 and 1 both resolve to the same numeric ID.
01 and 1 both resolve to the same numeric ID.
1.5 remains a non-integer key, which is unexpected for a validator ID.
Strict parsing also makes genesis/dev configuration errors fail early instead of producing confusing account/public-key mappings.
Suggested Fix
Validate the validator ID string before converting it to Number.
For example:
- require canonical decimal integer syntax:
/^(0|[1-9][0-9]*)$/
- then convert with
Number(...)
- then verify:
Number.isSafeInteger(id)
id >= 0
Potential Regression Tests
Add tests for overridePublicKeys parsing that verify:
Accepted:
Rejected:
1.5:<key>
1e0:<key>
01:<key>
-1:<key>
NaN:<key>
Infinity:<key>
:<key>
Summary
LocalDevAccountCreatoraccepts non-canonical validator IDs inoverridePublicKeysbecause it parses the validator ID withNumber(...)and only checksNumber.isNaN(...).As a result, values such as
1.5,1e0, and01are accepted as validator IDs even though they are not canonical integer validator IDs.Affected File
scripts/genesis/AccountCreator.tsObserved Behavior
overridePublicKeysentries are parsed from strings in this format:<validator_id>:<public_key>
The validator ID is currently converted with
Number(...). This accepts multiple forms that should likely be rejected for an integer identifier.Examples observed on current code:
1 ACCEPTED [[1,"0x1111...1111"]]
1.5 ACCEPTED [[1.5,"0x1111...1111"]]
1e0 ACCEPTED [[1,"0x1111...1111"]]
01 ACCEPTED [[1,"0x1111...1111"]]
The parser accepts:
1.51e001Expected Behavior
overridePublicKeysvalidator IDs should be canonical non-negative decimal integers.For example, these should be accepted:
0142These should be rejected:
1.51e001-1NaNInfinityReproduction
I verified this with a focused repro against the current parser.
Current behavior:
1 ACCEPTED [[1,"0x1111...1111"]]
1.5 ACCEPTED [[1.5,"0x1111...1111"]]
1e0 ACCEPTED [[1,"0x1111...1111"]]
01 ACCEPTED [[1,"0x1111...1111"]]
A negative regression test also fails on current code:
The constructor currently does not throw for
1.5.Why This Matters
validator_idis used as an identifier, so accepting fractional or alternate numeric encodings can cause ambiguous or unintended mappings.For example:
1e0and1both resolve to the same numeric ID.01and1both resolve to the same numeric ID.1.5remains a non-integer key, which is unexpected for a validator ID.Strict parsing also makes genesis/dev configuration errors fail early instead of producing confusing account/public-key mappings.
Suggested Fix
Validate the validator ID string before converting it to
Number.For example:
/^(0|[1-9][0-9]*)$/
Number(...)Number.isSafeInteger(id)
id >= 0
Potential Regression Tests
Add tests for
overridePublicKeysparsing that verify:Accepted:
0:<key>1:<key>42:<key>Rejected:
1.5:<key>1e0:<key>01:<key>-1:<key>NaN:<key>Infinity:<key>:<key>