github YawLabs/tailscale-mcp v0.22.0

2 hours ago

Changed

  • TAILSCALE_MCP_SANDBOX=1 grants the network as api.tailscale.com:443 instead of the bare host. oam 0.18.0, the floor, is the first release whose fetch honours a port-scoped --allow-net entry, and every request this server makes is HTTPS, so nothing it does changes; an http:// URL or a redirect to another port on that host is now refused as well.
  • TAILSCALE_MCP_RUNTIME=oam names the remedy for what it found when no usable oam turns up: oam self-update for an oam older than the floor, a check of the binary for one that would not run or report a version, a fix for an OAM_BIN that does not exist, and installing oam only when none was found at all. It used to say "Install or update from https://oamjs.org" in every case, and on linux-arm64, which oam publishes no build for, it now says so instead of sending you to a download that does not exist.
  • The launcher searches OAM_INSTALL_DIR first when that is set. It is where oam's installer and oam self-update put the binary, so an oam installed to a custom directory and left off PATH used to go unfound.
  • An API request that runs into fetch's own connect, response-header or body timeout is now reported as <METHOD> request timed out while connecting / waiting for the response headers / reading the response body, read from the error's cause.code (UND_ERR_CONNECT_TIMEOUT and the rest), instead of as a generic request failed: fetch failed (...).
  • npm run build:binary:oam verifies a cross-build carrier against the oam release's signed RELEASE-MANIFEST -- ssh-keygen -Y verify against oam's release keys, vendored in scripts/oam-release-keys/ -- and takes the checksum from the manifest instead of from the unsigned SHA256SUMS beside the binary. It fails closed: no ssh-keygen able to verify, a missing manifest, a bad signature or a tag outside the key's range aborts the build. An OAM_VERSION older than v0.18.0, released before oam signed its releases, has no manifest: its SHA256SUMS is used only when it hashes to the digest pinned for that tag in the vendored presigning-sums, as oam's installers do, and a pre-signing tag not pinned there is refused. A checksum file that lists an asset twice is refused too. Build tooling only.
  • release.sh checks the oam floor before releasing: scripts/check-oam-floor.mjs (also npm run check:oam-floor) fails when the README, the launcher or its tests quote a floor other than OAM_MIN, and when a newer oam has been published (TAILSCALE_MCP_ALLOW_STALE_OAM=1 releases on the old floor deliberately; no network is not a failure). The drift half runs in the test suite too. Ported from aws-mcp. Release tooling only.

Fixed

  • Under TAILSCALE_MCP_SANDBOX=1 the tailscale CLI child now gets the environment a Windows program needs to start. The CLI is spawned without an env option, so it inherits the server's environment, which under the sandbox's --allow-env list holds only the granted variables -- and oam 0.18.0 takes even the variables libuv adds to every Windows child (SYSTEMROOT, TEMP, USERPROFILE, ...) from that filtered environment. Measured on oam 0.18.0 on Windows: the child saw COMSPEC, NODE_OPTIONS, PATH, PATHEXT, PROCESSOR_ARCHITECTURE, PROMPT and TAILSCALE_API_KEY, and no SYSTEMROOT, without which a program cannot start Winsock. The grant now adds APPDATA, HOME, HOMEDRIVE, HOMEPATH, LOCALAPPDATA, SYSTEMDRIVE, SYSTEMROOT, TEMP, TMP, USERPROFILE and WINDIR for the child. On Windows each of these is also granted in the spelling the environment actually uses: oam matches a grant exactly, case included, and an MCP client started from Explorer passes on Path, SystemRoot, SystemDrive and windir -- measured on oam 0.18.0, a grant spelt PATH,SYSTEMROOT,... alone let neither through, to the server or the child (a Git Bash shell upper-cases them, which hides this). The grant also adds WSL_DISTRO_NAME, which the server reads to recognise WSL when the CLI is missing (its fallback, reading /proc/version, is denied by the sandbox). tailscale_local_status answered under the sandbox both before and after on the Windows box this was measured on (Tailscale 1.102.4, which reaches tailscaled over a named pipe), so what this fixes is the environment, not a failure observed in that one tool. A new test, src/oam-sandbox.integration.test.ts, runs the launcher's real grant on a real oam 0.18.0 or newer when one is found (it skips otherwise) and asserts what a child receives; it fails against the old grant.
  • A Node handoff from an oam host strips --permission and --allow-* from the NODE_OPTIONS it passes on. oam hands its permission flags to children through that variable, and Node refuses --allow-net and --allow-env there with exit 9, so a server handed to Node by an oam that carried them in its own NODE_OPTIONS died before running. Flags oam was given on its own command line are appended at the spawn by oam itself and cannot be removed this way; the README now says that under the sandbox TAILSCALE_BINARY must be the native CLI, not a Node-based wrapper, for the same reason.

Security

  • The bundled MCP SDK moves from 1.30.0 to 1.32.1 (GHSA-6qxp-vccf-f47h, high: the SDK's OAuth client could send credentials to an authorization server chosen by the MCP server). build.mjs bundles the SDK into dist/index.js, so this ships in the package, and the dependency floor is now ^1.32.1. Its fast-uri, also bundled through ajv, moves from 3.1.7 to 3.1.8 (GHSA-hrr3-gc8f-f4qj). Development-scope only, since the bundle never imports express: proxy-addr 2.0.8 (GHSA-jqcg-44mw-7w3h) and ip-address 10.7.3 (GHSA-j6r3-76f7-8jcv, GHSA-h3mg-xc3c-68pw). The overrides floors for fast-uri and ip-address move to the patched versions, ^3.1.8 and ^10.7.3. npm audit reports 0 vulnerabilities.

Don't miss a new tailscale-mcp release

NewReleases is sending notifications on new releases.