Vulnerabilities in pkg:npm/@lodestar/reqresp
PACKAGEGHSA-m9c9-mc2h-9wjw is a LOW lodestar snappy checksum issue vulnerability (CWE-354: Improper Validation of Integrity Check Value) affecting @lodestar/reqresp libraries in the npm ecosystem. The issue involves lodestar snappy checksum issue. Remediation is available by upgrading affected packages to version 1.25.0.
pkg:npm/@lodestar/reqresp
Vulnerability advisories affecting package pkg:npm/@lodestar/reqresp. Select an advisory below to view technical details or fixes.
| Advisory ID | CVE / NVD | Severity | Summary |
|---|---|---|---|
| GHSA-m9c9-mc2h-9wjw | - | LOW | Lodestar snappy checksum issue |
| GHSA-53rv-hcvm-rpp9 | - | LOW | Lodestar snappy decompression issue |
GHSA-m9c9-mc2h-9wjw at a Glance
How to Fix GHSA-m9c9-mc2h-9wjw
To remediate this vulnerability, upgrade all affected @lodestar/reqresp dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install @lodestar/reqresp@1.25.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls @lodestar/reqresp
How to Check if You Are Affected
To determine whether your Node.js application is affected by GHSA-m9c9-mc2h-9wjw, inspect your project dependencies using npm:
npm ls @lodestar/reqresp
Analyze the terminal output to locate any version of @lodestar/reqresp in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.25.0), your application is affected.
Note: The npm ls @lodestar/reqresp command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-354: Improper Validation of Integrity Check Value, where the product does not validate or incorrectly validates the integrity check values or "checksums" of a message. this may prevent it from detecting if the data has been modified or corrupted in transmission. In @lodestar/reqresp, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
GHSA-m9c9-mc2h-9wjw Affected @lodestar/reqresp Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
@lodestar/reqresp
|
npm |
< 1.25.0
|
1.25.0
|
References
Frequently Asked Questions
What is GHSA-m9c9-mc2h-9wjw?
Which @lodestar/reqresp versions are affected?
What version fixes GHSA-m9c9-mc2h-9wjw?
Is @lodestar/reqresp affected?
What CWE is associated with GHSA-m9c9-mc2h-9wjw?
How can I check npm dependencies for GHSA-m9c9-mc2h-9wjw?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-m9c9-mc2h-9wjw",
"modified" : "2025-01-14T22:04:02Z",
"published" : "2025-01-14T22:04:02Z",
"aliases" : [ ],
"summary" : "Lodestar snappy checksum issue",
"details" : "### Impact\nUnintended permanent chain split affecting greater than or equal to 25% of the network, requiring hard fork (network partition requiring hard fork)\n\nLodestar does not verify checksum in snappy framing uncompressed chunks.\n\n### Vulnerability Details\nIn Req/Resp protocol the messages are encoded by using ssz_snappy encoding, which is a snappy framing compression over ssz encoded message.\n\nIn snappy framing format there are uncompressed chunks, each such chunk is prefixed with a checksum.\n\nLet's see how golang implementation parses such chunks - https://github.com/golang/snappy/blob/master/decode.go#L176\n\n```\n\tcase chunkTypeUncompressedData:\n\t\t\t// Section 4.3. Uncompressed data (chunk type 0x01).\n\t\t\tif chunkLen < checksumSize {\n\t\t\t\tr.err = ErrCorrupt\n\t\t\t\treturn r.err\n\t\t\t}\n\t\t\tbuf := r.buf[:checksumSize]\n\t\t\tif !r.readFull(buf, false) {\n\t\t\t\treturn r.err\n\t\t\t}\n\t\t\tchecksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24\n\t\t\t// Read directly into r.decoded instead of via r.buf.\n\t\t\tn := chunkLen - checksumSize\n\t\t\tif n > len(r.decoded) {\n\t\t\t\tr.err = ErrCorrupt\n\t\t\t\treturn r.err\n\t\t\t}\n\t\t\tif !r.readFull(r.decoded[:n], false) {\n\t\t\t\treturn r.err\n\t\t\t}\n\t\t\tif crc(r.decoded[:n]) != checksum {\n\t\t\t\tr.err = ErrCorrupt\n\t\t\t\treturn r.err\n\t\t\t}\n\t\t\tr.i, r.j = 0, n\n\t\t\tcontinue\n```\n\nAs you can see, if checksum is incorrect, decoder fails and returns error.\n\nNow let's look at lodestar decoder https://github.com/ChainSafe/lodestar/blob/unstable/packages/reqresp/src/encodingStrategies/sszSnappy/snappyFrames/uncompress.ts#L17\n\n```\nuncompress(chunk: Uint8ArrayList): Uint8ArrayList | null {\n this.buffer.append(chunk);\n const result = new Uint8ArrayList();\n while (this.buffer.length > 0) {\n if (this.buffer.length < 4) break;\n\n const type = getChunkType(this.buffer.get(0));\n const frameSize = getFrameSize(this.buffer, 1);\n\n if (this.buffer.length - 4 < frameSize) {\n break;\n }\n\n const data = this.buffer.subarray(4, 4 + frameSize);\n this.buffer.consume(4 + frameSize);\n\n if (!this.state.foundIdentifier && type !== ChunkType.IDENTIFIER) {\n throw \"malformed input: must begin with an identifier\";\n }\n\n if (type === ChunkType.IDENTIFIER) {\n if (!Buffer.prototype.equals.call(data, IDENTIFIER)) {\n throw \"malformed input: bad identifier\";\n }\n this.state.foundIdentifier = true;\n continue;\n }\n\n if (type === ChunkType.COMPRESSED) {\n result.append(uncompress(data.subarray(4)));\n }\n if (type === ChunkType.UNCOMPRESSED) {\n1) result.append(data.subarray(4));\n }\n }\n if (result.length === 0) {\n return null;\n }\n return result;\n }\n```\n\nAs you can see, checksum is not verified, bytes are appended to 'result'\n\n### Proof of Concept\n\nHow to reproduce:\n\nget poc via [gist link](https://gist.github.com/gln7/aab55674431b1c8d42a59ccf9d7cbf60) and run it:\n\n```\n$ node dec1.mjs \nchecking chunk type=255\nchecking chunk type=1\ngot uncompressed chunk..\nDecompressed ok 124 bytes\n```\n",
"severity" : [ ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "@lodestar/reqresp"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "1.25.0"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/ChainSafe/lodestar/security/advisories/GHSA-m9c9-mc2h-9wjw"
}, {
"type" : "WEB",
"url" : "https://github.com/ChainSafe/lodestar/commit/18a0d681dbcc51fb2ac9456f31e91f4e31a18300"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/ChainSafe/lodestar"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-354" ],
"severity" : "LOW",
"github_reviewed" : true,
"github_reviewed_at" : "2025-01-14T22:04:02Z",
"nvd_published_at" : null
}
}