Skip to content
Blog

8 min read

The Trigger.dev leak: rotating secrets without downtime

How to identify potential leaks, rotate environment variables in the right order and look for unauthorised use without unnecessary disruption.

By Written with AI assistance from the source

Dark clouds over a troubled sea horizon
Photo: JOHN TOWNER on Unsplash

What happened

Trigger.dev published a security report on 1 November 2026 stating that an attacker had gained unauthorised access to environment variables belonging to affected organisations. Trigger.dev says that the attack method has been blocked and that affected account owners have received instructions by email.

The report is brief. It does not say which types of variables were read, when access began or whether the exposed information was used. This means you need to distinguish between what has been confirmed and what you need to investigate in your own environment.

An environment variable is a name with an associated value that your code can read without the value being stored directly in the source code. It may be ordinary configuration, such as the region being used, but it may also be a secret such as a database password, API key or signing key.

If an attacker can read a secret environment variable, you should treat the value as compromised. This applies even if you find no evidence of misuse. A copied key can be stored and used later, outside Trigger.dev and without your usual application logs showing the full sequence of events.

At the same time, not receiving an email is not technical confirmation that everything is secure. Check which address is registered for the account owner, the spam folder and the organisation each Trigger.dev project belongs to. Ask Trigger.dev to confirm the affected projects, environments, variable names and possible times without sending the secrets themselves to support.

Determine what may have leaked

Start with an inventory before changing anything. Otherwise, you risk losing track of which values were actually stored in Trigger.dev and where those same values are still used.

Review every Trigger.dev environment, including production, staging, development and active preview environments. Note the variable name, which service issued the value, which systems use it and where the original is managed. Never save the value itself in the incident document.

Pay particular attention to variables that provide access to:

  • databases and connection pools
  • Stripe or other payment services
  • Supabase with backend permissions
  • email providers
  • file and object storage
  • AI services and external APIs
  • webhook signing
  • authentication and token signing
  • Vercel, GitHub and other deployment systems
  • monitoring services that may also contain sensitive logs

Names such as DATABASE_URL, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, SUPABASE_SERVICE_ROLE_KEY, RESEND_API_KEY and SENTRY_AUTH_TOKEN are clear candidates. Custom names such as INTERNAL_API_KEY or ADMIN_TOKEN require you to read the code to understand their permissions.

Not all environment variables are secret. A publishable Stripe key or a Supabase key intended for the client may be present in the browser. Variables with prefixes such as NEXT_PUBLIC_ and VITE_ are often built into the client code and should therefore never be treated as secret.

This does not mean that public keys can be ignored. A public Supabase key, for example, assumes that the database access rules restrict what a standard or anonymous user can do. You should therefore check Row Level Security and the associated policies, but prioritise rotating keys with server permissions.

Check synchronisation as well. Trigger.dev can retrieve environment variables from services such as Vercel. The same secret may therefore exist in several dashboards, local files, CI pipelines and deployed versions. Decide which location is the source of truth before starting the rotation, and pause automatic configuration changes if they could write back an old value.

Rotate without causing downtime

Rotation means creating a new secret, moving all legitimate users to it and then revoking the old one. The order matters. If you revoke it first, dependent functions will stop working. If you wait too long after the change, you leave the attacker's access open.

The normal process is:

  • Create a new key in the service that issues it, without revoking the old one yet.
  • Add the new key to the location that will be the source of truth.
  • Update Trigger.dev and the other systems that use the same credential.
  • Restart, deploy or otherwise reload the processes that need to read the new value.
  • Verify that real requests use the new key.
  • Revoke the old key with the issuer.
  • Check errors, queues, scheduled jobs and external requests after revocation.

For Vercel, a changed environment variable will normally need to be included in a new deployment before it affects the running version. Do not assume that a value shown in the dashboard is already being used in production. Trigger.dev, server processes and external workers may have different rules for when values are loaded. Test each runtime environment instead of assuming that synchronisation has succeeded.

Stripe keys should be handled according to their function. A secret API key may provide broad access, while a restricted key may have permissions for a particular workflow. Preferably, create a separate restricted key for the Trigger.dev jobs and give it only the permissions required by the code. The webhook secret is a different credential from the API key and must be rotated separately if it was stored in Trigger.dev.

For Supabase, distinguish between a publishable client key, a secret backend key, database connection details and keys used to sign tokens. They have different consequences and cannot be changed as if they were the same thing. A backend key can normally be replaced in parallel, while changing older shared signing secrets may affect sessions and several parts of the system at the same time.

Database credentials require extra care. Update both direct connection strings and connections through pools. Check migrations, administration tools, local production scripts and scheduled jobs. Once all legitimate processes are using the new password, you can revoke the old one and terminate old database connections if necessary.

If you see ongoing misuse, do not keep the old key active to avoid downtime. Revoke it immediately, stop high-risk jobs and restore the service in a controlled way. A brief service disruption is then less serious than continued access to payments, customer data or administrative functionality.

Check whether the keys have been used

Rotation prevents future use but does not tell you what has already happened. You therefore need to review logs from both Trigger.dev and the service behind each credential.

In Trigger.dev, look for:

  • runs that you do not recognise
  • unexpected payloads, tags or manual requests
  • jobs run at unusual times
  • changes to projects, environment variables or deployments
  • new access tokens or changed team permissions
  • unusual errors, reruns and external network requests

Logs from the credential issuer are often more important. A stolen database password can be used directly against the database, and a Stripe key directly against the Stripe API, without the traffic passing through Trigger.dev.

For Stripe, you can review API logs and changes to refunds, payments, webhook endpoints and account settings, for example. For Supabase, you can check database, authentication and API logs, as well as changes to users, policies and the schema. For Vercel and GitHub, check activity related to deployments, environment variables, integrations and access tokens.

Do not search only for successful requests. Rejected attempts may show that someone tested the key or tried to understand its permissions. Compare them with known runs from your application and note which sources, times and operations differ.

Preserve the evidence before logs disappear or are overwritten. Export relevant events, but avoid copying secrets, complete personal data or sensitive payloads into an unprotected document. Document what you checked, which decisions you made and when the old key ceased to be valid.

Incident closure checklist

Use the checklist as a shared working document for engineering, product and whoever is responsible for the affected supplier accounts.

  • Confirm whether the organisation or any project is covered by Trigger.dev's notice.
  • Make an inventory of all environments and variable names without copying the values.
  • Mark which variables are public, secret or have administrative permissions.
  • Map where each secret is used and which location is the source of truth.
  • Preserve relevant logs and events before changing the configuration.
  • Rotate privileged keys and database credentials with overlapping validity where it is safe to do so.
  • Update Trigger.dev, Vercel, local environments and other consumers.
  • Deploy or restart processes that would otherwise retain old values.
  • Verify critical flows such as payments, sign-in, email and background jobs.
  • Revoke old credentials and check that they are no longer accepted.
  • Review supplier logs for unauthorised or anomalous requests.
  • Restrict broadly privileged keys and separate credentials between services and environments.
  • Document the incident and make the rotation process repeatable for the next incident.

Once the product is working again, you should also reduce the impact of future leaks. Use separate keys for each environment and component, choose restricted permissions, avoid shared administrator keys and make sure someone can carry out a rotation without first searching the entire codebase.

If you want to prioritise security work based on what affects revenue, you can start with the flow for paying customers.


Source: Trigger.dev blog

Want to know what your build would take?

Three questions, then you get a clickable sketch for free.

← All articles