Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.
Open advisories
10 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.
Affected version: trigger.dev 4.5.3 (4.5.6 was advertised by the CLI but was not tested). A staging dry-run executed with trigger.dev deploy --env staging --dry-run --log-level debug. The debug output logged the complete build-worker options object. Its envVars property contained unredacted values for every resolved staging variable, including database connection strings and service credentials. The non-debug environment listing correctly hides values, so users can reasonably expect deployment logs not to print secrets. Impact: anyone with access to a developer terminal transcript, CI debug log, captured agent/tool output, or support bundle can recover deployment secrets even though no deployment occurs. Reproduction: 1. Configure a Trigger.dev project with a secret environment variable. 2. Run the command above with an authenticated profile. 3. Inspect the Starting buildWorker debug record. 4. options.envVars contains the plaintext value. No real credential is included in this…
Recommended action: Upgrade to 4.5.9 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
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…
Recommended action: Upgrade to 4.5.6 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
A cross-tenant SQL injection in the TSQL query compiler lets any authenticated trigger.dev customer read every other tenant's analytics data. The customer-facing query endpoint POST /api/v1/query accepts a TSQL/TRQL query that is compiled to ClickHouse SQL by internal-packages/tsql. The compiler parameterizes or escapes all user input and injects a per-tenant WHERE guard — except the window-function name, which is concatenated into the SQL string with no allowlist and no escaping. By smuggling a backtick-quoted identifier into that position, an attacker injects a raw subquery (e.g. (SELECT ... FROM taskrunsv2 WHERE organizationid = 'orgVICTIM')) that sits outside the tenant guard, exfiltrating another organization's rows. Verified end-to-end against the real compiler and a live ClickHouse. Details Vulnerable sink — internal-packages/tsql/src/query/printer.ts:3073-3075, ClickHousePrinter.visitWindowFunction: node.name is emitted directly into the SQL with no allowlist check…
Recommended action: Upgrade to 4.5.6 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The POST handler for /realtime/v1/streams/:runId/:streamId has no authentication. Any entity that knows or guesses a run friendlyId can inject arbitrary data into its realtime stream. Vulnerability Details File: apps/webapp/app/routes/realtime.v1.streams.$runId.$streamId.ts The action handler (line 17) has no auth wrapper. The code comment says: "Plain action for backwards compatibility with older clients that don't send auth headers." The run lookup at line 29 uses where: { friendlyId: runId } with NO environment scoping (runtimeEnvironmentId is not checked), so production runs are accessible. Run friendlyIds follow predictable patterns (e.g., run1234abcd). Steps to Reproduce Impact Unauthenticated data injection into any run realtime stream. Cross-environment access (no scoping).
Recommended action: Upgrade to 4.5.5 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Self-hosted trigger.dev v4 instances deployed using the provided Docker Compose configuration with default secrets from hosting/docker/.env.example are vulnerable to a multi-stage unauthenticated attack chain leading to complete infrastructure compromise. Vulnerability Details The hosting/docker/.env.example file contains hardcoded cryptographic secrets: The MAGICLINKSECRET is used by remix-auth-email-link@2.0.2 to create authentication tokens via CryptoJS AES encryption. An attacker who knows this secret can forge valid magic links that authenticate as any email address without email delivery. The validateSessionMagicLink option defaults to false in the library (never overridden by trigger.dev), so no session-side validation occurs. User accounts are auto-created when WHITELISTEDEMAILS is not set (the default for self-hosted). Steps to Reproduce Setup Step 1: Forge magic link token Step 2: Authenticate via forged magic link Step 3: Verify database access from runner network…
Recommended action: Upgrade to 4.5.6 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
TL;DR The /coordinator Socket.IO namespace mounts on every webapp boot and authenticates with a default secret ("coordinator-secret") baked into source. The override variable isn't documented in the self-host docs, .env.example, or helm values, so any operator who didn't read source ships with the default. Once connected, READYFOREXECUTION returns the run's decrypted env vars. Anyone who can reach a default-config self-hosted webapp can pull production secrets out of any run whose internal id they can find. Vulnerabilities This attack is made possible by 3 vulnerabilities in Trigger.dev: 1. Hardcoded default authentication secret (CWE-798, Critical) PROVIDERSECRET and COORDINATORSECRET are declared with .default("provider-secret") / .default("coordinator-secret") in apps/webapp/app/env.server.ts:289-290. The values are present in the public source repo, neither var is documented in docs/self-hosting/env/.mdx, hosting/docker/.env.example, or hosting/k8s/helm/values.yaml, and the auth…
Recommended action: Upgrade to 4.5.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
A WEBHOOK alert channel stores a user-supplied url. When an alert fires (deployment/run failure, error groups), the webapp server (alertsWorker - DeliverAlertService) POSTs the HMAC-signed alert payload to that URL via fetch(webhook.url, ...). The URL is never validated against a host allowlist or private-IP/metadata blocklist (a repo-wide search for 169.254, isPrivate, isLoopback, net.isIP, ssrf returns ZERO hits), and the API route's URL field is just z.string().optional() (no syntax check at all). So an authenticated tenant can point the webhook at internal infrastructure or 169.254.169.254 and the multi-tenant server fetches it. Affected apps/webapp, HEAD 5d99457 (current main). Root cause - Source (API route): app/presenters/v3/ApiAlertChannelPresenter.server.ts ApiAlertChannelData.url = z.string().optional() (no host validation); route app/routes/api.v1.projects.$projectRef.alertChannels.ts (PAT-auth). - Store: app/v3/services/alerts/createAlertChannel.server.ts…
Recommended action: Upgrade to 4.5.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The run replay action function at apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts has no authentication or authorization check. While the loader (GET) in the same file properly calls requireUser(request) and scopes queries to the user's organizations, the action (POST) at line 166 does neither — allowing any authenticated user to replay task runs from any organization by knowing the run's friendlyId. Details Vulnerable file: apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts The loader (line 28-29) — properly authenticated: The action (line 166-193) — NO authentication: The Prisma query at line 177 fetches the run by friendlyId only — no userId or organization filter. The ReplayTaskRunService then creates a new task run in the victim's environment, executing with the victim's environment variables and secrets. Same bug class exists in: apps/webapp/app/routes/resources.batches.$batchId.check-completion.ts (line 17) — the action has zero authentication,…
Recommended action: Upgrade to 4.5.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
A project member can create a webhook alert channel whose delivery URL points at an internal address, and trigger.dev's control plane will send the alert there with no SSRF protection. The webhook URL is stored as an unvalidated string and is fetched directly from the webapp server, so a low-privilege authenticated user can make the server issue POST requests to internal-only services and cloud metadata endpoints (for example http://169.254.169.254/). No private-IP, scheme, or redirect filtering exists anywhere in the webapp. Details The delivery sink performs a raw fetch to the stored URL, apps/webapp/app/v3/services/alerts/deliverAlert.server.ts:949 (#deliverWebhook): The same pattern is in apps/webapp/app/v3/services/alerts/deliverErrorGroupAlert.server.ts:245. The URL is never validated. The stored shape is a bare string, apps/webapp/app/models/projectAlert.server.ts:6: The public API that creates alert channels accepts it with no constraint,…
Recommended action: Upgrade to 4.5.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The dashboard replay action authorizes the source run (it must belong to the caller's org), but the target environment for the replayed run is taken verbatim from the request body and is never checked for org or project membership. The environment lookup used by the replay path filters by id only. As a result, an authenticated user can replay one of their own runs into another organization's or project's environment, creating a task run there that consumes the victim tenant's queue and compute and pollutes their run history. Details The replay action member-scopes the source run correctly (apps/webapp/app/routes/resources.taskruns.$runParam.replay.ts, the findFirst on taskRun filtered by project.organization.members.some.userId), but passes the target environment straight from the submitted form, resources.taskruns.$runParam.replay.ts:344-346: submission.value.environment comes from ReplayRunData (apps/webapp/app/v3/replayTask.ts: environment: z.string().optional()), so it is…
Recommended action: Upgrade to 4.5.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.