The vulnerability lies in the improper handling of session keys generated from templates in hook mappings. The system failed to treat these templated keys as user-influenced input, allowing a bypass of the hooks.allowRequestSessionKey security setting.
The analysis of the patch 5275d008ed33203dba3f98e969ad683a65c416c3 reveals the following:
-
Root Cause: The resolveHookSessionKey function in src/gateway/hooks.ts only checked the allowRequestSessionKey policy for session keys explicitly coming from a request (source: "request"). It did not apply this check to session keys from mappings (source: "mapping"), even if those mappings used templates that rendered user-provided data.
-
The Fix: The patch introduces a more granular classification for session key origins: mapping-static and mapping-templated.
- The
buildActionFromMapping function in src/gateway/hooks-mapping.ts was modified to inspect the sessionKey for template expressions ({{...}}) and tag it with the appropriate source.
- The
resolveHookSessionKey function was then updated to enforce the allowRequestSessionKey policy for both request and mapping-templated sources.
- The main request handler,
createHooksRequestHandler in src/gateway/server-http.ts, was updated to pass this new, more precise source information when calling resolveHookSessionKey.
-
Vulnerable Functions:
resolveHookSessionKey is the primary vulnerable function as it contained the flawed security logic.
createHooksRequestHandler is the entry point for a malicious request and would appear in any runtime trace of an exploit.
buildActionFromMapping and applyHookMappings are also implicated as they are responsible for processing the templates and creating the hook action with the attacker-controlled session key, which was then improperly validated.
An attacker could exploit this by sending a request to a webhook endpoint that uses a mapping with a templated sessionKey (e.g., sessionKey: "hook:{{payload.id}}"). By controlling the payload.id, they could control the session key, bypassing the intended routing isolation, even when hooks.allowRequestSessionKey was set to false.