| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Convex.ThreatModel.NegativeInteger
Contents
Description
Threat model for detecting missing integer boundary checks.
A Negative Integer Attack exploits validators that don't check integer bounds
(e.g., balance >= 0). The attack negates integer fields in output datums,
which may reveal that the validator allows negative values where only positive
values make semantic sense.
Consequences ==
- Logical state corruption: If a validator allows negative balances, users can withdraw more than they deposited, draining funds from a pool.
- Protocol invariant violation: Counters, timestamps, or other fields that should be monotonic or non-negative can be corrupted.
Vulnerable Patterns ==
Pattern: Missing balance check ===
// Vulnerable: no check that balance >= 0 let new_balance = input_balance - withdrawal_amount expect output_datum.balance == new_balance
An attacker with balance = 0 can withdraw funds, creating balance = -100.
The validator doesn't reject this because it never checks balance >= 0.
Mitigation ==
A secure validator should:
- Explicitly check
balance >= 0or appropriate bounds for all integer fields - Validate that counters only increase (or decrease within bounds)
- Use unsigned integers where semantically appropriate (though Plutus uses Integer)
This threat model tests if a script output with an inline datum still validates when integer fields are negated.
Synopsis
Negative integer attack
negativeIntegerAttack :: ThreatModel () Source #
Check for missing integer boundary checks.
For a transaction with script outputs containing inline datums:
- Recursively negate all
ScriptDataNumberfields in the datum - If the transaction still validates, the script doesn't enforce proper bounds checking on integer fields.
This catches vulnerabilities where validators allow negative values for fields like balances, counters, or timestamps that should be non-negative.
negativeIntegerAttack -- Negate all integers in the datum
negateIntegers :: ScriptData -> ScriptData Source #
Recursively negate all integer fields in a ScriptData value.
For ScriptDataNumber n, returns ScriptDataNumber (negate n).
Recursively processes ScriptDataConstructor fields, lists, and maps.
For other ScriptData variants (Bytes), returns the value unchanged.