GitHub Advisoryadvisory · npm
GHSA-53rv-hcvm-rpp9 Lodestar snappy decompression issue
LOW
Official page ↗
- Ecosystem
- npm
- Packages
- @lodestar/reqresp
- Severity
- Low
- Weaknesses
- CWE-703
- Reviewed
- 2025-01-14
Affected packages
• npm @lodestar/reqresp: < 1.25.0 → fixed in 1.25.0
Description
Impact
Unintended permanent chain split affecting greater than or equal to 25% of the network, requiring hard fork (network partition requiring hard fork)
Description
Lodestar client may fail to decode snappy framing compressed messages.
Vulnerability Details
In Req/Resp protocol the message are encoded by using ssz_snappy encoding, which is basically snappy framing compression over ssz encoded message.
It's mentioned here - https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md
```
The token of the negotiated protocol ID specifies the type of encoding to be used for the req/resp interaction. Only one value is possible at this time:
ssz_snappy: The contents are first SSZ-encoded and then compressed with Snappy frames compression. For objects containing a single field, only the field is SSZ-encoded not a container with a single field. For example, the BeaconBlocksByRoot request is an SSZ-encoded list of Root's. This encoding type MUST be supported by all clients.
```
In snappy framing format there a few types of chunks.
We are interested in so called reserved skippable chunks. These are chunks with chunk type in range [0x80, 0xfd]
Let's see how rust snappy handles them https://github.com/BurntSushi/rust-snappy/blob/master/src/read.rs#L137
```
impl io::Read for FrameDecoder {
fn read(&mut self, buf: &mut [u8]) -> io::Result {
...
...
let len = len64 as usize;
match ty {
Err(b) if 0x02 {
// Spec says that chunk types 0x02-0x7F are reserved and
// conformant decoders must return an error.
fail!(Error::UnsupportedChunkType { byte: b });
}
Err(b) if 0x80 {
// Spec says that chunk types 0x80-0xFD are reserved but
// skippable.
self.r.read_exact(&mut self.src[0..len])?;
}
```
Similar code can be found in golang implementation - https://github.com/golang/snappy/blob/master/decode.go#L221
```
func (r *Reader) fill() error {
...
if chunkType 0) {
if (this.buffer.length poc.tgz
$ tar zxf poc.tgz
```
2. run dec1.go to verify that our snappy file decompressed successfully
```
$ go run dec1.go
reading 1.snappy...
read 124 bytes, err
```
3. run dec1.mjs to verify that lodestar fails to decode such file
```
checking chunk type=255
checking chunk type=1
got uncompressed chunk..
checking chunk type=129
file:///../poc/dec1.mjs:74
throw new Error("Unsupported snappy chunk type");
```
Related
Weakness · CWE (1)
- CWE-703 Improper Check or Handling of Exceptional Conditions weakness