Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
* nothing. The obvious fix (write the discarded event as a `dead` row) is
* *actively unsafe on its own*: `redeliver()` reset ANY terminal row to
* `pending` with no signature check, behind `POST /api/v1/webhooks/redeliver`
* which any authenticated user can reach. A parked row has no signature —
* (admitted to a caller with edit access to `sys_webhook`, as decided by
* `packages/plugins/plugin-webhooks/src/redeliver-entitlement.ts`). A parked
* row has no signature —
* the signature is computed at enqueue from the very secret that could not be
* resolved — so redelivering one would put the payload on the wire UNSIGNED,
* reopening #7799 through a door nobody would think to audit.
Expand Down
6 changes: 4 additions & 2 deletions packages/services/service-messaging/src/http-outbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -487,8 +487,10 @@ export class HttpRedeliverError extends Error {
* ## Why this is a security refusal and not a tidiness one
* A parked row has no {@link HttpDelivery.signature}, because the signature is
* computed at enqueue from the very secret that could not be resolved (#7722,
* #7799). `POST /api/v1/webhooks/redeliver` is reachable by any authenticated
* user. Without this refusal, making the drop durable would hand that user a
* #7799). `POST /api/v1/webhooks/redeliver` admits a caller with edit
* (`update`) access to `sys_webhook`, as decided by
* `packages/plugins/plugin-webhooks/src/redeliver-entitlement.ts`. Without this
* refusal, making the drop durable would hand any such webhook administrator a
* button that delivers the webhook UNSIGNED — reopening #7799 through a door
* nobody would think to audit. **An unsigned redelivery is strictly worse than
* an unrecorded drop**, which is why this guard lands with — and logically
Expand Down
6 changes: 4 additions & 2 deletions packages/services/service-messaging/src/messaging-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,10 @@ export class MessagingService {
*
* [#10740] `options.tenantId` is the REQUESTING caller's organization, and
* it is the whole reason this method takes a second argument: the door in
* front of it (`POST /api/v1/webhooks/redeliver`) is open to any
* authenticated user, and `sys_http_delivery` is tenant-scoped. The
* front of it (`POST /api/v1/webhooks/redeliver`) admits any caller with
* edit (`update`) access to `sys_webhook`, as decided by
* `packages/plugins/plugin-webhooks/src/redeliver-entitlement.ts` — a caller
* in any organization — and `sys_http_delivery` is tenant-scoped. The
* outbox applies it to the rows it reads and the row it writes, so a
* caller can only replay deliveries in its own organization; a row
* elsewhere is `RESOURCE_NOT_FOUND`. ⛔ There is no tenant-audit bypass
Expand Down
Loading