mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Add content from: Use mutation testing to find the bugs your tests don't catch
- Remove searchindex.js (auto-generated file)
This commit is contained in:
parent
74cc86ad2c
commit
a7b192a182
File diff suppressed because one or more lines are too long
@ -931,3 +931,5 @@
|
||||
- [Post Exploitation](todo/post-exploitation.md)
|
||||
- [Investment Terms](todo/investment-terms.md)
|
||||
- [Cookies Policy](todo/cookies-policy.md)
|
||||
|
||||
- [Mutation Testing With Slither](blockchain/smart-contract-security/testing-and-analysis/mutation-testing-with-slither.md)
|
@ -176,6 +176,14 @@ Transactions in Ethereum involve a sender and a recipient, which can be either u
|
||||
|
||||
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
|
||||
|
||||
## Smart Contract Security
|
||||
|
||||
- Mutation testing to find blind spots in test suites:
|
||||
|
||||
{{#ref}}
|
||||
../smart-contract-security/testing-and-analysis/mutation-testing-with-slither.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
|
||||
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
|
||||
|
@ -0,0 +1,126 @@
|
||||
# Mutation Testing for Solidity with Slither (slither-mutate)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Mutation testing "tests your tests" by systematically introducing small changes (mutants) into your Solidity code and re-running your test suite. If a test fails, the mutant is killed. If the tests still pass, the mutant survives, revealing a blind spot in your test suite that line/branch coverage cannot detect.
|
||||
|
||||
Key idea: Coverage shows code was executed; mutation testing shows whether behavior is actually asserted.
|
||||
|
||||
## Why coverage can deceive
|
||||
|
||||
Consider this simple threshold check:
|
||||
|
||||
```solidity
|
||||
function verifyMinimumDeposit(uint256 deposit) public returns (bool) {
|
||||
if (deposit >= 1 ether) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Unit tests that only check a value below and a value above the threshold can reach 100% line/branch coverage while failing to assert the equality boundary (==). A refactor to `deposit >= 2 ether` would still pass such tests, silently breaking protocol logic.
|
||||
|
||||
Mutation testing exposes this gap by mutating the condition and verifying your tests fail.
|
||||
|
||||
## Common Solidity mutation operators
|
||||
|
||||
Slither’s mutation engine applies many small, semantics-changing edits, such as:
|
||||
- Operator replacement: `+` ↔ `-`, `*` ↔ `/`, etc.
|
||||
- Assignment replacement: `+=` → `=`, `-=` → `=`
|
||||
- Constant replacement: non-zero → `0`, `true` ↔ `false`
|
||||
- Condition negation/replacement inside `if`/loops
|
||||
- Comment out whole lines (CR: Comment Replacement)
|
||||
- Replace a line with `revert()`
|
||||
- Data type swaps: e.g., `int128` → `int64`
|
||||
|
||||
Goal: Kill 100% of generated mutants, or justify survivors with clear reasoning.
|
||||
|
||||
## Running mutation testing with slither-mutate
|
||||
|
||||
Requirements: Slither v0.10.2+.
|
||||
|
||||
- List options and mutators:
|
||||
|
||||
```bash
|
||||
slither-mutate --help
|
||||
slither-mutate --list-mutators
|
||||
```
|
||||
|
||||
- Foundry example (capture results and keep a full log):
|
||||
|
||||
```bash
|
||||
slither-mutate ./src/contracts --test-cmd="forge test" &> >(tee mutation.results)
|
||||
```
|
||||
|
||||
- If you don’t use Foundry, replace `--test-cmd` with how you run tests (e.g., `npx hardhat test`, `npm test`).
|
||||
|
||||
Artifacts and reports are stored in `./mutation_campaign` by default. Uncaught (surviving) mutants are copied there for inspection.
|
||||
|
||||
### Understanding the output
|
||||
|
||||
Report lines look like:
|
||||
|
||||
```text
|
||||
INFO:Slither-Mutate:Mutating contract ContractName
|
||||
INFO:Slither-Mutate:[CR] Line 123: 'original line' ==> '//original line' --> UNCAUGHT
|
||||
```
|
||||
|
||||
- The tag in brackets is the mutator alias (e.g., `CR` = Comment Replacement).
|
||||
- `UNCAUGHT` means tests passed under the mutated behavior → missing assertion.
|
||||
|
||||
## Reducing runtime: prioritize impactful mutants
|
||||
|
||||
Mutation campaigns can take hours or days. Tips to reduce cost:
|
||||
- Scope: Start with critical contracts/directories only, then expand.
|
||||
- Prioritize mutators: If a high-priority mutant on a line survives (e.g., entire line commented), you can skip lower-priority variants for that line.
|
||||
- Parallelize tests if your runner allows it; cache dependencies/builds.
|
||||
- Fail-fast: stop early when a change clearly demonstrates an assertion gap.
|
||||
|
||||
## Triage workflow for surviving mutants
|
||||
|
||||
1) Inspect the mutated line and behavior.
|
||||
- Reproduce locally by applying the mutated line and running a focused test.
|
||||
|
||||
2) Strengthen tests to assert state, not only return values.
|
||||
- Add equality-boundary checks (e.g., test threshold `==`).
|
||||
- Assert post-conditions: balances, total supply, authorization effects, and emitted events.
|
||||
|
||||
3) Replace overly permissive mocks with realistic behavior.
|
||||
- Ensure mocks enforce transfers, failure paths, and event emissions that occur on-chain.
|
||||
|
||||
4) Add invariants for fuzz tests.
|
||||
- E.g., conservation of value, non-negative balances, authorization invariants, monotonic supply where applicable.
|
||||
|
||||
5) Re-run slither-mutate until survivors are killed or explicitly justified.
|
||||
|
||||
## Case study: revealing missing state assertions (Arkis protocol)
|
||||
|
||||
A mutation campaign during an audit of the Arkis DeFi protocol surfaced survivors like:
|
||||
|
||||
```text
|
||||
INFO:Slither-Mutate:[CR] Line 33: 'cmdsToExecute.last().value = _cmd.value' ==> '//cmdsToExecute.last().value = _cmd.value' --> UNCAUGHT
|
||||
```
|
||||
|
||||
Commenting out the assignment didn’t break the tests, proving missing post-state assertions. Root cause: code trusted a user-controlled `_cmd.value` instead of validating actual token transfers. An attacker could desynchronize expected vs. actual transfers to drain funds. Result: high severity risk to protocol solvency.
|
||||
|
||||
Guidance: Treat survivors that affect value transfers, accounting, or access control as high-risk until killed.
|
||||
|
||||
## Practical checklist
|
||||
|
||||
- Run a targeted campaign:
|
||||
- `slither-mutate ./src/contracts --test-cmd="forge test"`
|
||||
- Triage survivors and write tests/invariants that would fail under the mutated behavior.
|
||||
- Assert balances, supply, authorizations, and events.
|
||||
- Add boundary tests (`==`, overflows/underflows, zero-address, zero-amount, empty arrays).
|
||||
- Replace unrealistic mocks; simulate failure modes.
|
||||
- Iterate until all mutants are killed or justified with comments and rationale.
|
||||
|
||||
## References
|
||||
|
||||
- [Use mutation testing to find the bugs your tests don't catch (Trail of Bits)](https://blog.trailofbits.com/2025/09/18/use-mutation-testing-to-find-the-bugs-your-tests-dont-catch/)
|
||||
- [Arkis DeFi Prime Brokerage Security Review (Appendix C)](https://github.com/trailofbits/publications/blob/master/reviews/2024-12-arkis-defi-prime-brokerage-securityreview.pdf)
|
||||
- [Slither (GitHub)](https://github.com/crytic/slither)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
@ -176,6 +176,14 @@ Transactions in Ethereum involve a sender and a recipient, which can be either u
|
||||
|
||||
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
|
||||
|
||||
## Smart Contract Security
|
||||
|
||||
- Mutation testing to find blind spots in test suites:
|
||||
|
||||
{{#ref}}
|
||||
../blockchain/smart-contract-security/testing-and-analysis/mutation-testing-with-slither.md
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
|
||||
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
|
||||
|
Loading…
x
Reference in New Issue
Block a user