Every CVE Search/ Get API key

CVE-2026-115477

obsidian-tc: Declined human-in-the-loop confirmations can permit destructive calls over HTTP

7.1 HighFix available

obsidian-tc is a governed, agent-ready Model Context Protocol server for Obsidian vaults. From 1.13.0 until 1.31.4, on a Streamable HTTP deployment with auth.jwtSecret configured and a 2026-07-28-era client declaring elicitation.form support, a dispatch-gated tool call offered an inputRequired confirmation could still complete after the human declined or 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 even though that state was minted before the elicitation/create leg was asked and proved only that the resubmission belonged to the same call. A client behaving incorrectly or under an attacker's control could therefore execute dispatch-gated destructive vault operations without the human's approval, while still requiring the caller's ordinary tool permissions. Only tools marked destructive: true or requiring a scope with a human-in-the-loop floor were reachable through this bypass. The sixteen handler-side conditionally gated tools, including write_note overwrite and move_note, did not read elicitation state on the modern wire and let neither approval nor decline through that path. Affected deployments using stdio or leaving auth.jwtSecret unset instead used the CLI elicit_token fallback and did not offer this requestState round trip. The fix does not prevent a malicious client from reporting a fabricated approval, because the server cannot verify that the client displayed the form or that a human saw it. This issue is fixed in version 1.31.4.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
High
Availability
Low

Exploit likelihood

0.35%Down 0.1 points since Oct 24, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.1

obsidian-tc: Declined human-in-the-loop confirmations can permit destructive calls over HTTP

obsidian-tc is a governed, agent-ready Model Context Protocol server for Obsidian vaults. From 1.13.0 until 1.31.4, on a Streamable HTTP deployment with auth.jwtSecret configured and a 2026-07-28-era client declaring elicitation.form support, a dispatch-gated tool call offered an inputRequired confirmation could still complete after the human declined or 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 even though that state was minted before the elicitation/create leg was asked and proved only that the resubmission belonged to the same call. A client behaving incorrectly or under an attacker's control could therefore execute dispatch-gated destructive vault operations without the human's approval, while still requiring the caller's ordinary tool permissions. Only tools marked destructive: true or requiring a scope with a human-in-the-loop floor were reachable through this bypass. The sixteen handler-side conditionally gated tools, including write_note overwrite and move_note, did not read elicitation state on the modern wire and let neither approval nor decline through that path. Affected deployments using stdio or leaving auth.jwtSecret unset instead used the CLI elicit_token fallback and did not offer this requestState round trip. The fix does not prevent a malicious client from reporting a fabricated approval, because the server cannot verify that the client displayed the form or that a human saw it. This issue is fixed in version 1.31.4.

Record
CVE-2026-115477
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N
Weakness
CWE-285, CWE-863
Updated
2026-11-02
EUVDEUVD-2026-109082 7.1

obsidian-tc is a governed, agent-ready Model Context Protocol server for Obsidian vaults. From 1.13.0 until 1.31.4, on a Streamable HTTP deployment with auth.jwtSecret configured and a 2026-07-28-era client declaring elicitation.form support, a dispatch-gated tool call offered an inputRequired confirmation could still complete after the human declined or 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 even though that state was minted before the elicitation/create leg was asked and proved only that the resubmission belonged to the same call. A client behaving incorrectly or under an attacker's control could therefore execute dispatch-gated destructive vault operations without the human's approval, while still requiring the caller's ordinary tool permissions. Only tools marked destructive: true or requiring a scope with a human-in-the-loop floor were reachable through this bypass. The sixteen handler-side conditionally gated tools, including write_note overwrite and move_note, did not read elicitation state on the modern wire and let neither approval nor decline through that path. Affected deployments using stdio or leaving auth.jwtSecret unset instead used the CLI elicit_token fallback and did not offer this requestState round trip. The fix does not prevent a malicious client from reporting a fabricated approval, because the server cannot verify that the client displayed the form or that a human saw it. This issue is fixed in version 1.31.4.

Record
EUVD-2026-109082
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-737x-cwfr-5vvc 7.1

obsidian-tc: Declined human-in-the-loop confirmations can permit destructive calls over HTTP

Summary

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.

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.

Patches

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.

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/call handler), packages/server/src/vault/hitl.ts
Record
GHSA-737x-cwfr-5vvc
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N
Weakness
CWE-285, CWE-863
Updated
2026-11-02
NVD 7.1

obsidian-tc is a governed, agent-ready Model Context Protocol server for Obsidian vaults. From 1.13.0 until 1.31.4, on a Streamable HTTP deployment with auth.jwtSecret configured and a 2026-07-28-era client declaring elicitation.form support, a dispatch-gated tool call offered an inputRequired confirmation could still complete after the human declined or 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 even though that state was minted before the elicitation/create leg was asked and proved only that the resubmission belonged to the same call. A client behaving incorrectly or under an attacker's control could therefore execute dispatch-gated destructive vault operations without the human's approval, while still requiring the caller's ordinary tool permissions. Only tools marked destructive: true or requiring a scope with a human-in-the-loop floor were reachable through this bypass. The sixteen handler-side conditionally gated tools, including write_note overwrite and move_note, did not read elicitation state on the modern wire and let neither approval nor decline through that path. Affected deployments using stdio or leaving auth.jwtSecret unset instead used the CLI elicit_token fallback and did not offer this requestState round trip. The fix does not prevent a malicious client from reporting a fabricated approval, because the server cannot verify that the client displayed the form or that a human saw it. This issue is fixed in version 1.31.4.

Record
CVE-2026-115477
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Weakness
CWE-285, CWE-863
Updated
2026-11-02
OSV 7.1

obsidian-tc: Declined human-in-the-loop confirmations can permit destructive calls over HTTP

obsidian-tc is a governed, agent-ready Model Context Protocol server for Obsidian vaults. From 1.13.0 until 1.31.4, on a Streamable HTTP deployment with auth.jwtSecret configured and a 2026-07-28-era client declaring elicitation.form support, a dispatch-gated tool call offered an inputRequired confirmation could still complete after the human declined or 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 even though that state was minted before the elicitation/create leg was asked and proved only that the resubmission belonged to the same call. A client behaving incorrectly or under an attacker's control could therefore execute dispatch-gated destructive vault operations without the human's approval, while still requiring the caller's ordinary tool permissions. Only tools marked destructive: true or requiring a scope with a human-in-the-loop floor were reachable through this bypass. The sixteen handler-side conditionally gated tools, including write_note overwrite and move_note, did not read elicitation state on the modern wire and let neither approval nor decline through that path. Affected deployments using stdio or leaving auth.jwtSecret unset instead used the CLI elicit_token fallback and did not offer this requestState round trip. The fix does not prevent a malicious client from reporting a fabricated approval, because the server cannot verify that the client displayed the form or that a human saw it. This issue is fixed in version 1.31.4.

Record
CVE-2026-115477
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N
Weakness
CWE-285, CWE-863
Updated
2026-11-02
OSVGHSA-737x-cwfr-5vvc 7.1

obsidian-tc: Declined human-in-the-loop confirmations can permit destructive calls over HTTP

Summary

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.

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.

Patches

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.

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/call handler), packages/server/src/vault/hitl.ts
Record
GHSA-737x-cwfr-5vvc
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N
Weakness
CWE-285, CWE-863
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
obsidian-tc
npm
1.13.0 to 1.31.3
1.31.4
obsidian-tc
npm
1.13.0 up to 1.31.4
1.31.4

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-115477 is a high vulnerability (CVSS 7.1) in The-40-thieves Obsidian-tc, published October 23, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.35%, the 29th percentile. Fixed in obsidian-tc 1.31.4.

References

Show 5 moreShow less
MoveEnter Open