Skip to content

fix(hooks): validate internal event trigger configuration on save (24.05) - #7867

Open
ar2rsawseen wants to merge 1 commit into
release.24.05from
backport/hooks-validate-trigger-config-2405
Open

fix(hooks): validate internal event trigger configuration on save (24.05)#7867
ar2rsawseen wants to merge 1 commit into
release.24.05from
backport/hooks-validate-trigger-config-2405

Conversation

@ar2rsawseen

Copy link
Copy Markdown
Member

Backport of #7866 to release.24.05.

What changes

/i/hook/save validated the hook's apps but never its trigger configuration. The event type was not checked at all, so any string was accepted and stored, and the events that name a target object matched on that id alone at delivery time, with nothing tying the target to the hook's own apps.

Validation is added on both create and update:

  • the event type must be one of the registered internal events
  • /hooks/trigger must name a source hook whose apps are within this hook's apps. A subset rather than merely overlapping, because the delivered payload includes the source hook's whole document
  • /cohort/enter and /cohort/exit must name a cohort belonging to one of the hook's apps
  • /alerts/trigger, when it names an alert, must name one belonging to one of the hook's apps. Not required to name one, since the field is optional today

Update validates the effective hook, payload merged over stored, so changing only the trigger or only the apps is still checked, and retargeting an existing chain at another app's hook is rejected.

hooks and alerts are core collections, so an unresolvable target is rejected. Cohorts belong to an enterprise plugin whose collection may be absent, so an unresolvable cohort is allowed through and left to the delivery-time check rather than blocking a feature that cannot be verified here.

Not exempt for global admins, matching the delivery-side check. Exempting save would let a global admin store a hook that can never fire, which is the failure mode this removes.

Adapted for this branch

Two differences from master, both real rather than cosmetic:

  • the save handler and its findOne callback are callback-style here rather than async, so both were made async to host the validation. Master's handler is already async, so this brings the two in line rather than introducing a new pattern.
  • hooks tests live in a single plugins/hooks/tests.js, so the new describe block is appended there instead of added as a separate file.

Tests

Through the real save endpoint: unknown event type rejected, cross-app chain rejected, chain with no source rejected, same-app chain allowed, an event carrying no target id allowed, and retargeting an existing chain at another app's hook rejected on update.

🤖 Generated with Claude Code

/i/hook/save validated the hook's apps but never its trigger configuration. The
event type was not checked at all, so any string was accepted and stored, and the
events that name a target object matched on that id alone at delivery time with
nothing tying the target to the hook's own apps.

Adds validation on both create and update:

- the event type must be one of the registered internal events
- /hooks/trigger must name a source hook whose apps are within this hook's apps.
  Required to be a subset rather than merely overlapping, because the delivered
  payload includes the source hook's whole document
- /cohort/enter and /cohort/exit must name a cohort belonging to one of the hook's
  apps
- /alerts/trigger, when it names an alert, must name one belonging to one of the
  hook's apps. Not required to name one, since the field is optional today

Update validates the effective hook, payload merged over stored, so changing only
the trigger or only the apps is still checked, and retargeting an existing chain at
another app's hook is rejected.

hooks and alerts are core collections, so an unresolvable target is rejected.
Cohorts belong to an enterprise plugin and the collection may be absent, so an
unresolvable cohort is allowed through and left to the delivery-time check rather
than blocking a working feature in a deployment where it cannot be verified.

Deliberately not exempt for global admins. The delivery-side check is not exempt
either, so exempting save would let a global admin store a hook that can never
fire, which is the failure mode this removes: previously such a hook was accepted
and then silently did nothing.

Tests go through the real save endpoint and assert the rejections and the
allowed cases, including the retarget-on-update path.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 29, 2026 23:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants