Skip to content

Commit f83eec7

Browse files
committed
fix(webapp,slack): guard webhook composer path writes and fix package checks
Guard the webhook console path builder against prototype-pollution keys (__proto__, constructor, prototype) flagged by static analysis. Route webhook delivery run lookups through the run store instead of the control-plane replica, matching how run tables are read elsewhere. Update @trigger.dev/slack to a type-export checker compatible with the current TypeScript, keep compiled test files out of its build, and format two JSON fixtures.
1 parent 37d5285 commit f83eec7

9 files changed

Lines changed: 98 additions & 306 deletions

File tree

apps/webapp/app/components/webhookConsole/WebhookComposer.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,13 @@ function HeadersEditor({
449449
);
450450
}
451451

452+
const UNSAFE_PATH_KEYS = new Set(["__proto__", "constructor", "prototype"]);
453+
452454
function setPath(target: Record<string, unknown>, path: string, value: unknown) {
453455
const parts = path.split(".");
456+
if (parts.some((part) => UNSAFE_PATH_KEYS.has(part))) {
457+
return;
458+
}
454459
let cursor = target;
455460
for (let i = 0; i < parts.length - 1; i++) {
456461
const key = parts[i];

apps/webapp/app/presenters/v3/WebhookDeliveriesListPresenter.server.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { type ClickHouse } from "@internal/clickhouse";
22
import { type PrismaClientOrTransaction, type WebhookDeliveryStatus } from "@trigger.dev/database";
33
import parseDuration from "parse-duration";
44
import { webhookReplica } from "~/db.server";
5+
import { runStore } from "~/v3/runStore.server";
56
import { webhookDeliveriesRepository } from "~/services/webhookDeliveriesRepository/webhookDeliveriesRepository.server";
67
import {
78
resolveDeliveryRunTargets,
@@ -77,10 +78,11 @@ export class WebhookDeliveriesListPresenter {
7778
// Resolve it, and force empty results when no run matches.
7879
let internalRunId: string | undefined;
7980
if (runId) {
80-
const run = await this.replica.taskRun.findFirst({
81-
where: { friendlyId: runId },
82-
select: { id: true },
83-
});
81+
const run = await runStore.findRun(
82+
{ friendlyId: runId },
83+
{ select: { id: true } },
84+
this.replica
85+
);
8486
internalRunId = run?.id ?? "__none__";
8587
}
8688

apps/webapp/app/presenters/v3/WebhookDeliveryDetailPresenter.server.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
type WebhookDeliveryStatus,
77
} from "@trigger.dev/database";
88
import { webhookReplica } from "~/db.server";
9+
import { runStore } from "~/v3/runStore.server";
910
import { webhookDeliveriesRepository } from "~/services/webhookDeliveriesRepository/webhookDeliveriesRepository.server";
1011

1112
export type WebhookDeliveryDetail = {
@@ -80,10 +81,7 @@ export class WebhookDeliveryDetailPresenter {
8081
let session: { friendlyId: string; externalId: string | null } | null = null;
8182
if (delivery.runId) {
8283
const [taskRun, sessionRun] = await Promise.all([
83-
this.replica.taskRun.findFirst({
84-
where: { id: delivery.runId },
85-
select: { friendlyId: true },
86-
}),
84+
runStore.findRun({ id: delivery.runId }, { select: { friendlyId: true } }, this.replica),
8785
this.replica.sessionRun.findUnique({
8886
where: { runId: delivery.runId },
8987
select: { session: { select: { friendlyId: true, externalId: true } } },

apps/webapp/app/presenters/v3/WebhookDetailPresenter.server.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import parseDuration from "parse-duration";
1010
import { z } from "zod";
1111
import { type Direction } from "~/components/ListPagination";
1212
import { webhookReplica } from "~/db.server";
13+
import { runStore } from "~/v3/runStore.server";
1314
import { findCurrentWorkerFromEnvironment } from "~/v3/models/workerDeployment.server";
1415
import { webhookDeliveriesRepository } from "~/services/webhookDeliveriesRepository/webhookDeliveriesRepository.server";
1516
import {
@@ -89,10 +90,10 @@ export async function resolveDeliveryRunTargets(
8990
if (runIds.length === 0) return { runFriendlyIdById, sessionByRunId };
9091

9192
const [runs, sessionRuns] = await Promise.all([
92-
replica.taskRun.findMany({
93-
where: { id: { in: runIds } },
94-
select: { id: true, friendlyId: true },
95-
}),
93+
runStore.findRuns(
94+
{ where: { id: { in: runIds } }, select: { id: true, friendlyId: true } },
95+
replica
96+
),
9697
replica.sessionRun.findMany({
9798
where: { runId: { in: runIds } },
9899
select: { runId: true, session: { select: { friendlyId: true, externalId: true } } },

internal-packages/webhook-sources/catalog/providers.json

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,10 @@
33
"scope": "ai-agent-first",
44
"updatedAt": null,
55
"definitionOfDone": {
6-
"first-class": [
7-
"registryEntry",
8-
"samples",
9-
"roundTrip",
10-
"producer"
11-
],
12-
"sample-only": [
13-
"registryEntry",
14-
"samples"
15-
]
6+
"first-class": ["registryEntry", "samples", "roundTrip", "producer"],
7+
"sample-only": ["registryEntry", "samples"]
168
},
17-
"statusValues": [
18-
"not-started",
19-
"in-progress",
20-
"complete",
21-
"blocked"
22-
],
9+
"statusValues": ["not-started", "in-progress", "complete", "blocked"],
2310
"providers": [
2411
{
2512
"id": "anthropic",

0 commit comments

Comments
 (0)