Executor version
Executor Cloud (hosted, executor.sh), reproduced 2026-09-18.
Summary
policies.create documents its pattern as "a tool address tail (integration.connection.tool)", but policies are matched against integration.owner.connection.tool by a head-anchored, length-exact matcher. A pattern written in the documented three-segment form is accepted by isValidPattern, stored, and listed as an active policy — and can never match anything.
The result is a silently dead policy. There is no warning at create time, and policies.list shows it as active, so the only way to notice is to observe that the gate never changes behaviour.
For an approve policy this looks like "auto-approval doesn't work". For a block policy this is a security problem: an operator can believe a tool is blocked when every call is still dispatched.
Reproduction
- Pick any connection-backed MCP tool, e.g.
<integration>.<owner>.<connection>.<tool>.
- Create a user policy using the form shown in the
policies.create description — omitting the owner segment:
pattern: "<integration>.<connection>.<tool>"
action: "approve"
policies.list reports it as an active approve policy.
- Call the tool.
Expected
Either the policy matches and the tool auto-approves, or creation is rejected with an explanation that the pattern cannot match any tool address.
Actual
The tool still requires approval on every call. The policy never fires.
Changing the pattern to include the owner segment fixes it immediately:
"<integration>.*.<connection>.<tool>" # works
"<integration>.<connection>.<tool>" # accepted, never matches
Where the mismatch is
packages/core/sdk/src/executor.ts builds the id that policies are matched against with four segments:
const normalizedPolicyId = (tool: Tool): string =>
tool.static
? String(tool.address)
: `${tool.integration}.${tool.owner}.${tool.connection}.${tool.name}`;
packages/core/sdk/src/policies.ts matches from segment 0 and requires equal length for a pattern with no trailing *:
if (i >= toolSegments.length || toolSegments[i] !== seg) return false;
...
return patternSegments.length === toolSegments.length;
So a three-segment pattern fails at index 1, where <connection> is compared against <owner>.
Two pieces of guidance point at the three-segment form:
- the public
policies.create description: "pattern matches a tool address tail (integration.connection.tool)" — it is not a tail match, it is head-anchored
- the comment above
normalizedPolicyId: "Tool policies gate by tool identity (<integration>.<tool>)" — inconsistent with the four-segment id constructed directly beneath it
isValidPattern only checks syntax (no empty segments, no partial wildcards, no leading *), so a structurally unmatchable pattern passes.
Suggested fix
Any one of these would have prevented it, roughly in order of value:
- Validate at create/update time that the pattern can match at least one known tool address, or at minimum that its segment count is compatible, and reject with a message naming the expected form.
- Correct the
policies.create description and the normalizedPolicyId comment to state the real grammar, integration.owner.connection.tool.
- Surface a match count in
policies.list (e.g. matches: 0), so a dead policy is visible without having to test the gate.
(1) and (3) matter most for block policies, where silence is mistaken for enforcement.
Related
Not a duplicate of #1752 (workspace policies bypassed on toolkit-scoped endpoints). This is the inverse: a policy on the base endpoint that is never evaluated because the pattern cannot match.
Executor version
Executor Cloud (hosted, executor.sh), reproduced 2026-09-18.
Summary
policies.createdocuments itspatternas "a tool address tail (integration.connection.tool)", but policies are matched againstintegration.owner.connection.toolby a head-anchored, length-exact matcher. A pattern written in the documented three-segment form is accepted byisValidPattern, stored, and listed as an active policy — and can never match anything.The result is a silently dead policy. There is no warning at create time, and
policies.listshows it as active, so the only way to notice is to observe that the gate never changes behaviour.For an
approvepolicy this looks like "auto-approval doesn't work". For ablockpolicy this is a security problem: an operator can believe a tool is blocked when every call is still dispatched.Reproduction
<integration>.<owner>.<connection>.<tool>.policies.createdescription — omitting the owner segment:policies.listreports it as an activeapprovepolicy.Expected
Either the policy matches and the tool auto-approves, or creation is rejected with an explanation that the pattern cannot match any tool address.
Actual
The tool still requires approval on every call. The policy never fires.
Changing the pattern to include the owner segment fixes it immediately:
Where the mismatch is
packages/core/sdk/src/executor.tsbuilds the id that policies are matched against with four segments:packages/core/sdk/src/policies.tsmatches from segment 0 and requires equal length for a pattern with no trailing*:So a three-segment pattern fails at index 1, where
<connection>is compared against<owner>.Two pieces of guidance point at the three-segment form:
policies.createdescription: "patternmatches a tool address tail (integration.connection.tool)" — it is not a tail match, it is head-anchorednormalizedPolicyId: "Tool policies gate by tool identity (<integration>.<tool>)" — inconsistent with the four-segment id constructed directly beneath itisValidPatternonly checks syntax (no empty segments, no partial wildcards, no leading*), so a structurally unmatchable pattern passes.Suggested fix
Any one of these would have prevented it, roughly in order of value:
policies.createdescription and thenormalizedPolicyIdcomment to state the real grammar,integration.owner.connection.tool.policies.list(e.g.matches: 0), so a dead policy is visible without having to test the gate.(1) and (3) matter most for
blockpolicies, where silence is mistaken for enforcement.Related
Not a duplicate of #1752 (workspace policies bypassed on toolkit-scoped endpoints). This is the inverse: a policy on the base endpoint that is never evaluated because the pattern cannot match.