GHSA-737x-cwfr-5vvc: Npm/obsidian-tc vulnerability

Published Oct 23, 2026
·
Updated

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 (writenote overwrite, movenote, 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 elicitrequired 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 elicittoken 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 elicittoken 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

Affected Software

1 affected componentFixes available
npm/obsidian-tc>=1.13.0<=1.31.3
1.31.4

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/obsidian-tc to a version that resolves this vulnerability.

    Fixed in 1.31.4
  2. Upgrade

    Upgrade to a fixed release to a version that resolves this vulnerability.

    Fixed in 1.31.4
  3. Configuration

    Leave auth.jwtSecret unset so requestState and inputRequired are not offered.

    auth jwtSecret = unset
  4. Compensating control

    Run affected deployments over stdio so they fall back to the CLI elicit_token path.

Event History

Oct 23, 2026
Advisory Published
via GitHub·05:30 PM
Data Sourced
via GitHub·05:30 PM
DescriptionWeaknessAffected Software

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203