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
CPEX now enforces hook payload mutation policies more strictly. For each hook, HOOK_PAYLOAD_POLICIES defines which top-level payload fields a plugin may change. Example: tool_post_invoke allows only result changes.
This enforcement is a useful guardrail, but it changes how plugin mutations are observed and merged. Plugins that mutate nested payload objects in-place, or that do not correctly handle CPEX copy-on-write isolation wrappers, can appear to make no allowed top-level change. In that case CPEX returns modified_payload=None or drops the effective update, and gateway continues with the original payload.
Concrete Example
PII filter exposed this on tool_post_invoke:
policy allows result
gateway result shape may be nested, e.g. result["content"][0]["text"]
CPEX wraps payload data for isolation when policy is active
PII scanning missed the wrapped mapping shape and returned no modified payload
gateway kept the original tool result, so masked content did not survive policy filtering
PR #89 fixes this for pii_filter by making the Rust scanner process Python mappings through the mapping protocol, and adds a regression test using real CPEX isolation + apply_policy().
Work Needed
Audit every plugin that mutates hook payloads under CPEX policy enforcement.
For each plugin/hook combination:
identify which payload fields the plugin intends to mutate
verify the hook has the expected writable fields in policy
verify nested mutations survive CPEX isolation and apply_policy()
prefer returning a new payload/new top-level field value rather than mutating nested structures in-place
add regression tests that exercise real CPEX policy filtering, not only direct plugin method calls
Hooks To Prioritize
tool_post_invoke, especially plugins rewriting nested result content
tool_pre_invoke, especially plugins rewriting nested args
prompt_post_fetch and resource_post_fetch, where result/content objects are often nested
Acceptance Criteria
all mutation-capable plugins have tests covering CPEX policy/isolation behavior
any plugin relying on in-place nested mutation is updated to return a policy-visible payload change
no plugin silently loses an allowed mutation when explicit hook policy is present
Problem
CPEX now enforces hook payload mutation policies more strictly. For each hook,
HOOK_PAYLOAD_POLICIESdefines which top-level payload fields a plugin may change. Example:tool_post_invokeallows onlyresultchanges.This enforcement is a useful guardrail, but it changes how plugin mutations are observed and merged. Plugins that mutate nested payload objects in-place, or that do not correctly handle CPEX copy-on-write isolation wrappers, can appear to make no allowed top-level change. In that case CPEX returns
modified_payload=Noneor drops the effective update, and gateway continues with the original payload.Concrete Example
PII filter exposed this on
tool_post_invoke:resultresult["content"][0]["text"]PR #89 fixes this for
pii_filterby making the Rust scanner process Python mappings through the mapping protocol, and adds a regression test using real CPEX isolation +apply_policy().Work Needed
Audit every plugin that mutates hook payloads under CPEX policy enforcement.
For each plugin/hook combination:
apply_policy()Hooks To Prioritize
tool_post_invoke, especially plugins rewriting nestedresultcontenttool_pre_invoke, especially plugins rewriting nestedargsprompt_post_fetchandresource_post_fetch, where result/content objects are often nestedAcceptance Criteria