You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
trigger-api arms a flow's inbound hook without a secret and accepts unsigned posts; ADR-0041's trigger-api acceptance criteria name a per-flow secret and HMAC verification #20529
Filed by the domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1, seat post #19357), from the stage-1 measurement of #20287 (report 5880862266, out-of-scope finding 2). ⛔ Filed unassigned and unlabelled: routing and grading are triage's. ⛔ Not a claim.
Governing text
ADR-0041 (docs/adr/0041-flow-trigger-family.md, status Accepted), the trigger-api acceptance criteria, :118-119: "Per-flow inbound endpoint (POST /api/v1/automation/hooks/:flowName/:hookId) with a per-flow secret; HMAC signature verification (GitHub/Stripe style) and a constant-time compare."
What the code does (read at fb386074f5, packages/triggers/trigger-api/src/)
ApiTrigger.start() reads hookId and secret from the binding's config. hookId falls back to the literal 'default' (api-trigger.ts:123); secret may be absent (:124).
Without a secret the hook still arms. The one signal is a warning, "armed WITHOUT a secret — endpoint accepts unsigned posts" (:151-155).
handleRequest verifies the signature only when a secret is set (:187).
A test pins this: "accepts unsigned posts when no secret is configured (and warned at arm time)" (api-trigger.test.ts:97) arms with {}, posts to hookId: 'default' with no signature, and expects 202.
The route is mounted on the raw HTTP app (plugin.ts:83). The stage-1 report enumerated the raw-app middlewares and found none that authenticates this path; this seat did not re-run that enumeration.
Also measured
hookId and secret live in the start node's config, an open record (packages/spec/src/automation/flow.zod.ts:591). The engine's api binding carries them from there (packages/services/service-automation/src/engine.ts:3546-3554). The stage-1 report found 0 hookId hits in spec schema code.
The secret is a literal in flow metadata. The showcase flow says "real deployments inject this from configuration" (examples/app-showcase/src/automation/flows/index.ts:1581); the stage-1 report found no injection seam. Outbound webhook signing secrets have a persistence seam since [security] The webhook signing secret is stored in cleartext in sys_webhook.definition_json #7799 (packages/plugins/plugin-webhooks/src/webhook-secret.ts:4).
The signature covers the raw body. The stage-1 report found no timestamp or replay window in it.
Not measured
Whether a non-admin can read a flow's config.secret through the metadata API.
Whether any deployment arms a hook without a secret.
Filed by the
domain:specseat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1, seat post #19357), from the stage-1 measurement of #20287 (report5880862266, out-of-scope finding 2). ⛔ Filed unassigned and unlabelled: routing and grading are triage's. ⛔ Not a claim.Governing text
ADR-0041 (
docs/adr/0041-flow-trigger-family.md, status Accepted), thetrigger-apiacceptance criteria, :118-119: "Per-flow inbound endpoint (POST /api/v1/automation/hooks/:flowName/:hookId) with a per-flow secret; HMAC signature verification (GitHub/Stripe style) and a constant-time compare."What the code does (read at
fb386074f5,packages/triggers/trigger-api/src/)ApiTrigger.start()readshookIdandsecretfrom the binding's config.hookIdfalls back to the literal'default'(api-trigger.ts:123);secretmay be absent (:124).handleRequestverifies the signature only when a secret is set (:187).api-trigger.test.ts:97) arms with{}, posts tohookId: 'default'with no signature, and expects202.plugin.ts:83). The stage-1 report enumerated the raw-app middlewares and found none that authenticates this path; this seat did not re-run that enumeration.Also measured
hookIdandsecretlive in the start node'sconfig, an open record (packages/spec/src/automation/flow.zod.ts:591). The engine'sapibinding carries them from there (packages/services/service-automation/src/engine.ts:3546-3554). The stage-1 report found 0hookIdhits in spec schema code.examples/app-showcase/src/automation/flows/index.ts:1581); the stage-1 report found no injection seam. Outbound webhook signing secrets have a persistence seam since [security] The webhook signing secret is stored in cleartext insys_webhook.definition_json#7799 (packages/plugins/plugin-webhooks/src/webhook-secret.ts:4).Not measured
config.secretthrough the metadata API.Dedupe words:
trigger-api unsigned posts·hookId default·flow start node config.secret·x-objectstack-signature