GHSA-4672-hwv6-gq62: Medium severity npm/trigger.dev vulnerability

Published Oct 2, 2026
·
Updated

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: 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 FINALDEPLOYMENTSTATUSES, so any in-progress deployment (PENDING/INSTALLING/BUILDING/DEPLOYING) is cancellable.

Contrast — the correctly env-scoped sibling api.v1.deployments.$deploymentId.ts (GET): ts 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 trprod…) and a dev env (key trdev…) and one WorkerDeployment (deploymentpocvictim, status DEPLOYING) in the prod env. As the dev key:

status BEFORE : DEPLOYING GET /api/v1/deployments/deploymentpocvictim (dev key) -> 404 (env-scoped read DENIES it) POST /api/v1/deployments/deploymentpocvictim/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 Software

1 affected componentFixes available
npm/trigger.dev<=4.5.5
4.5.6

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/trigger.dev to a version that resolves this vulnerability.

    Fixed in 4.5.6

Event History

Oct 2, 2026
Advisory Published
via GitHub·10:42 PM
Data Sourced
via GitHub·10:42 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Which deployments are exposed to cancellation by a lower-trust credential?

Any deployment in another environment of the same project, including production deployments, can be targeted. The issue crosses environment boundaries but does not indicate cross-project access.

2

What does an attacker need to exploit this?

An attacker needs a secret API key for any environment within the target project, such as a dev, preview, staging, or CI environment key. That credential can be used to cancel a deployment associated with a different environment in that project.

3

Are hosted and self-hosted deployments affected?

Yes. The advisory identifies both Trigger.dev Cloud and self-hosted deployments as affected.

4

Can the same lower-trust key retrieve details of the production deployment before canceling it?

Not through the deployment GET route described in the advisory. That route is environment-scoped and returns a 404 for a production deployment when accessed with a key from another environment, while the cancel path was not environment-scoped.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203