Follow-up to #822, which added the layered MCP access policy (etcd kind mcp_policies + the api_keys mcp_access block).
The resources-file source (crates/aisix-core/src/filesource/mod.rs KINDS) does not accept a top-level mcp_policies: collection, while an api_keys entry in the same file happily carries mcp_access (the file source validates keys with the canonical validate_apikey). A standalone operator can therefore write mcp_access: {mode: inherit} on a key with no way to define the policy it inherits from — the key resolves to zero MCP access. Fail-closed, so not a security issue, but a silent dead-end knob.
Options, in order of preference:
- Add
("mcp_policies", IdentityField::…) to KINDS and wire typed parsing like rate_limit_policies (identity: scope_ref for team rows, a fixed env identity for the default row).
- Alternatively, reject
mcp_access in file-mode api_keys with a load error naming it managed-only.
Until then the layered policy is a managed-mode (control-plane) surface only.
Follow-up to #822, which added the layered MCP access policy (etcd kind
mcp_policies+ the api_keysmcp_accessblock).The resources-file source (
crates/aisix-core/src/filesource/mod.rsKINDS) does not accept a top-levelmcp_policies:collection, while anapi_keysentry in the same file happily carriesmcp_access(the file source validates keys with the canonicalvalidate_apikey). A standalone operator can therefore writemcp_access: {mode: inherit}on a key with no way to define the policy it inherits from — the key resolves to zero MCP access. Fail-closed, so not a security issue, but a silent dead-end knob.Options, in order of preference:
("mcp_policies", IdentityField::…)toKINDSand wire typed parsing likerate_limit_policies(identity:scope_reffor team rows, a fixedenvidentity for the default row).mcp_accessin file-mode api_keys with a load error naming it managed-only.Until then the layered policy is a managed-mode (control-plane) surface only.