---
id: GHSA-pp95-gc86-jq6q
title: >-
  Trigger.dev: Missing Authentication in Run Replay Action Allows
  Cross-Organization Task Execution (IDOR)
summary: >-
  Trigger.dev: Missing Authentication in Run Replay Action Allows
  Cross-Organization Task Execution (IDOR)
severity: high
cvss: 7.1
cwe:
  - CWE-862
vendor: trigger.dev
product: trigger.dev
ecosystem: npm
affected:
  - trigger.dev <= 4.5.1
patched:
  - trigger.dev 4.5.2
published: '2026-10-02'
updated: '2026-10-02'
sourceUpdated: '2026-10-02T22:35:26Z'
source: GHSA
sourceUrl: 'https://github.com/advisories/GHSA-pp95-gc86-jq6q'
references:
  - url: >-
      https://github.com/triggerdotdev/trigger.dev/security/advisories/GHSA-pp95-gc86-jq6q
  - url: 'https://github.com/triggerdotdev/trigger.dev/pull/4199'
  - url: >-
      https://github.com/triggerdotdev/trigger.dev/commit/34b1a181c2a1d33a53ebab88f84b05f81fea4254
  - url: 'https://github.com/triggerdotdev/trigger.dev/releases/tag/v4.5.2'
  - url: 'https://github.com/advisories/GHSA-pp95-gc86-jq6q'
tags:
  - ghsa
  - npm
ingestedAt: '2026-10-02T23:34:57.407Z'
---

## Overview

### Summary

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:**
```typescript
export async function loader({ request, params }: LoaderFunctionArgs) {
  const user = await requireUser(request);  // ✓ Auth check
  const userId = user.id;
  // ... queries scoped to user's orgs
}
```

**The `action` (line 166-193) — NO authentication:**
```typescript
export const action: ActionFunction = async ({ request, params }) => {
  const { runParam } = ParamSchema.parse(params);
  // ✗ NO requireUser() call
  // ✗ NO requireUserId() call
  // ✗ NO org membership check

  const taskRun = await prisma.taskRun.findFirst({
    where: {
      friendlyId: runParam,  // Queries ANY run, no org scoping
    },
    include: {
      runtimeEnvironment: { select: { slug: true } },
      project: { include: { organization: true } },
    },
  });

  // ... proceeds to replay the run in the victim's environment
  const replayRunService = new ReplayTaskRunService();
```

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, allowing any user to trigger batch completion for any batch ID.

### PoC

**Run replay IDOR:**
```bash
# Any authenticated user can replay any org's task run
POST /resources/taskruns/run_abc123def/replay
Cookie: <any-valid-session>
Content-Type: application/x-www-form-urlencoded

environmentId=<victim-env-id>&failedRedirect=/
```

The `friendlyId` values (e.g., `run_abc123def`) are short, incrementing strings that can be enumerated.

**Batch completion (same bug class):**
```bash
# Any authenticated user can trigger batch completion for any batch
POST /resources/batches/<batchId>/check-completion
Cookie: <any-valid-session>
Content-Type: application/x-www-form-urlencoded

redirectUrl=/
```

### Impact

- **Cross-organization task execution:** An attacker can replay task runs belonging to other organizations, executing tasks in the victim's environment with the victim's secrets and API keys
- **Secret exposure:** Replayed tasks run with the victim organization's environment variables, which may contain database credentials, API keys, and other secrets
- **Resource consumption:** Attacker consumes the victim's compute quota by replaying their tasks
- **Data integrity:** The batch completion endpoint can prematurely resume parent tasks waiting for batch results, causing data integrity issues
- **Low attack complexity:** `friendlyId` values are short, predictable strings — enumeration is feasible

## Affected packages

- `trigger.dev <= 4.5.1`

## Remediation

Upgrade to a patched release:

- `trigger.dev 4.5.2`
