An explicit denial is discarded by default substitution during policy compilation
An operator sets an authority bearing value explicitly to false or another falsy value meant to deny or disable a capability. A generic templating or defaulting function treats that value as empty rather than as present, and silently substitutes a permissive default before any runtime check ever sees the operator's own instruction.
Description
This weakness sits earlier in the authorization lifecycle than most of this registry's entries. It is not about an agent misusing a capability, an approval failing to bind to what executes, or a claim of authority nobody checks; it is about the configuration compiler that produces the policy those later stages read, itself changing what the operator asked for before anything downstream can evaluate it. Many templating and configuration languages provide a generic default helper that returns its fallback whenever the input is empty, and define empty broadly enough to include false, 0 and an empty string alongside a genuinely unset value. When that helper is applied to a field whose valid values include an explicit false meant to deny or disable something, the helper cannot distinguish an operator who never set the field from an operator who set it exactly to the value that should turn the capability off. Both compile to the same permissive default. Nothing errors, nothing warns, and no diff between requested and rendered configuration is surfaced anywhere an operator would see it, because the substitution happens inside logic nobody treats as part of the authorization boundary. This is distinct from a value simply defaulting to permissive when left unset: an unset value defaulting to an insecure default is a design choice with a name, and an operator can find and override it once they know it exists. Here the operator did override it, explicitly, in the one place they were told to, and the override never reached the system it was meant to configure.
The authority gap
The operator holds authority to deny or disable the capability and exercises it explicitly, in the configuration surface they were told governs it. The compiler holds no delegated authority to override that denial, yet a generic helper's inability to tell an explicit false from an absent value produces exactly that override, silently, before any policy, approval or runtime check downstream ever has the chance to evaluate the operator's actual instruction.
Failure conditions
- An authority bearing configuration field is optional, and one of its valid values, false, 0 or empty, is also the value a generic defaulting or templating function treats as absent.
- The operator sets that field explicitly to the restrictive value, intending to deny or disable the capability it governs.
- A defaulting function determines the effective value by testing whether the input is empty rather than whether the key was present at all, and substitutes its own fallback.
- Downstream code, infrastructure or a runtime agent reads only the already compiled, already inverted value, with no way to distinguish it from a genuine operator opt in to the permissive default.
Consequences shown by the evidence
- A capability the operator explicitly disabled, at whatever cost or risk tolerance they declared by disabling it, runs anyway until the operator separately notices the compiled output does not match what they set.
- Every downstream policy, approval or audit control that trusts the compiled configuration as a faithful record of operator intent inherits the same silent authority widening, since none of them re-derives the operator's original input.
Detection signals
- A chart, template or configuration compiler repeatedly applies a generic default helper to fields whose valid values include false, 0 or empty, rather than a presence check.
- Rendering the same template with a field left unset and with the field explicitly set to its most restrictive value produces identical output.
- A sibling template, module or code path in the same codebase already uses a presence based pattern for a field of the identical name and purpose, showing the correct form was known and simply not applied everywhere.
Known examples
- dhyansraj/mcp-mesh issue #1573, opened by the repository owner on 5 September 2026 and independently corroborated by this record's own direct read of the chart source at commit 4b4cb00f1c1b0e35829a4aa9f77c7c92068d7bc3: the agent and UI Helm charts render MCP_MESH_HTTP_ENABLED, MCP_MESH_ENABLED and three observability enabled flags with a Sprig default true, so operator supplied false values for agent.http.enabled, mesh.enabled and agent.observability.distributedTracing.enabled, tracing.enabled and metrics.enabled all compile to "true". The registry chart's own configmap.yaml uses the correct hasKey and ternary pattern for the identically named MCP_MESH_DISTRIBUTED_TRACING_ENABLED variable, next to a comment naming the exact defect, so the fix already exists once in the same repository without having been carried to the sibling chart using the same variable name for the same purpose. The registry chart's own waitForDatabase flag, documented in values.yaml as the way to disable a wait-for-database init container, is gated the same way in deployment.yaml and cannot in fact be disabled by an operator following that documentation.
Recorded instances
No recorded instance yet. The weakness stands on the records below.
Protocol evidence
Published authority architectures whose artifacts bear on the requirement this weakness names: which satisfy it, which expose a way past it, and which leave it unanswered.
- Supports requirement
Cedulon, an audit layer for agent to agent commerce
E. C. Dogru, individual submission to the IETF
Requirement The policy decision point fails closed
Cedulon's own specification, verified directly, requires that an unreachable, uninitialized or failing policy decision point resolve to deny, precisely so a failure inside the check itself cannot quietly relax the limit it exists to enforce. MCP Mesh's Helm charts show the same underlying question, whether the intended check actually runs, answered the other way at a different stage: no policy decision point failed at runtime here, none was ever wired to see the operator's own explicit denial in the first place, because a generic defaulting helper discarded it during template compilation. This is concrete evidence for why Cedulon's own fail-closed requirement matters as a general design principle for any policy bearing layer, compilation included, and not only for the one draft's own runtime decision point.
