GitHub Advisoryadvisory · npm

GHSA-53rv-hcvm-rpp9 Lodestar snappy decompression issue

LOW Published 2025-01-14 Modified 2025-01-14 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

References