Summary
obsidian-tc: Declined human-in-the-loop confirmations can permit destructive calls over HTTP
On a Streamable HTTP deployment with auth.jwtSecret configured, serving a 2026-07-28-era client that declared elicitation.form support, a call to a dispatch-gated tool (destructive: true, or a scope with an HITL floor) that was offered an inputRequired confirmation could still complete after the human declined, cancelled, or the elicitation response was omitted or malformed, provided the client echoed the validly bound requestState on resubmission. The server trusted an authentic, call-bound state as proof of approval; the state is minted before the elicitation leg is asked, so it proves only that the resubmission belongs to the same call.
Details
Reproduced directly: a destructive: true tool call, offered inputRequired, answered with {action: "decline"} on the elicitation/create leg, still wrote. Present since the 2026-07-28 round trip shipped in v1.13.0 (THE-583). Only dispatch-gated tools were reachable; the sixteen handler-side conditionally gated tools (write_note overwrite, move_note, and others) did not read the elicitation state on the modern wire at all, so they neither let a decline nor an approval through.
Not addressed
A malicious or non-compliant client can still answer its own elicitation/create leg with an approval regardless of what the human said. The server cannot verify that the client rendered the form or that a human saw it; this is inherent to the client-driven half of the 2026-07-28 protocol. The legacy shim, where the server sends and owns the leg, does not share this gap.
Workarounds
Run affected deployments over stdio, or leave auth.jwtSecret unset so the requestState codec (and therefore inputRequired) is never offered; both fall back to the CLI elicit_token path.
Credit
Reported in GH #967; found and closed under THE-1106 (PR #969); the residual is documented in SECURITY.md.
References
- PR #969, GH #967, CHANGELOG
## [1.31.4] ### Security packages/server/src/mcp/server.ts(tools/callhandler),packages/server/src/vault/hitl.ts
Impact
A client that echoes state after a decline can execute destructive vault operations (delete, cross-folder move, frontmatter replace, link rewrite) that the human explicitly refused. The precondition is a compliant client behaving incorrectly or a client under an attacker's control; the human's refusal is not enforced by the server.
The application does not correctly enforce access controls, allowing a principal to access resources or operations beyond their granted permissions. Typical impact: unauthorized data access or execution of privileged operations.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Already deployed Kodem?
See it in your environmentNew to Kodem? Get a demo →Remediation advice
Fixed in 1.31.4: the server now also requires the confirm leg's own response (inputResponse) to be {action: "accept", content: {approve: true}} before trusting the echoed state. A declined, cancelled or not-approved round renders the ordinary elicit_required error and is never offered a second round for the same declined confirmation. The same release adds server-initiated in-band confirmation on stdio (legacy era), so stdio agents no longer need to mint elicit_token themselves.
Frequently Asked Questions
- What is CVE-2026-115477? CVE-2026-115477 is a high-severity incorrect authorization vulnerability in obsidian-tc (npm), affecting versions >= 1.13.0, <= 1.31.3. It is fixed in 1.31.4. The application does not correctly enforce access controls, allowing a principal to access resources or operations beyond their granted permissions.
- Which versions of obsidian-tc are affected by CVE-2026-115477? obsidian-tc (npm) versions >= 1.13.0, <= 1.31.3 is affected.
- Is there a fix for CVE-2026-115477? Yes. CVE-2026-115477 is fixed in 1.31.4. Upgrade to this version or later.
- Is CVE-2026-115477 exploitable, and should I be worried? Whether CVE-2026-115477 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2026-115477 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2026-115477? Upgrade
obsidian-tcto 1.31.4 or later.