Coverage-guided fuzzer for React Server Components Flight protocol using Jazzer.js.
Target: react-server-dom-webpack - React's Flight protocol implementation
The Flight protocol is the wire format React uses to communicate between server and client components. It handles:
- Server Actions (form submissions, mutations)
- Server-to-client data streaming
- Client-to-server argument passing
| Function | Direction | What it does |
|---|---|---|
decodeReply() |
client→server | Deserialize arguments |
decodeReplyFromAsyncIterable() |
client→server | Streaming deserialization |
createFromReadableStream() |
server→client | Parse server response |
npm install
npm run generate:seeds
npm run fuzzPress Ctrl+C to stop. Crashes saved to crashes/.
| Command | Target | Description |
|---|---|---|
npm run fuzz |
decodeReply() |
Main server-side fuzzer |
npm run fuzz:stream |
decodeReplyFromAsyncIterable() |
Streaming input fuzzer |
npm run fuzz:traversal |
decodeReply() |
Property path patterns ($N:path) |
npm run fuzz:client |
createFromReadableStream() |
Client-side fuzzer |
| Command | Description |
|---|---|
npm run crash:triage |
Analyze and prioritize crashes |
npm run crash:replay <file> |
Replay a specific crash |
npm run coverage |
Show corpus feature coverage |
├── fuzz/
│ ├── FuzzFlightProtocol.js # Server-side decodeReply
│ ├── FuzzFlightStream.js # Streaming input
│ ├── FuzzColonTraversal.js # Property path traversal
│ ├── FuzzClientStream.js # Client-side parsing
│ └── flight.dict # libFuzzer dictionary
├── corpus/
│ ├── protocol/ # Seeds for main fuzzer
│ ├── stream/ # Seeds for streaming fuzzer
│ └── traversal/ # Seeds for traversal fuzzer
├── crashes/ # Crash artifacts
└── scripts/
├── generateSeeds.js # Seed generator
├── triageCrashes.js # Crash analysis
└── replayCrash.js # Crash replay
"0" = payload (arguments)
"1" = chunk 1 (referenced by $1)
"2" = chunk 2 (referenced by $2)
...
| Pattern | Meaning |
|---|---|
$1 |
Reference chunk 1 |
$1:a:b |
chunk1["a"]["b"] |
$undefined |
undefined value |
$Infinity |
Infinity |
$B0 |
Blob reference |
$T0 |
TypedArray reference |
Seeds contain both chunks and payload:
byte 0: num_chunks (1-5)
remaining: chunk1 | chunk2 | ... | payload (split evenly)
The fuzzer can mutate both chunk content AND payload.
- Property traversal crashes (
$1:nonexistent:path) - Prototype pollution (
$1:__proto__) - Parser edge cases
- Type confusion
- Client-side parsing bugs
- Node.js >= 18
- npm
MIT