TL;DR
- protobufjs has three medium-severity issues: two denial‑of‑service risks in .proto option parsing and a prototype mutation weakness in text format string map parsing.
- If you use protobufjs v7, upgrade to 7.6.5 or later. If you use v8, upgrade to 8.6.6 or later (the prototype mutation was fixed in 8.6.5, and the latest DoS fix in 8.6.6).
- These bugs could let attackers hang a service or tamper with returned map objects.
- Your next scheduled FrameScan run will automatically check for these detections.
At-a-glance
| ID (official advisory) | Plain-English impact | Severity | Affected versions | Fixed version |
|---|---|---|---|---|
| protobufjs < 7.6.5 — DoS in .proto option parsing | Crafted .proto can hang parsing | medium | < 7.6.5 | 7.6.5 |
| protobufjs < 8.6.5 — Text format string map parsing prototype mutation | Map prototype can be mutated | medium | < 8.6.5 | 8.6.5 |
| protobufjs < 8.6.6 — DoS in .proto option parsing | Crafted .proto can hang parsing | medium | < 8.6.6 | 8.6.6 |
Details and guidance
protobufjs < 7.6.5 — Denial of Service via infinite loop in .proto option parsing
An attacker who can influence .proto definitions or options could trigger an infinite loop during parsing. The result is that your process can hang and stop handling requests, causing a denial of service. Medium severity means treat it seriously, especially in any workflow that processes external or untrusted .proto files.
Technical details
The issue involves an infinite loop when parsing option constructs inside .proto files. A robust parser must advance input state on every iteration and bail out on malformed sequences.
Illustrative example — not protobufjs source:
// Vulnerable pattern (illustrative): loop may not advance on malformed input
function parseOptions(tokens) {
let i = 0;
const options = {};
while (i < tokens.length) {
const t = tokens[i];
if (t.type === 'OPTION_START') {
// BUG: on unexpected token, neither i++ nor return occurs -> infinite loop
if (!tokens[i + 1] || tokens[i + 1].type !== 'IDENT') {
continue; // i is unchanged -> potential infinite loop
}
options[tokens[i + 1].value] = true;
i += 2;
} else {
i++;
}
}
return options;
}
// Fixed pattern (illustrative): always advance or fail fast with a limit
function parseOptionsSafe(tokens, maxTokens = 100000) {
let i = 0;
let steps = 0;
const options = {};
while (i < tokens.length) {
if (++steps > maxTokens) throw new Error('Option parsing limit exceeded');
const t = tokens[i];
if (t.type === 'OPTION_START') {
const ident = tokens[i + 1];
if (!ident || ident.type !== 'IDENT') {
i++; // ensure progress on malformed input
continue;
}
options[ident.value] = true;
i += 2; // progress guaranteed
} else {
i++;
}
}
return options;
}
protobufjs < 8.6.5 — Text Format string map parsing can mutate returned map object prototype
When parsing text-format string maps, a caller could receive an object whose prototype is unexpectedly mutable. That can lead to surprising behavior, property shadowing, or unsafe assumptions in downstream code. Treat this as a data integrity and safety fix.
Technical details
Map-like results should not inherit from Object.prototype when keys may come from untrusted input. Returning a plain object can allow prototype fields to be set or influenced via special keys.
Illustrative example — not protobufjs source:
// Vulnerable pattern (illustrative): map inherits from Object.prototype
function parseStringMap(pairs) {
const map = {}; // inherits prototype
for (const [k, v] of pairs) {
map[String(k)] = String(v);
}
return map; // prototype can be mutated elsewhere
}
// Fixed pattern (illustrative): create a null-prototype object and freeze prototype
function parseStringMapSafe(pairs) {
const map = Object.create(null); // no inherited props
for (const [k, v] of pairs) {
map[String(k)] = String(v);
}
return map;
}
protobufjs < 8.6.6 — Denial of Service via infinite loop in .proto option parsing
A second parser hardening fix for v8 ensures crafted .proto options cannot cause the process to spin indefinitely. Services that compile or load .proto files at runtime should prioritize this update to avoid request starvation or job stalls.
Technical details
As with the v7 issue, safe parsers must guarantee forward progress and enforce iteration limits.
Illustrative example — not protobufjs source:
function parseOptionsHardened(tokens) {
let i = 0;
const options = {};
const maxSteps = Math.max(1000, tokens.length * 10);
for (let steps = 0; i < tokens.length; steps++) {
if (steps > maxSteps) throw new Error('Parsing aborted: limit exceeded');
const t = tokens[i];
if (t.type !== 'OPTION_START') {
i++;
continue;
}
const ident = tokens[i + 1];
if (!ident || ident.type !== 'IDENT') {
i++; // ensure forward progress on malformed input
continue;
}
options[ident.value] = true;
i += 2;
}
return options;
}
Remediation
- If you are on protobufjs v7:
- Upgrade to 7.6.5 or later.
- npm:
npm install protobufjs@^7.6.5 - yarn:
yarn add protobufjs@^7.6.5 - pnpm:
pnpm add protobufjs@^7.6.5 - If you are on protobufjs v8:
- Upgrade to 8.6.6 or later (covers both the prototype mutation fix in 8.6.5 and the DoS fix in 8.6.6).
- npm:
npm install protobufjs@^8.6.6 - yarn:
yarn add protobufjs@^8.6.6 - pnpm:
pnpm add protobufjs@^8.6.6
Official security-release reference: [MISSING: advisory link]
Call to action
- Existing customers: review your latest results and trigger an on-demand scan at https://framescan.io/scan
- New to FrameScan? Your first scan per verified domain is free: https://framescan.io/#pricing