TSLink is designed around explicit capability boundaries. The machine-readable product SSOT is internal/security/capabilities.v1.json; public docs and help text must stay within that manifest.
- No public internet exposure by default — services are private to your Tailscale network unless proxy-only Funnel exposure is explicitly acknowledged
- Explicit public exposure guardrail — Tailscale Funnel is proxy-only and requires an explicit
--public/public_ack:trueacknowledgement - Tailnet transport encryption — traffic between Tailscale devices uses WireGuard; public Funnel paths follow Tailscale Funnel semantics
- HTTP identity verification for proxy/file requests — Tailscale WhoIs authenticates TSLink-managed HTTP requests before identity headers are injected; raw TCP streams and public Funnel exposure are not treated as TSLink-enforced Tailscale user authentication
- Credential storage with restricted fallback — API keys and OAuth client secrets use macOS Keychain / Linux secret service / Windows Credential Manager when available. On macOS and Linux, restricted-permission file fallback succeeds only after TSLink proves any stale keychain credential absent or removed. A completely unreachable or uncertain keychain causes an explicit failure to preserve existing credential authority; restore keychain access and retry. Windows has no file fallback, because TSLink cannot prove a user-only DACL locally
- Dynamic auth key derivation — API-token-derived startup auth keys are generated on demand and not persisted; legacy authkey files may still be read for compatibility and should be migrated
- Per-service isolation — each service runs as its own tsnet node with an independent identity
- Inbound header stripping — the proxy strips client-supplied
Tailscale-*andX-Tailscale-*identity headers, including underscore and mixed spellings, before injecting WhoIs identity
Important boundaries:
-
--allowis HTTP access control for proxy and file services. Raw TCP services do not receive TSLink HTTP identity filtering; protect them with Tailscale/Headscale policy, tags, tailnet membership, and the target service's own authentication. -
tslink doctor,tslink status --urls, andtslink access explainare local evidence tools. They do not prove live remote Tailscale ACL/grants, Funnel reachability, or backend application authentication unless those checks are explicitly added in the future. -
tslink mcpis a local stdio MCP server. It is not a REST/admin server and does not create a member-facing service directory. -
Ordinary tag ACL writes require
--manage-aclonlogin,serve, ortags delete-remote. Acknowledged Funnel services are a separate default-on case: auto-provisioning may add the sharedtag:tslink-funnelowner andnodeAttrsgrant to the tailnet policy file. Use--no-auto-provisiononadd --funnel,serve, orinstallto disable its service or daemon setup path. The side-effect plan is machine-readable. -
Per-service tsnet nodes provide network identity and routing separation. TSLink does not provide host process isolation or a compliance attestation.
-
Atomic writes into existing directories reject foreign-owned and group- or world-writable parents on Unix. On Windows, TSLink does not validate the parent directory's DACL: Go's
os.FileModeexposes only synthesized bits that do not represent Windows access control. Windows callers must provision an appropriately restricted DACL when the parent directory is security-sensitive. -
Proxy and TCP target validation refuses literal link-local and unspecified addresses, known cloud-metadata addresses (
fd00:ec2::254,100.100.100.200) and hostnames (metadata.google.internal,metadata.tencentyun.com,instance-data,metadata), and numeric respellings of refused IPv4 addresses. Loopback shorthand such as127.1is accepted. It never resolves DNS: another hostname that resolves to a refused address is accepted at registration and dialed by the daemon. Treat the check as a guard against accidental or injected targets, not as an SSRF boundary; a dial-time address check is tracked as follow-up work. -
The
logsMCP tool's redaction narrows what incidentally reaches a model's context; it is not an isolation boundary. The same log file is emitted verbatim by thetslink logsCLI, so any agent with a shell reads the originals. -
That redaction does not cover a capability separated from its host by a delimiter.
mcpLogsTailscaleURLPatternends a URL at whitespace, a quote, an angle bracket or), and requires one or two slashes afterhttps:. Both choices are deliberate -- the token class is what lets the rule find a URL inside a quoted log field, and the slash count is what made it matchhttps:/login...-- but they leave two shapes that reachsanitizeLogLineintact:https://login.tailscale.com<SP|TAB|CR|">/a/<token> https:login.tailscale.com/a/<token> (zero slashes, url.Opaque)Nothing in TSLink emits either shape:
internal/loggingroutes tsnet's authorization URL through slog as one unbroken token. The exposure is a log line authored elsewhere -- a third-party library, a user pasting into a log, a future formatter that wraps long lines. Widening the token class is not a fix on its own: it trades this leak for over-redacting ordinary prose that mentions the host.
The Go vulnerability database identifies golang.org/x/crypto/openpgp and its six subpackages as unmaintained and unsafe, with no known fixed release. TSLink requires other x/crypto packages through Tailscale. As reviewed on 2026-09-30, the package and test import graphs for all six supported release targets contain none of the affected OpenPGP packages. The required-module advisory remains visible in govulncheck output. The release candidate gate scans ./... for all six OS/architecture targets so a future platform-specific affected import fails the gate; this statement must be rechecked when dependencies or targets change.
If you discover a security vulnerability, please report it responsibly:
- Do not open a public GitHub issue
- Open a private GitHub Security Advisory: https://github.com/anydoor7/tslink/security/advisories/new
- Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
GitHub private vulnerability reporting is the vulnerability intake channel for this repository. The repository maintainer must enable it in GitHub settings. The maintainers coordinate disclosure, fixes, and credit in the advisory thread before any public issue or pull request is opened.
Expect an initial acknowledgement within 7 days. The coordinated disclosure target is 90 days from that acknowledgement; if a fix needs longer, the advisory thread says so and names a new date rather than going quiet.
| Version | Supported |
|---|---|
| v0.1.x | Yes |
| Older versions | No |
The following are in scope for security reports:
- Authentication bypass or credential exposure
- Unauthorized access to services
- Identity header spoofing
- Privilege escalation
- Denial of service against the TSLink daemon
- Vulnerabilities in dependencies that affect TSLink
The following are out of scope:
- Issues in Tailscale itself (report to Tailscale)
- Social engineering
- Issues requiring physical access to the machine running TSLink