Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦 npm
Not in CISA KEV

CVE-2026-114079 — trigger.dev

Fix: triggerdotdev/trigger.dev#4316

CVE-2026-114079 is a CWE-639 vulnerability in trigger.dev. A fix is available for trigger.dev — see the affected versions and patch details below.

Trigger.dev before 4.5.6 Cross-Environment Deployment Cancel via Cancel Endpoint

Also known asGHSA-4672-hwv6-gq62
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 23, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

EPSS Exploitation Probability

via FIRST.org ↗
0.2%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs12th percentile — riskier than 12% of all scored CVEsHighest risk

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

Real-World Exposure

1 pkg affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

1other npm packages depend on this — each one inherits the vulnerability until it's patched upstream
trigger.devnpm
572Kdownloads / week

Description

Summary

Trigger.dev isolates each project into multiple environments (dev, staging, prod, and per-PR preview branches), each with its own secret API key — the environment is a trust boundary (a dev/preview/CI key is lower-trust than a prod key). Most API routes enforce this by scoping resource lookups to the authenticated key's environment (where: { friendlyId, runtimeEnvironmentId: auth.environment.id }).

The deployment cancel path does not. DeploymentService.getDeployment() scopes the lookup by projectId only — never environmentId — so a secret key for any environment in a project can cancel a deployment belonging to any other environment of the same project, including production. The deployment GET route, by contrast, is env-scoped — so the same key that is 404'd when trying to read a prod deployment can nonetheless cancel it. That asymmetry is the bug.

Affected

apps/webapp, HEAD 5d99457 (current main). Affects self-hosted and cloud.

Root cause

apps/webapp/app/routes/api.v1.deployments.$deploymentId.cancel.ts authenticates to an environment and calls deploymentService.cancelDeployment(authenticatedEnv, deploymentId, ...).

apps/webapp/app/v3/services/deployment.server.ts:

public cancelDeployment(authenticatedEnv: Pick<AuthenticatedEnvironment,"projectId">, friendlyId, ...) {
  return this.getDeployment(authenticatedEnv.projectId, friendlyId)   // projectId only
    .andThen(validateDeployment)                                      // rejects only FINAL statuses
    .andThen(cancelDeployment);                                       // updateMany -> status CANCELED
}
private getDeployment(projectId: string, friendlyId: string) {
  return this._prisma.workerDeployment.findFirst({
    where: { friendlyId, projectId },        // <-- NO environmentId filter
  });
}

cancelDeployment accepts authenticatedEnv but its type is literally Pick<AuthenticatedEnvironment,"projectId"> — it discards the environment identity. validateDeployment blocks only FINAL_DEPLOYMENT_STATUSES, so any in-progress deployment (PENDING/INSTALLING/BUILDING/DEPLOYING) is cancellable.

Contrast — the correctly env-scoped sibling api.v1.deployments.$deploymentId.ts (GET):

const deployment = await prisma.workerDeployment.findFirst({
  where: { friendlyId: deploymentId, environmentId: authenticatedEnv.id },   // env-scoped
});

Reads are env-scoped; the cancel mutation is not. The same getDeployment(authenticatedEnv.projectId, …) helper also backs the deployment progress methods (deployment.server.ts:172,329), so the projectId-only scope is a small class.

Runtime PoC (proven on the self-host stack)

Seeded one project with a prod env (key tr_prod_…) and a dev env (key tr_dev_…) and one WorkerDeployment (deployment_pocvictim, status DEPLOYING) in the prod env. As the dev key:

status BEFORE                                                  : DEPLOYING
GET  /api/v1/deployments/deployment_pocvictim   (dev key)      -> 404   (env-scoped read DENIES it)
POST /api/v1/deployments/deployment_pocvictim/cancel (dev key) -> 204
status AFTER                                                   : CANCELED   (prod deploy canceled by the dev key)
CONTROL: same cancel with a DIFFERENT project's key            -> 404   (projectId scope blocks cross-project)

The dev key cannot read the prod deployment (404) yet cancels it (204 → CANCELED); a different project's key is correctly 404'd — so the gap is precisely cross-environment within a project.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
📦npmtrigger.devall versions4.5.6npm install trigger.dev@4.5.6

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for trigger.dev, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update trigger.dev to 4.5.6 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-114079 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

Frequently Asked Questions

### Summary Trigger.dev isolates each project into multiple **environments** (`dev`, `staging`, `prod`, and per-PR `preview` branches), each with its **own secret API key** — the environment is a trust boundary (a `dev`/preview/CI key is lower-trust than a `prod` key). Most API routes enforce this by scoping resource lookups to the authenticated key's environment (`where: { friendlyId, runtimeEnvironmentId: auth.environment.id }`). The deployment **cancel** path does not. `DeploymentService.getDeployment()` scopes the lookup by **`projectId` only** — never `environmentId` — so a secret key f
O3 Security · Impact-Aware SCA

Is CVE-2026-114079 in your dependencies?

Find it across npm, including transitive dependencies.

CVE-2026-114079: trigger.dev — Fixed in 4.5.6