You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Three HIGH findings from the audit. Each was reproduced before fixing and
each is pinned by a regression test that fails against the old code.
daemon: the daemon held TWO independent activeTunnel handles -- one in
server.js (filled by POST /daemon/enable-tunnel) and one in launcher.js
(filled by the boot auto-start) -- and neither closure could see the other.
disable-tunnel was a silent no-op on a boot-started tunnel: it skipped
stop(), nulled the lockfile tunnelUrl and returned ok while cloudflared
kept serving the public hostname. The 401-burst tripwire delegated to the
launcher callback and so could never stop a dashboard-enabled tunnel. And
enable-tunnel's stop-the-existing guard was equally blind, orphaning a
second cloudflared. getHealth() reads the server closure, so /daemon/health
and manage_daemon status corroborated the false state. /mcp still required
the 256-bit timing-safe bearer, so this is failed revocation rather than
open access -- but with /mcp?token= secret URLs the URL is the credential.
startDaemonServer now exposes adoptTunnel()/getActiveTunnel(), the launcher
hands its handle over, and the tripwire stops that single handle directly.
Also consumes the boot tunnel's waitUntilReady rejection. It is created
eagerly in tunnel.js and rejected when cloudflared exits before publishing
a URL; nothing consumed it and there is no unhandledRejection handler, so
Node's default throw killed the daemon ~1s after it began serving.
index.js: download_formula_field and download_base_formulas were annotated
readOnlyHint:true while writing files at a caller-supplied path.
readOnlyHint is the signal MCP clients use to auto-approve without
prompting, so the annotation removed the consent step from a filesystem
write. Now readOnlyHint:false, destructiveHint:true. Separately, the
filename sanitiser stripped separators but not '.', so a table named '..'
wrote every file one directory above outputDir -- table names come from the
base and are attacker influenced. Both segments now go through
confineToDir(). fieldName is newline-stripped in the # AT: header, which
description already was.
lsp-config.ts: unconfigureMcpToml/unconfigureHelix truncated the user's
config from our marker to EOF instead of removing our block. Both
configureMcpToml and `codex mcp add` append at EOF, so a second MCP server
added after Setup sat below ours and was destroyed by Unconfigure -- no
confirmation, no backup, no error. Measured on the old code, a config.toml
with one extra server was reduced to a single newline. Now removes only
our own sections; HELIX_BLOCK is four tables, not one, and the header
matcher will not mistake a multi-line array continuation for a header.
Verified: 1442 mcp-server + 421 extension + 88 webview tests pass,
check:tool-sync green, pnpm build succeeds.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0 commit comments