Trigger.dev: Missing Authentication in Run Replay Action Allows Cross-Organization Task Execution (IDOR)
### 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 `use
- Products
- trigger.dev
- Affected versions
- Not specified
- Fixed versions
- 4.5.2
- CVEs
- Not specified
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 31 Oct 2026, 14:09 UTC · Revision 1
Source evidence
Trigger.dev: Missing Authentication in Run Replay Action Allows Cross-Organization Task Execution (IDOR)
core-osv · Original sourcePublished 2 Oct 2026, 22:35 UTC
### 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 `use
osv:GHSA-pp95-gc86-jq6q
trigger.dev
Fixed versions: 4.5.2
Complete source record
{
"id": "61d9c417bd4d26822841a11d95073a36e0e2d4a4d4be1e9a22e62d69a10255aa",
"url": "https://osv.dev/vulnerability/GHSA-pp95-gc86-jq6q",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "Trigger.dev: Missing Authentication in Run Replay Action Allows Cross-Organization Task Execution (IDOR)",
"summary": "### 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 `use",
"evidence": "osv:GHSA-pp95-gc86-jq6q",
"products": [
{
"name": {
"value": "trigger.dev",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "4.5.2",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": []
}
],
"severity": "high",
"structured": {
"id": "GHSA-pp95-gc86-jq6q",
"aliases": [
"GHSA-pp95-gc86-jq6q"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:N"
}
],
"affected": [
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0"
},
{
"fixed": "4.5.2"
}
]
}
],
"package": {
"name": "trigger.dev",
"purl": "pkg:npm/trigger.dev",
"ecosystem": "npm"
},
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-pp95-gc86-jq6q/GHSA-pp95-gc86-jq6q.json",
"last_known_affected_version_range": "<= 4.5.1"
}
}
],
"modified": "2026-10-21T10:58:05.446872453Z",
"provider": "osv",
"references": [
"https://github.com/triggerdotdev/trigger.dev/security/advisories/GHSA-pp95-gc86-jq6q",
"https://github.com/triggerdotdev/trigger.dev/pull/4199",
"https://github.com/triggerdotdev/trigger.dev/commit/34b1a181c2a1d33a53ebab88f84b05f81fea4254",
"https://github.com/triggerdotdev/trigger.dev",
"https://github.com/triggerdotdev/trigger.dev/releases/tag/v4.5.2"
],
"provider_metadata": {
"cwe_ids": [
"CWE-862"
],
"severity": "HIGH",
"github_reviewed": true,
"nvd_published_at": null,
"github_reviewed_at": "2026-10-02T22:35:24Z"
}
},
"related_cves": [],
"security_relevant": true,
"severity_evidence": "/database_specific/severity"
},
"source_id": "core-osv",
"document_id": 392991,
"published_at": "2026-10-02T22:35:24+00:00"
}