中文導讀(編輯整理)
確認預設 loopback、工作階段認證與 token 簽章;未驗證能排除 tunnel 營運者的應用層端對端加密。
實際閱讀範圍:server 綁定、認證/工作階段/機密儲存、cookie/CORS 與安裝;WebSocket 及 DPoP 檢查不完整。
下載完整英文原文 · SHA-256 addb37ce582feab22ae907e274dd736e3d84f9be21be45de2466a5a32480a493
完整英文原始回覆(未翻譯)
Short answer: I didn’t find anything malicious or carelessly insecure in the code I read. The auth design is careful. The real risk comes from what the tool does: it runs coding agents on your machine and can expose control of them to other devices. How risky it is depends mostly on how you configure it.
I read the code through GitHub web fetches at commit d13fc84. I didn’t clone or audit the whole repo, so this covers the security-relevant files only.
Verified from code
Local server and network exposure
- Local-only by default: The server listens on
127.0.0.1unless you set a host (apps/server/src/server.ts:host: config.host ?? "127.0.0.1"). Some third-party doc mirrors say it binds all interfaces by default. The code says otherwise. - Auth even on localhost: There’s no mode that turns auth off. Local browser use needs a one-time token, and the desktop app uses its own bootstrap credential (
auth/EnvironmentAuthPolicy.ts). - Network binding: Binding to
0.0.0.0or::is treated as reachable from other machines (auth/utils.ts).
Session tokens
- Format and signing: Tokens are base64url JSON signed with HMAC-SHA256 (
auth/utils.ts). The key is 32 random bytes fromcrypto.randomBytes, and signatures are checked in constant time. - Lifetimes: Sessions last 30 days. WebSocket tickets last 5 minutes.
- Revocation: Each request checks the database for revocation (
auth/SessionStore.ts). - Not encrypted: The token contents are only signed. Anyone holding a token can read the claims, but they can’t change them.
- Key-binding is optional: DPoP (proof-of-key) binding is optional per token. A token issued without it works as a plain bearer token if stolen.
Secrets on disk
- Server secrets are raw
.binfiles in<state>/secrets, with file mode0600and directory mode0700(auth/ServerSecretStore.ts). - They are not encrypted and the OS keychain isn’t used, so any process running as your user can read them.
Browser cookie and CORS
- The cookie is
httpOnlyandSameSite=Laxbut has noSecureflag (auth/http.ts). That’s harmless on localhost. It’s a small weakness if you serve over a reachable non-HTTPS address. - Packaged builds use a wildcard CORS origin without credentials (
http.ts). That’s acceptable because the API needs a bearer token or DPoP.
Install script (https://t3.codes/install.sh)
- It downloads from GitHub Releases and checks a SHA-256 checksum.
- There’s no signature check, and the checksum file comes from the same release as the binary. So it catches corrupted downloads but not a compromised release.
- It doesn’t use sudo or edit your shell profile.
Things that raise the risk
- Full permissions by default. Pairing links get every permission unless you pass
--scope. That includes running terminal commands andfilesystem:read, which per the docs can read any file your user can read. Anyone with a pairing URL or a stolen session effectively gets a shell as you. Treat pairing links like passwords. --host 0.0.0.0on an untrusted network exposes the server. Auth still applies, but you’re now relying on it entirely. Tailscale or SSH is safer.- T3 Connect sends traffic through Cloudflare Tunnel.
- Per the docs, the relay can’t get your session tokens.
- Neither the repo nor the docs say the traffic is end-to-end encrypted. Cloudflare Tunnel generally decrypts TLS at Cloudflare’s edge, but that’s general Cloudflare behaviour I didn’t verify in this repo. Assume Cloudflare can see that traffic.
- The docs admit that a compromised relay signing key would be a problem.
- Telemetry appears to be on by default.
- It goes to
ingest.t3.codesand is forwarded to PostHog. Relay traces go to Axiom. - It includes hashed account IDs for your T3 Connect, OpenAI and Claude accounts. The docs say prompts, responses, file contents and tokens are excluded.
- To turn it off, set
T3CODE_TELEMETRY_ENABLED=false. The docs note the browser web app doesn’t read these variables.
- It goes to
- The agents themselves. Claude Code, Codex and the others run with whatever permission mode you pick. That’s usually the biggest real-world risk.
What I couldn’t verify
- Where provider and source-control secrets end up.
settingsSecrets.tsandsourceControlHostSecrets.tspass them to a store whose code wasn’t shown. It’s probably the same unencrypted0600file store, but I didn’t confirm it. - The WebSocket upgrade handler and any
Origincheck.ws.tswas truncated, though authentication clearly happens before the RPC layer. - Shared DPoP checks (allowed algorithms, time window), which live in
@t3tools/shared/dpop. - The relay’s server-side code (
infra/relay/src), the mobile apps, and the Electron hardening settings. - Whether the release binaries match this source code.
Recommendation
It’s reasonable to install for local use on a machine you trust. To keep the risk low:
- Keep the default loopback binding.
- Pass
--scopewhen pairing, and revoke devices you no longer use (t3 auth). - Prefer Tailscale or SSH over T3 Connect for sensitive code.
- Set
T3CODE_TELEMETRY_ENABLED=falseif you don’t want telemetry. - Read
install.shbefore piping it tosh.
Sources: repo @ d13fc84, install.sh, mintlify mirror – server options, mintlify mirror – CLI usage