Звіт у форматі JSON машиночитний
{
"data": {
"repo": {
"topics": [],
"is_fork": true,
"size_kb": 83442,
"has_wiki": true,
"homepage": "https://tailscale.com",
"languages": {
"C": 249384,
"Go": 16075410,
"CSS": 31257,
"Lua": 6882,
"Nix": 10309,
"HTML": 37894,
"Rust": 16854,
"Shell": 89976,
"Swift": 56179,
"Makefile": 13065,
"Dockerfile": 8363,
"JavaScript": 3774,
"PowerShell": 19244,
"TypeScript": 163468,
"Go Template": 489
},
"pushed_at": "2026-07-22T06:24:52Z",
"created_at": "2026-07-19T22:40:50Z",
"owner_type": "User",
"updated_at": "2026-07-19T22:40:50Z",
"description": "The easiest, most secure way to use WireGuard and 2FA.",
"is_archived": false,
"is_disabled": false,
"license_spdx": "BSD-3-Clause",
"default_branch": "main",
"license_spdx_raw": "BSD-3-Clause",
"primary_language": "Go",
"significant_languages": [
"Go"
]
},
"owner": {
"blog": null,
"name": null,
"type": "User",
"login": "siteexperts",
"company": null,
"location": null,
"followers": 0,
"avatar_url": "https://avatars.githubusercontent.com/u/22379862?v=4",
"created_at": "2016-09-22T19:59:52Z",
"is_verified": null,
"public_repos": 1,
"account_age_days": 3594
},
"license": {
"state": "standard",
"spdx_id": "BSD-3-Clause",
"raw_spdx": "BSD-3-Clause",
"file_present": true,
"scorecard_found": true,
"profile_has_license": false
},
"activity": {
"releases": [
{
"tag": "v1.101.0-pre",
"kind": "prerelease",
"published_at": "2026-06-03T19:40:23Z"
},
{
"tag": "v1.100.0",
"kind": "minor",
"published_at": "2026-06-03T19:30:27Z"
},
{
"tag": "v1.99.0-pre",
"kind": "prerelease",
"published_at": "2026-05-05T19:07:20Z"
},
{
"tag": "v1.98.9",
"kind": "patch",
"published_at": "2026-07-14T21:36:13Z"
},
{
"tag": "v1.98.8",
"kind": "patch",
"published_at": "2026-06-23T22:22:41Z"
},
{
"tag": "v1.98.7",
"kind": "patch",
"published_at": "2026-06-22T22:49:52Z"
},
{
"tag": "v1.98.6",
"kind": "patch",
"published_at": "2026-06-18T22:56:06Z"
},
{
"tag": "v1.98.5",
"kind": "patch",
"published_at": "2026-05-29T17:11:41Z"
},
{
"tag": "v1.98.4",
"kind": "patch",
"published_at": "2026-05-28T19:16:35Z"
},
{
"tag": "v1.98.3",
"kind": "patch",
"published_at": "2026-05-21T18:27:19Z"
},
{
"tag": "v1.98.2",
"kind": "patch",
"published_at": "2026-05-14T15:22:47Z"
},
{
"tag": "v1.98.1",
"kind": "patch",
"published_at": "2026-05-07T19:31:26Z"
},
{
"tag": "v1.98.1-r2h.6",
"kind": "prerelease",
"published_at": "2026-07-22T06:24:50Z"
},
{
"tag": "v1.98.1-r2h.5",
"kind": "prerelease",
"published_at": "2026-07-22T06:22:18Z"
},
{
"tag": "v1.98.1-r2h.4",
"kind": "prerelease",
"published_at": "2026-07-22T06:15:18Z"
},
{
"tag": "v1.98.1-r2h.3",
"kind": "prerelease",
"published_at": "2026-07-22T06:06:19Z"
},
{
"tag": "v1.98.1-r2h.2",
"kind": "prerelease",
"published_at": "2026-07-22T05:43:25Z"
},
{
"tag": "v1.98.1-r2h.1",
"kind": "prerelease",
"published_at": "2026-07-22T05:13:37Z"
},
{
"tag": "v1.98.0",
"kind": "minor",
"published_at": "2026-05-05T18:47:22Z"
},
{
"tag": "v1.97.0-pre",
"kind": "prerelease",
"published_at": "2026-03-05T20:24:48Z"
},
{
"tag": "v1.96.5",
"kind": "patch",
"published_at": "2026-03-27T18:20:32Z"
},
{
"tag": "v1.96.4",
"kind": "patch",
"published_at": "2026-03-25T19:45:12Z"
},
{
"tag": "v1.96.3",
"kind": "patch",
"published_at": "2026-03-19T17:37:00Z"
},
{
"tag": "v1.96.2",
"kind": "patch",
"published_at": "2026-03-17T22:05:14Z"
},
{
"tag": "v1.96.1",
"kind": "patch",
"published_at": "2026-03-10T14:09:37Z"
},
{
"tag": "v1.96.0",
"kind": "minor",
"published_at": "2026-03-05T20:08:34Z"
},
{
"tag": "v1.95.0-pre",
"kind": "prerelease",
"published_at": "2026-01-14T22:19:17Z"
},
{
"tag": "v1.94.2",
"kind": "patch",
"published_at": "2026-02-13T19:41:21Z"
},
{
"tag": "v1.94.1",
"kind": "patch",
"published_at": "2026-01-22T18:44:55Z"
},
{
"tag": "v1.94.0",
"kind": "minor",
"published_at": "2026-01-14T20:55:28Z"
},
{
"tag": "v1.93.0-pre",
"kind": "prerelease",
"published_at": "2025-11-26T20:49:52Z"
},
{
"tag": "v1.92.5",
"kind": "patch",
"published_at": "2026-01-06T18:15:04Z"
},
{
"tag": "v1.92.4",
"kind": "patch",
"published_at": "2025-12-18T10:30:54Z"
},
{
"tag": "v1.92.3",
"kind": "patch",
"published_at": "2025-12-16T20:11:52Z"
},
{
"tag": "v1.92.2",
"kind": "patch",
"published_at": "2025-12-10T18:24:06Z"
},
{
"tag": "v1.92.1",
"kind": "patch",
"published_at": "2025-12-05T15:51:26Z"
},
{
"tag": "v1.92.0",
"kind": "minor",
"published_at": "2025-11-26T20:35:58Z"
},
{
"tag": "v1.91.0-pre",
"kind": "prerelease",
"published_at": "2025-10-20T16:11:05Z"
},
{
"tag": "v1.90.9",
"kind": "patch",
"published_at": "2025-11-25T16:12:16Z"
},
{
"tag": "v1.90.8",
"kind": "patch",
"published_at": "2025-11-18T18:31:30Z"
},
{
"tag": "v1.90.7",
"kind": "patch",
"published_at": "2025-11-18T17:32:04Z"
},
{
"tag": "v1.90.6",
"kind": "patch",
"published_at": "2025-10-31T21:18:03Z"
},
{
"tag": "v1.90.5",
"kind": "patch",
"published_at": "2025-10-30T17:38:25Z"
},
{
"tag": "v1.90.4",
"kind": "patch",
"published_at": "2025-10-28T18:29:24Z"
},
{
"tag": "v1.90.3",
"kind": "patch",
"published_at": "2025-10-27T16:15:14Z"
},
{
"tag": "v1.90.2",
"kind": "patch",
"published_at": "2025-10-24T16:49:00Z"
},
{
"tag": "v1.90.1",
"kind": "patch",
"published_at": "2025-10-23T16:06:03Z"
},
{
"tag": "v1.90.0",
"kind": "minor",
"published_at": "2025-10-20T16:01:07Z"
},
{
"tag": "v1.89.0-pre",
"kind": "prerelease",
"published_at": "2025-09-11T18:19:17Z"
},
{
"tag": "v1.88.4",
"kind": "patch",
"published_at": "2025-10-14T17:45:00Z"
},
{
"tag": "v1.88.3",
"kind": "patch",
"published_at": "2025-09-25T13:04:46Z"
},
{
"tag": "v1.88.2",
"kind": "patch",
"published_at": "2025-09-17T17:13:08Z"
},
{
"tag": "v1.88.1",
"kind": "patch",
"published_at": "2025-09-11T19:13:06Z"
},
{
"tag": "v1.88.0",
"kind": "minor",
"published_at": "2025-09-11T17:33:53Z"
},
{
"tag": "v1.87.0-pre",
"kind": "prerelease",
"published_at": "2025-07-24T18:25:57Z"
},
{
"tag": "v1.86.5",
"kind": "patch",
"published_at": "2025-08-22T16:30:19Z"
},
{
"tag": "v1.86.4",
"kind": "patch",
"published_at": "2025-08-07T16:46:29Z"
},
{
"tag": "v1.86.3",
"kind": "patch",
"published_at": "2025-08-07T15:18:21Z"
},
{
"tag": "v1.86.2",
"kind": "patch",
"published_at": "2025-07-29T16:56:20Z"
},
{
"tag": "v1.86.1",
"kind": "patch",
"published_at": "2025-07-25T17:54:40Z"
},
{
"tag": "v1.86.0",
"kind": "minor",
"published_at": "2025-07-24T18:11:13Z"
},
{
"tag": "v1.85.0-pre",
"kind": "prerelease",
"published_at": "2025-05-21T19:27:32Z"
},
{
"tag": "v1.84.3",
"kind": "patch",
"published_at": "2025-06-26T16:26:38Z"
},
{
"tag": "v1.84.2",
"kind": "patch",
"published_at": "2025-06-09T21:39:17Z"
},
{
"tag": "v1.84.1",
"kind": "patch",
"published_at": "2025-05-29T17:40:49Z"
},
{
"tag": "v1.84.0",
"kind": "minor",
"published_at": "2025-05-21T19:10:03Z"
},
{
"tag": "v1.83.0-pre",
"kind": "prerelease",
"published_at": "2025-03-26T13:29:38Z"
},
{
"tag": "v1.82.5",
"kind": "patch",
"published_at": "2025-04-17T19:01:26Z"
},
{
"tag": "v1.82.4",
"kind": "patch",
"published_at": "2025-04-11T17:52:10Z"
},
{
"tag": "v1.82.3",
"kind": "patch",
"published_at": "2025-04-11T16:32:59Z"
},
{
"tag": "v1.82.2",
"kind": "patch",
"published_at": "2025-04-10T19:53:40Z"
},
{
"tag": "v1.82.0",
"kind": "minor",
"published_at": "2025-03-26T19:50:33Z"
},
{
"tag": "v1.81.0-pre",
"kind": "prerelease",
"published_at": "2025-01-30T21:04:29Z"
},
{
"tag": "v1.80.3",
"kind": "patch",
"published_at": "2025-03-03T20:05:20Z"
},
{
"tag": "v1.80.2",
"kind": "patch",
"published_at": "2025-02-12T18:31:52Z"
},
{
"tag": "v1.80.1",
"kind": "patch",
"published_at": "2025-02-06T18:38:55Z"
},
{
"tag": "v1.80.0",
"kind": "minor",
"published_at": "2025-01-30T20:52:55Z"
},
{
"tag": "v1.79.0-pre",
"kind": "prerelease",
"published_at": "2024-12-06T17:25:12Z"
},
{
"tag": "v1.78.3",
"kind": "patch",
"published_at": "2024-12-11T20:26:51Z"
},
{
"tag": "v1.78.2",
"kind": "patch",
"published_at": "2024-12-11T18:06:06Z"
},
{
"tag": "v1.78.1",
"kind": "patch",
"published_at": "2024-12-05T23:51:23Z"
},
{
"tag": "v1.78.0",
"kind": "minor",
"published_at": "2024-12-05T19:16:48Z"
},
{
"tag": "v1.77.0-pre",
"kind": "prerelease",
"published_at": "2024-10-10T18:34:14Z"
},
{
"tag": "v1.76.6",
"kind": "patch",
"published_at": "2024-11-04T20:07:36Z"
},
{
"tag": "v1.76.3",
"kind": "patch",
"published_at": "2024-10-21T15:10:38Z"
},
{
"tag": "v1.76.1",
"kind": "patch",
"published_at": "2024-10-15T18:20:59Z"
},
{
"tag": "v1.76.0",
"kind": "minor",
"published_at": "2024-10-10T18:11:51Z"
},
{
"tag": "v1.75.0-pre",
"kind": "prerelease",
"published_at": "2024-09-12T20:19:46Z"
},
{
"tag": "v1.74.1",
"kind": "patch",
"published_at": "2024-09-18T18:54:26Z"
},
{
"tag": "v1.74.0",
"kind": "minor",
"published_at": "2024-09-12T19:58:22Z"
},
{
"tag": "v1.73.0-pre",
"kind": "prerelease",
"published_at": "2024-08-19T17:17:29Z"
},
{
"tag": "v1.72.1",
"kind": "patch",
"published_at": "2024-08-22T16:21:32Z"
},
{
"tag": "v1.72.0",
"kind": "minor",
"published_at": "2024-08-19T17:07:21Z"
},
{
"tag": "v1.71.0-pre",
"kind": "prerelease",
"published_at": "2024-07-17T17:27:05Z"
},
{
"tag": "v1.70.0",
"kind": "minor",
"published_at": "2024-07-17T17:11:59Z"
},
{
"tag": "v1.69.0-pre",
"kind": "prerelease",
"published_at": "2024-06-12T17:16:33Z"
},
{
"tag": "v1.68.2",
"kind": "patch",
"published_at": "2024-07-02T18:23:20Z"
},
{
"tag": "v1.68.1",
"kind": "patch",
"published_at": "2024-06-14T11:47:24Z"
},
{
"tag": "v1.68.0",
"kind": "minor",
"published_at": "2024-06-12T17:03:59Z"
}
],
"recent_commits": [
{
"oid": "82cfea90ca1f3bbfd8f224d88c939f8264eb2ff1",
"body": "Go 1.27 enables GOEXPERIMENT=jsonv2 by default: encoding/json is now\nbacked by the json/v2 machinery, and github.com/go-json-experiment/json\ncompiles as a thin alias of the standard library's encoding/json/v2.\nSeveral tag options and behaviors we relied on did not make the cut for\nthe final Go 1.27 \n[…]\n./... passes with both Go 1.26.5 and\ngo1.27rc2.\n\nUpdates #20220\nFixes #20528\nFixes #20254\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I694c7d57fd81e55a579c579e9be10032bca569d4",
"is_bot": false,
"headline": "all: fix JSON serialization under Go 1.27's finalized encoding/json/v2",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-19T16:58:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ece1b12ebfa7956432027d8b995e5ed84b7da780",
"body": "…rror\n\nThe NetstackDialTCP/UDP hooks returned the result of DialContextTCP/UDP\ndirectly, so on error they returned a non-nil net.Conn interface holding\na nil *gonet.TCPConn or *gonet.UDPConn pointer, tripping up callers that\ncheck the interface against nil and then call Close, crashing the wasm\nworker. Apply the same fix that 46bdbb387 made for tailscaled and tsnet.\n\nFixes #20529\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I4fd66bb7615ee9b2d204256a43288ed7b7a12f35",
"is_bot": false,
"headline": "cmd/tsconnect/wasm: don't return non-nil net.Conn interface on dial e…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-19T13:48:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7be0054a7b1dd4ba791f94302211e2614d6a42ce",
"body": "b5a41ff381bf originally added both tuatara and mispelled tautara,\none as a tail and one as a scale.\n\nf174ecb6fdab added tuatara as a scale, not noticing the tautara\nimposter.\n\nFixes #20522\n\nChange-Id: Ie4fcb262ac705c766f55d406835de419856bb170\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "words: redress historical wrongs against the tuatara",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-18T22:34:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b91e844014228a488979612031b3bd474d6d9f4b",
"body": "Simplifies cmd/containerboot env var parsing. Most of the private helpers did\nnot earn their abstraction: defaultEnv(name, \"\") is just os.Getenv(name), and\nthe rest collapse into cmp.Or and the existing def.Bool. defaultEnv,\ndefaultEnvs and defaultBool are gone.\n\nAdds def.LookupEnv, the env companio\n[…]\nS_KUBE_SECRET, where an explicit \"\" disables Kubernetes secret storage and\nmust stay distinct from unset (cmp.Or cannot express that).\n\nUpdates #20018\n\nSigned-off-by: Nick Rossi <nrossi0530@gmail.com>",
"is_bot": false,
"headline": "util/def,cmd/containerboot: add LookupEnv, simplify env parsing (#20277)",
"author_name": "Nick Rossi",
"author_login": "nicholasrossi0530",
"committed_at": "2026-07-18T01:32:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d2af6a4d39adbca71792cf0f89119e513e111e1c",
"body": "…DoH (#20463)\n\nDoHEndpointFromIP mapped the entire 2606:1a40::/48 range to a\ndns.controld.com/<id> DoH URL, but the ID-encoded addresses in that range\nare legacy plaintext-DNS endpoints that refuse :443. They now fall through\nas ordinary port-53 resolvers; the free anycast freedns.controld.com/pN\naddresses still upgrade via exact match.\n\nFixes #20433\n\nSigned-off-by: Brendan Creane <bcreane@gmail.com>",
"is_bot": false,
"headline": "net/dns/publicdns: don't upgrade Control D port-53-only addresses to …",
"author_name": "Brendan Creane",
"author_login": "bcreane",
"committed_at": "2026-07-17T22:33:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "689c6c2e6d24763829f9d991a9037b92d8ee9ef4",
"body": "…eers (#20513)\n\nThis change ensures `packetFilterPermitsUnlockedNodes` also considers SrcCaps-based grants when checking for unsigned peer access.\n\nFixes tailscale/corp#45116\n\nChange-Id: I0ac938367888f67ed6f355fc19959cc8c31722a2\n\nSigned-off-by: Mike Jensen <mikej@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal: reject SrcCaps-based packet filter rules for unsigned p…",
"author_name": "Mike Jensen",
"author_login": "jentfoo",
"committed_at": "2026-07-17T21:58:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bab3f5fce77544937a36d4d7705f040c3cd1cea8",
"body": "…20304)\n\n* net/tsaddr: unmap IPv4-mapped IPv6 addrs in IsTailscaleIP\n\nIsTailscaleIP branched on ip.Is4() before checking the CGNAT range, so an\nIPv4-mapped IPv6 address (e.g. ::ffff:100.64.0.1) took the IPv6 path and was\ntested only against the ULA range, wrongly returning false for a Tailscale\nCGNA\n[…]\n remains a follow-up (tailscale/corp#43882).\n\nUpdates #19974\nFixes tailscale/corp#44173\n\nSigned-off-by: Brendan Creane <bcreane@gmail.com>\n\n---------\n\nSigned-off-by: Brendan Creane <bcreane@gmail.com>",
"is_bot": false,
"headline": "wgengine/router/osrouter: remove orphaned tailnet addrs on cleanup (#…",
"author_name": "Brendan Creane",
"author_login": "bcreane",
"committed_at": "2026-07-17T21:18:09Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0433cc69297ed15d1a5ed09add693e15cb886133",
"body": "Add a new modular syslog feature providing a tailscaled --syslog flag\nthat sends the daemon's logs to the system syslog daemon instead of\nstderr, which is useful when running as a daemon without a service\nmanager that captures stderr (e.g. OpenWrt's procd).\n\nThe feature package registers two new hoo\n[…]\nails at startup, tailscaled logs a warning and\ncontinues logging to stderr.\n\nFixes #16270\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I8f3a92d4c1e6b70a5d29e4f61b3c874250a9de13",
"is_bot": false,
"headline": "feature/syslog, cmd/tailscaled, logpolicy: add optional --syslog flag",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-17T20:55:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "def265083b56a19b7f813a054d217af09fc0a7ba",
"body": "…vice (#20382)\n\n* tstest/integration: run a test against a real Windows tailscaled service\n\nUpdates #20381\n\nSigned-off-by: Yaruk Asghar <yaruk@tailscale.com>\n\n* tstest/integration: serialize Windows service tests and clean up state\n\nUpdates #20381\n\nSigned-off-by: Yaruk Asghar <yaruk@tailscale.com>\n\n\n[…]\n\n* tstest/integration: address review feedback on Windows service tests\n\nUpdates #20381\n\nSigned-off-by: Yaruk Asghar <yaruk@tailscale.com>\n\n---------\n\nSigned-off-by: Yaruk Asghar <yaruk@tailscale.com>",
"is_bot": false,
"headline": "tstest/integration: run a smoke test against a Windows tailscaled ser…",
"author_name": "yaruk-byte",
"author_login": "yaruk-byte",
"committed_at": "2026-07-17T19:29:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "11a6255b22a3071bb63992ee8f7fbedd6d50f4d1",
"body": "This variable wasn't used in the commit when it was introduced (bd5c509).\n\nFixes #19841\n\nChange-Id: I82a2ba613c71eb99d98c5e7063e8cd077ba03ece\nSigned-off-by: Alex Chan <alexc@tailscale.com>",
"is_bot": false,
"headline": "scripts/installer.sh: remove an unused PACKAGE_NAME variable",
"author_name": "Alex Chan",
"author_login": "alexwlchan",
"committed_at": "2026-07-17T19:12:50Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9175fe2675264bbb08a9d6d8830e282c0b68f17c",
"body": "Enforce that TSMP messages are only accepted for transmission over the\nwireguard connection from within the client.\n\nUpdates tailscale/corp#45059\n\nSigned-off-by: Claus Lensbøl <claus@tailscale.com>",
"is_bot": false,
"headline": "net/tstun: drop TSMP messages injected into TUN (#20511)",
"author_name": "Claus Lensbøl",
"author_login": "cmol",
"committed_at": "2026-07-17T19:10:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "82a381e54b9866133dac1b425d806fd174b19690",
"body": "…ero keys in TSMP (#20508)\n\nUpdates tailscale/corp#45042\n\nSigned-off-by: Claus Lensbøl <claus@tailscale.com>",
"is_bot": false,
"headline": "control/controlclient,net/tstun,wgengine/magicsock: fix handling of z…",
"author_name": "Claus Lensbøl",
"author_login": "cmol",
"committed_at": "2026-07-17T18:02:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c1edf7f45836b3e8c1bb9a75ce62fe0ed4f82371",
"body": "…os.OpenInRoot (#20505)\n\ninterfaceV6UsableForTun interpolates the interface name into a /proc path.\nA plain filepath.Join + os.Open only cleans the path, so a tunname with\n\"..\" (or a symlinked component) could read outside /proc/sys/net/ipv6/conf.\nOpen under that fixed directory with os.OpenInRoot, \n[…]\n root (openat-based, so also TOCTOU-resistant), still using\nfilepath.Join to build the relative name. See https://go.dev/blog/osroot.\n\nUpdates #20447\n\nSigned-off-by: Brendan Creane <bcreane@gmail.com>",
"is_bot": false,
"headline": "wgengine/router/osrouter: sanitize interfaceV6UsableForTun path with …",
"author_name": "Brendan Creane",
"author_login": "bcreane",
"committed_at": "2026-07-17T17:17:06Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cc0b3ddbbe7804f84cf95bd087df9e921bada30e",
"body": "Updates #cleanup\n\nSigned-off-by: Jordan Whited <jordan@tailscale.com>",
"is_bot": false,
"headline": "net/packet: add TSMPType docs",
"author_name": "Jordan Whited",
"author_login": "jwhited",
"committed_at": "2026-07-17T16:56:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3076698cdf8c075740d8f48b554b4b4451901897",
"body": "Updates #cleanup\n\nSigned-off-by: Jordan Whited <jordan@tailscale.com>",
"is_bot": false,
"headline": "net/packet: fix TSMPType docs",
"author_name": "Jordan Whited",
"author_login": "jwhited",
"committed_at": "2026-07-17T16:28:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "94381a191aa6018ac2c6e3127a7f85077fddd806",
"body": "Fixes tailscale/corp#45066\n\nSigned-off-by: Jordan Whited <jordan@tailscale.com>",
"is_bot": false,
"headline": "disco: fix UDPRelayEndpoint.AddrPorts slice cap math",
"author_name": "Jordan Whited",
"author_login": "jwhited",
"committed_at": "2026-07-17T16:11:12Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7ec9b7ffa3dc1c4b0c7ce4e8a7b05cd28775bac9",
"body": "We were accidentally hardcoding TTL 0 before.\n\nFixes tailscale/corp#45025\n\nSigned-off-by: Michael Ben-Ami <mzb@tailscale.com>",
"is_bot": false,
"headline": "feature/conn25: preserve TTL on DNS rewrites",
"author_name": "Michael Ben-Ami",
"author_login": "mzbenami",
"committed_at": "2026-07-17T14:27:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cfd101f9d773695def27a5f6289fc25ac36ac991",
"body": "* wgengine: configure DNS even when router.Set fails\n\nReconfig configured the router first and returned on any router.Set error,\nbefore the DNS block ran. On a host where router config fails on every\nreconfig -- e.g. a tun MTU below 1280 that breaks IPv6, or a kernel missing\nnetfilter features -- th\n[…]\nove the dead r.v6Available field that masked this with its global\nname.\n\nUpdates #20447\n\nSigned-off-by: Brendan Creane <bcreane@gmail.com>\n\n---------\n\nSigned-off-by: Brendan Creane <bcreane@gmail.com>",
"is_bot": false,
"headline": "configure DNS even when router.Set fails (#20488)",
"author_name": "Brendan Creane",
"author_login": "bcreane",
"committed_at": "2026-07-16T21:53:30Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b2de420e3db415767ab1800bea8c09b28e3e185c",
"body": "At /v0/conn25-state.\n\nState includes whether the node is configured for Connectors 2025, as\nwell as client-specific and connector-specific state, if the node is\nacting in those contexts.\n\nClient-specific state includes the reserved Magic IPs and Transit IPs on\nthe client that have not been returned \n[…]\nnts that have\nregistered Transit IPs with the connector, and the apps are real\ndestination IPs the Transit IPs map to.\n\nUpdates tailscale/corp#40125\n\nSigned-off-by: Michael Ben-Ami <mzb@tailscale.com>",
"is_bot": false,
"headline": "feature/conn25,types/appctype: serve active Conn25 state over localapi",
"author_name": "Michael Ben-Ami",
"author_login": "mzbenami",
"committed_at": "2026-07-16T20:35:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "71e5a984049c4191d0cbeedb1d4a0dbd29aa17b3",
"body": "Updates tailscale/corp#41997\n\nChange-Id: I5fb3d4705766deb71abd0b79a186e99e86be0b15\n\nSigned-off-by: Mike Jensen <mikej@tailscale.com>",
"is_bot": false,
"headline": "Update tailscale/gliderssh to pull in tailscale/gliderssh#12 (#20485)",
"author_name": "Mike Jensen",
"author_login": "jentfoo",
"committed_at": "2026-07-16T19:46:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6a2aa6889e02bbae30c86f95b3a8f6761b575c67",
"body": "Updates #20081\n\nSigned-off-by: Jordan Whited <jordan@tailscale.com>",
"is_bot": false,
"headline": "go.mod: bump wireguard-go for priority msg callback",
"author_name": "Jordan Whited",
"author_login": "jwhited",
"committed_at": "2026-07-16T15:59:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "50f1c285bae11966697dcc0f682feb2527b099a0",
"body": "…erve\n\nAllow `tailscale serve --tcp <port> unix:/path/to/socket` and `tailscale serve --tls-terminated-tcp <port> unix:/path/to/socket` to forward TCP connections to a Unix domain socket. Previously only host:port targets were supported for TCP serve mode.\n\nUpdates #20161\n\nSigned-off-by: ayanamist <ayanamist@gmail.com>",
"is_bot": false,
"headline": "ipn/ipnlocal,cmd/tailscale/cli: support unix socket targets for TCP s…",
"author_name": "ayanamist",
"author_login": "ayanamist",
"committed_at": "2026-07-16T15:13:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "38345dce3d475a064f5dd6557553fc0ffa2795dc",
"body": "The job is consistently failing on main when it hits the 5 minute\ntimeout; let's double it to get useful results.\n\nUpdates #cleanup\n\nChange-Id: Iaff2f95d4944929e6832273c94d628f376e2d30e\nSigned-off-by: Alex Chan <alexc@tailscale.com>",
"is_bot": false,
"headline": ".github: double the timeout for `go vet` in CI",
"author_name": "Alex Chan",
"author_login": "alexwlchan",
"committed_at": "2026-07-16T15:05:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "71b90de0d4aed7ea720e395ee945a6bfd63c5d8b",
"body": "…0484)",
"is_bot": false,
"headline": "derp/derpserver,cmd/derper: use slices.Clip for cert chain copies (#2…",
"author_name": "Mike O'Driscoll",
"author_login": "mikeodr",
"committed_at": "2026-07-16T02:13:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bf7d815631f2f48c34834d9b5f5688e424f85c20",
"body": "…ertificate (#20478)\n\nModifyTLSConfigToAddMetaCert (and its inline copy in cmd/derper) appended\nthe DERP meta cert directly to the *tls.Certificate returned by the\nunderlying GetCertificate. autocert returns a certificate sharing a cached\nchain slice (and, on the TLS-ALPN token path, the same pointe\n[…]\npended to a fresh backing\narray instead, and have cmd/derper reuse ModifyTLSConfigToAddMetaCert\nrather than duplicating the wrapper.\n\nFixes #20352\n\nSigned-off-by: Mike O'Driscoll <mikeo@tailscale.com>",
"is_bot": false,
"headline": "derp/derpserver,cmd/derper: don't mutate cert provider's shared tls.C…",
"author_name": "Mike O'Driscoll",
"author_login": "mikeodr",
"committed_at": "2026-07-15T21:16:40Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bef2cd8088e95d093928874d8ae00d5cd50501c5",
"body": "…tests\n\nThe \"vm\" CI job ran a single test (TestRunUbuntu2404 from\ntstest/integration/vms) on a privileged self-hosted runner. Its coverage\nis nearly all redundant with the modern natlab vmtest suite, which boots\nreal Ubuntu VMs and already exercises connectivity, kernel TUN, SSH,\nTaildrop, ACME, and\n[…]\ne through the guest's OS\nresolver (libc to systemd-resolved to quad-100).\n\nUpdates #13038\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I8d0dfb8b8153289e7ca78f3af03dfece9497bfe8",
"is_bot": false,
"headline": ".github, tstest/natlab/vmtest: replace old VM runner job with natlab …",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-15T19:25:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6bf05cb63e21d7e56bfc02acc005011807327287",
"body": "The Apple clients' last consumer of the legacy Notify.NetMap field was\nconverted to peer deltas in tailscale/corp#44962, so tailscaled no\nlonger needs to build and emit full netmaps on the IPN bus for darwin\nand ios. Windows is now the only remaining platform on the legacy path.\n\nUpdates #12542\n\nChange-Id: I295d826735191bb601d2b69d8d85d37a5a82b6c9\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "ipn, ipn/ipnlocal: remove darwin & ios from goosGetsLegacyNetmapNotify",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-15T18:47:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "168b20d3b42088aafa30e73dd57e8590ad8d5fbd",
"body": "The android client was converted in https://github.com/tailscale/tailscale-android/pull/797\n\nUpdates #12542\n\nChange-Id: Ibb2cc6fbafdad93ae44e1a60e5cc5de8183f9b97\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal: remove android from goosGetsLegacyNetmapNotify",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-15T17:41:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "65fd320aa670d6e075dc5b20dc987f7748f22405",
"body": "The nodeBackend's netMap.Peers slice is frozen at the last full netmap\ninstall; the live per-peer state lives in the nodeBackend.peers map,\nupdated by delta mutations. Three spots still read the stale slice or\npaid to materialize a fresh one:\n\nAppendMatchingPeers iterated netMap.Peers and re-looked-\n[…]\ns-free netmap to peerAPIBase, which only\nreads the self node's addresses.\n\nUpdates #12542\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I2e57527d64733b4eb17006f896faaa907b1d128c",
"is_bot": false,
"headline": "ipn/ipnlocal: use the live peer map, not the netmap's stale Peers slice",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-15T17:29:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0bae2019126d6309311fc206e848afa48cfd535b",
"body": "Split TestTailscaleSSH into separate tests per host OS being tested to\nallow for potentially running these tests in parallel on different\nmachines.\n\nUpdates https://github.com/tailscale/tailscale/issues/13038\n\nSigned-off-by: Mario Minardi <mario@tailscale.com>",
"is_bot": false,
"headline": "tstest/natlab: split SSH test into separate tests",
"author_name": "Mario Minardi",
"author_login": "mpminardi",
"committed_at": "2026-07-15T16:53:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0fb82267083457acd4a6172331e41794db15cf54",
"body": "The tailscale/gokrazy-kernel module was a fork of rtr7/kernel that\nstalled at Linux 6.8.9 (July 2024). All of the kernel config options we\nhad added in that fork (ENA, Xen for EC2, virtio-mmio for qemu microvm,\nvirtio RNG, IPv6 policy routing, netlink diag, etc) are now present in\nthe gokrazy projec\n[…]\nustIPv6, and TestTailscaleSSH in\ntstest/natlab/vmtest with --run-vm-tests.\n\nUpdates #1866\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I90c3765a4e18f5609b4d77b51ac38d17c8e3688a",
"is_bot": false,
"headline": "gokrazy, tstest, cmd/vnet: switch amd64 kernel to gokrazy/kernel.amd64",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-15T15:45:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4660a961ebd64c4fdafe93d8cef834d973b36387",
"body": "… path\n\nProcessing a peer add/remove delta still materialized the full netmap\n(an O(n) slicesx.MapValues plus sort over all peers, at 10k+\npeers in a large tailnet) twice per delta: once in UpdateNetmapDelta\npurely to hand the self node to Engine.SetSelfNode, and once in\nauthReconfigLocked.\n\nNeither\n[…]\n at the\nstart of this effort, before the incremental route manager work).\n\nUpdates #12542\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: Ia0e03ef9db0c988790b2c29de1f0505305e93f58",
"is_bot": false,
"headline": "ipn/ipnlocal, wgengine/wgcfg/nmcfg: stop building peer lists on delta…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-15T15:21:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3515b009c22d1d6b299cead0fde6e3f9d1068d59",
"body": "… hook\n\nThe ExtraWireGuardAllowedIPs hook was called once per peer on every\nauthReconfig, so each netmap delta paid an O(n) scan over all peers\neven when conn25 (the only implementer) wasn't configured and every\ncall returned nothing.\n\nInvert the API: the hook now receives an iter.Seq2 of the curren\n[…]\no longer reports the updateRouteManagerExtras peer scan on netmap\ndeltas.\n\nUpdates #12542\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I9181e77416fa22f4c904620d42e9bcb934165216",
"is_bot": false,
"headline": "ipn/ipnext, ipn/ipnlocal, feature/conn25: pass peer seq to AllowedIPs…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-15T14:12:58Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f68e4d93fd309f329299896a8f1a291fdc08bf39",
"body": "Do not label plain TCP forwarding as TLS over TCP. Render status\nannotations only when TLS termination or PROXY protocol is configured.\n\nFixes #20367\n\nChange-Id: I3f6507365ceedc2950451810e9715afb85176fc5\nSigned-off-by: coyaSONG <66289470+coyaSONG@users.noreply.github.com>",
"is_bot": false,
"headline": "cmd/tailscale/cli: fix plain TCP serve status",
"author_name": "coyaSONG",
"author_login": "coyaSONG",
"committed_at": "2026-07-15T14:01:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a534ad5e86840c8ffada033496d22a80191684b2",
"body": "Make CheckAWSAuth, UploadToS3, ImportSnapshot, and RegisterAMI public so\na build server can run them individually (e.g. Marketplace publishing\nafter RegisterAMI). Rename BuildAMI to BuildAndImportAMI, now a thin\norchestrator over them. Each step records into Result and returns its\nartifact; the AWS steps guard on their predecessor and error clearly if\ncalled out of order.\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "gokrazy/build: expose AMI pipeline as composable steps",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-15T13:15:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "720cd0a2d0adc084262a5571e4d38d1bf278f984",
"body": "Generated by make updatedeps and ./tool/go run ./tool/updateflakes\nafter adding service/ec2 (and the smithy-go bump it pulls in).\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "all: regenerate dep manifests for aws-sdk-go-v2/service/ec2",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-15T13:15:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a7f3e083350e1bb12dc4f6cf067a4f5b294f2a3f",
"body": "Replace the four aws CLI shell-outs (s3 cp, ec2 import-snapshot,\ndescribe-import-snapshot-tasks, register-image) with aws-sdk-go-v2 S3\nand EC2 clients. Credentials come from the SDK default chain, so\nexisting aws sso login / aws configure / AWS_PROFILE / env / aws-vault\nsessions keep working.\n\nVerif\n[…]\nnative progress reader, log\n[n/4] step lines, and bail on terminal import-snapshot failure states\ninstead of polling forever.\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "gokrazy/build: use AWS SDK instead of shelling out to aws CLI",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-15T13:15:17Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b049ce71a53909e5e8897823ae8d17e7b60e4814",
"body": "Capture the AWS Progress/StatusMessage fields and report them instead of\nreprinting the full describe-import-snapshot-tasks JSON every 5s. On a\nterminal, repaint one live percentage line; otherwise log one line per\nphase change so CI stays terse.\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "gokrazy/build: show import-snapshot progress, quiet in CI",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-15T13:15:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7653a1e438105edf88a9b5224318c1dfaa01b6f3",
"body": "Move the appliance/AMI build logic into tailscale.com/gokrazy/build so\nGo callers (e.g. flash-appliance) can call it directly instead of\ndriving build.go over --json. build.go is now a thin flag wrapper; flags\nand --json output are unchanged. Package-level state becomes a Builder\nwith an exported Config, ctx-first steps, and a Build one-shot.\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "gokrazy: split build.go into thin main + reusable build package",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-15T13:15:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bb4f458207c441727bc88b59bd315ccbf78449b5",
"body": "…heck\n\nCaptive portal detection was half-migrated: it had a build tag and\nbuildfeatures constant, but its code still lived in build-tag-gated\nfiles in ipn/ipnlocal and net/netcheck, with its per-backend state\n(context, cancel func, signaling channel) as fields on LocalBackend.\n\nMove it under feature\n[…]\nblank-import the feature package, and\ntsnet's dep test now locks that in.\n\nUpdates #12614\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I3f1d09f9dc03e18f9a648ab5e42d16fa540b3fa9",
"is_bot": false,
"headline": "feature/captiveportal: move captive portal code out of ipnlocal, netc…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-15T00:22:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "72ca0cae4b690555edc7612be9d4ca8564337017",
"body": "The wireguard-go device now learns its peer set solely from the live\nper-peer config source that LocalBackend installs with\nEngine.SetPeerConfigFunc, backed by the route manager. Peers are\ncreated lazily on first packet and converged per peer with\nEngine.SyncDevicePeer, so the full-peer-list snapsho\n[…]\ny the peers whose routes the route manager reports as\nchanged or removed.\n\nUpdates #12542\n\nChange-Id: Ic776e42cfaa5be6b9329b3d381d5cbde17d7078b\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "wgengine/wgcfg,wgengine,ipn/ipnlocal: remove Peers from wgcfg.Config",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-14T23:57:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "87c0d3694213f432f0b5b44584c9aad006541a05",
"body": "The map[key.NodePublic][]netip.Prefix that flows from route manager\ncommits to WireGuard device syncs has subtle semantics (a nil value\nmeans the peer was removed or no longer contributes any prefixes)\nthat were documented on routemanager.Result.AllowedIPs and then\nre-documented, or not, at each sig\n[…]\nd type, PeersWithRouteChanges, and document the nil\nsemantics once on it.\n\nUpdates #12542\n\nChange-Id: I2566361a5331eb11b2b70a5bcdb497cc20ee561d\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "net/routemanager,ipn/ipnlocal: name the changed-allowed-IPs map type",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-14T23:57:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f0ce89b71526c73803c61adcc14243b40c17ff50",
"body": "…teManager table\n\nPreviously tstun.Wrapper.SetWGConfig walked wgcfg.Config.Peers on every\nnetmap to rebuild its own IP-to-peer table for masquerade NAT rewrites\nand jailed-peer classification. Now the tun layer instead consumes the\nroute manager's shared immutable outbound snapshot directly, via a n\n[…]\n\nThis is the last step before removing the Peers field from wgcfg.Config.\n\nUpdates #12542\n\nChange-Id: Ifce09ca929a3f2511303ca1d6efdd583739494ce\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "net/tstun,wgengine,ipn/ipnlocal: make tstun's peerConfigTable use Rou…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-14T19:41:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e4144230f410204aa2f43a07a57182c751239597",
"body": "Reject leading dashes in usernames and add double dash to getent call\non linux to prevent values sent as usernames being interpreted as\ncommand options.\n\nFixes https://github.com/tailscale/corp/issues/44813\n\nSigned-off-by: Mario Minardi <mario@tailscale.com>",
"is_bot": false,
"headline": "util/osuser: reject leading dashes in usernames",
"author_name": "Mario Minardi",
"author_login": "mpminardi",
"committed_at": "2026-07-14T18:59:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9d01b036c798fec65432f4ec918b2ec3c2e57597",
"body": "The tun-layer per-peer data plane (jailed packet filter selection and\nmasquerade NAT rewrites) had no end-to-end coverage: nothing asserted\nthat a peer the control server marks jailed actually has its flows\ndropped, or that masquerade addresses assigned by control actually\ncarry rewritten traffic in\n[…]\n before running the packet filter, so\nthey succeed even for jailed peers.\n\nUpdates #12542\n\nChange-Id: Ia978e8d368f08a5a1117280f12bd50310969d0ec\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "tstest/natlab/vmtest: test jailed and masqueraded peers end-to-end",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-14T18:39:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0c4dcbdfebd4536c155046a7c7222c0efc8ed2e4",
"body": "Two adjacent bool arguments at call sites are easy to transpose and\nhard to read. Use an unexported bitmask type instead, per review\nfeedback on PR #20414.\n\nUpdates #cleanup\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I0417270c9c3f4b2522911c39aad375cbaf025a82",
"is_bot": false,
"headline": "ipn/ipnlocal: replace magicDNSAddrs bool params with a flags type",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-14T17:59:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3d07b5d6e121a489e7d4f3e9d20f12f58bd981f3",
"body": "The BIRD (BGP) integration previously lived half in cmd/tailscaled\n(which created a chirp client via a build-tag-gated file on some\nplatforms) and half in wgengine (which carried the client in its\nConfig and toggled the \"tailscale\" protocol as the node gained or\nlost primary subnet router duty).\n\nMo\n[…]\nn integration test, as this feature lacked much test\ncoverage previously.\n\nUpdates #12614\n\nChange-Id: I7866a50779e454c87933b358735f7dcd9e2b126f\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "wgengine,cmd/tailscaled,feature/bird: move BIRD integration to ./feature",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-14T17:48:09Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9bd62683dd5643a7de73adf093fcfa7cc5e2d63f",
"body": "This reverts commit 468a7f497323804f55c5d9f6fe2ed770dceb445e on request to @ChaosInTheCRD\n\nAlthough passing all our CI checks, @ChaosInTheCRD would like to plan manual testing as part of incorporating these updates.\n\nUpdates #cleanup\n\nChange-Id: I3f007b571b884c9538a97ac5d3ded782bcba2347\n\nSigned-off-by: Mike Jensen <mikej@tailscale.com>",
"is_bot": false,
"headline": "go.mod: revert update vulnerable dependencies (#20435) (#20456)",
"author_name": "Mike Jensen",
"author_login": "jentfoo",
"committed_at": "2026-07-14T16:26:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c9b5a918ceb4c93c85f2836307758ed67d09035d",
"body": "…d remove\n\nnoisy logs\n\nRemove most logs in mapDNSResponse() that could potentially be spammed by\na misbehaving or abusive DNS client or resolver.\n\nKeep logs, and complement with metrics, for failed rewrites, as they\nlikely point to an internal error, e.g. ip pools exhausted. Metrics\nallow for potential alerting in the future.\n\nUpdates tailscale/corp#40125\nUpdates tailscale/corp#40126\n\nSigned-off-by: Michael Ben-Ami <mzb@tailscale.com>",
"is_bot": false,
"headline": "feature/conn25: add client metrics for dns response rewrite errors an…",
"author_name": "Michael Ben-Ami",
"author_login": "mzbenami",
"committed_at": "2026-07-14T15:31:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "468a7f497323804f55c5d9f6fe2ed770dceb445e",
"body": "This change updates vulnerable dependencies with a direct fix path. Updated:\n * github.com/prometheus/prometheus@v0.311.3 - Direct dependency addressing https://pkg.go.dev/vuln/GO-2026-5710 and https://pkg.go.dev/vuln/GO-2026-5662\n * github.com/go-openapi/swag@v0.27.0 - Needed to fix mutual depend\n[…]\nwere discovered from govulncheck, which includes reachability in the analysis.\n\nUpdates #cleanup\n\nChange-Id: I8345745d22a7e6ee106b58c410889e0aef748be4\n\nSigned-off-by: Mike Jensen <mikej@tailscale.com>",
"is_bot": false,
"headline": "go.mod: update vulnerable dependencies (#20435)",
"author_name": "Mike Jensen",
"author_login": "jentfoo",
"committed_at": "2026-07-14T14:29:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8bc4c09a46dd0ea5c2710738d9177bc4cb4dc0df",
"body": "Add logic to generateFreeBSDUserData to allow for an SSH connection as\nroot for FreeBSD.\n\nAdd FreeBSD test cases to ssh_test that exercise the same paths as the\nexisting Ubuntu tests but for BSD.\n\nUpdates https://github.com/tailscale/corp/issues/44813\nUpdates https://github.com/tailscale/tailscale/issues/13038\n\nSigned-off-by: Mario Minardi <mario@tailscale.com>",
"is_bot": false,
"headline": "tstest/natlab: add FreeBSD test case for SSH test",
"author_name": "Mario Minardi",
"author_login": "mpminardi",
"committed_at": "2026-07-14T14:28:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7e609b2581077b2faa76ee5cd398dea7d9839a68",
"body": "Every netmap change, including an incremental delta of a single peer,\nrebuilt the full MagicDNS state twice: dnsConfigForNetmap walked all\npeers to build the dns.Config.Hosts map, and resolver.SetConfig then\nwalked that map again to build its reverse (PTR) index. On a tailnet\nwith 10k peers that is \n[…]\nd\nHosts map and thus from the reverse index.\n\nUpdates #12542\nUpdates tailscale/corp#43949\n\nChange-Id: I63b99199c2b3b124c08cb8bbaea1f63165095294\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal,net/dns/resolver: serve MagicDNS names from live indexes",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-14T14:26:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6a635c4e55ac026a9bf7d2d1a25e1870fb18173d",
"body": "The conn25 extension's ExtraWireGuardAllowedIPs hook (Transit IPs)\nwas only appended to wgcfg.Config.Peers in authReconfig. Now that\noutbound peer selection comes from the route manager's outbound\ntable via the engine's PeerByIPPacketFunc (which, when installed,\nreplaces wireguard-go's AllowedIPs tr\n[…]\nsn't strip the extras from active\npeers, and goes away with Config.Peers.\n\nUpdates #12542\n\nChange-Id: I06c8fa30929fbf8fe171a2d34c47c6fcc3abfa16\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal: route extra WireGuard AllowedIPs through the route manager",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-14T14:11:34Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "aff605d163b529728a056e39b1fb96bf69586838",
"body": "Engine.Reconfig previously diffed cfg.Peers disco keys against the\nprevious config to find restarted peers and flush their WireGuard\nsessions, with a TSMP-learned-key map to suppress resets for key\nchanges that arrived over a working session. That was the last\nper-peer state computed from wgcfg.Conf\n[…]\n.\n\nThis is one of the last steps toward removing Peers from wgcfg.Config.\n\nUpdates #12542\n\nChange-Id: I6b42e460f42924816beae89ca43731cb91b66054\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal,wgengine: move disco-key change detection to nodeBackend",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-14T13:32:35Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "911c5e58ed4900efd9693a5df87c594e8f8ab8f4",
"body": "Make build.go drivable and consumable by a CI builder. --json prints one\nmachine-readable result line to stdout while all logs/progress go to stderr,\nso scripts can capture data cleanly. --region (honoring $AWS_REGION, default\nus-east-1) pins import+register deterministically. AMI names derive from git:\n<app>-<tag> on a tagged commit, else <app>-<describe>-<unixtime>.\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "gokrazy: add --json output, --region pinning, git-derived AMI names",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-14T12:51:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7e62ead76e1cac3a18428b9d742d420675efaa54",
"body": "We've occasionally seen CI jobs retry broken commits for a long time\nbecause we only implement a budget per test. Add a cap to ensure we\nnever spend an unreasonable amount of time on retries.\n\nUpdates tailscale/corp#43604\n\nSigned-off-by: Tom Proctor <tomhjp@users.noreply.github.com>",
"is_bot": false,
"headline": "cmd/testwrapper: add a max retry time across all failures (#20453)",
"author_name": "Tom Proctor",
"author_login": "tomhjp",
"committed_at": "2026-07-14T12:44:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6ee7bcb4583575f8b2623bc16d55f92737465217",
"body": "…Group (#19898)\n\n* cmd/{k8s-operator,containerboot,k8s-proxy},kube: support IPv6 in egress ProxyGroup\n\n Add support for dual-stack and IPv6 clusters in egress ProxyGroup.\n Previously, egress ProxyGroup only supported IPv4: the operator and\n containerboot assumed IPv4 for ClusterIP Services, Endpo\n[…]\n IP family on dual-stack clusters.\n\nChange-Id: I35b03daf76ac817cd516e9a731770b2d85f6ee16\nSigned-off-by: Becky Pauley <becky@tailscale.com>\n\n---------\n\nSigned-off-by: Becky Pauley <becky@tailscale.com>",
"is_bot": false,
"headline": " cmd/{k8s-operator,containerboot,kube}: support IPv6 in egress Proxy…",
"author_name": "BeckyPauley",
"author_login": "BeckyPauley",
"committed_at": "2026-07-14T12:26:40Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9711883a2f27cd0c49d9a15366f80cf538a9aa97",
"body": "…s (#20376)\n\nRate-limit responses from the CA now use the Retry-After hint (via\nclient/local.RateLimitRetryAfter) instead of walking the local retry\nschedule.\n\nFailures that never reached the CA -- context deadline/cancel,\nECONNREFUSED, ECONNRESET, EHOSTUNREACH, EPIPE, and net.Error\ntimeouts -- retry at retrySchedule[0] without advancing retryCount.\n\nUpdates tailscale/corp#42164\n\nSigned-off-by: chaosinthecrd <tom@tmlabs.co.uk>",
"is_bot": false,
"headline": "kube/certs: honour Retry-After and skip escalation on transient error…",
"author_name": "Tom Meadows",
"author_login": "ChaosInTheCRD",
"committed_at": "2026-07-14T12:22:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "236564af757e2b6bce266b6278bbb203763e6be2",
"body": "…IPService delete (#20426)\n\nThe cert loop only stops when the domain leaves the ServeConfig.\nDeleting the VIPService first left the loop hammering ACME for a\ndomain the control plane no longer recognised, burning retry slots.\n\nReorder to: remove from serve config, unadvertise, delete VIPService,\nclean cert resources.\n\nUpdates #20288\n\nSigned-off-by: chaosinthecrd <tom@tmlabs.co.uk>",
"is_bot": false,
"headline": "cmd/k8s-operator: reorder Ingress cleanup so cert loop stops before V…",
"author_name": "Tom Meadows",
"author_login": "ChaosInTheCRD",
"committed_at": "2026-07-14T11:11:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "58fcaaf9a53689a93f79d379834bf5d266d9438f",
"body": "Add ConfigVAlpha.RemoteConfig so a user-data/cloud-init config can\ndelegate remote control to the tailnet admin (see Prefs.RemoteConfig).\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "ipn/conf: support RemoteConfig in the config file",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-14T08:29:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f9cd687180557b4397fdb9ceb38ea64b26078b9c",
"body": "Updates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "flake.nix: add awscli2 for building the appliance AMI",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-14T08:29:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e212b075a70e3e1d453492f729507b4ebc52ac7d",
"body": "register-image defaults to paravirtual: arm64 rejects it outright and\namd64 won't boot on Nitro. Force HVM; pick UEFI boot mode per arch.\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "gokrazy: register appliance AMIs as HVM",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-14T08:29:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5e0972344a9c1ff9b0de6f27054d83a8ca4ce710",
"body": "One AMI now self-configures from user-data or, when absent, enrolls over\nserial.\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "gokrazy: read config from EC2 user-data on the appliance",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-14T08:29:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "758c28fd41173fe0cde7c1020fd52d78b410eb82",
"body": "optional:vm:user-data boots unconfigured when the source is absent\ninstead of failing; an invalid config still fails.\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "cmd/tailscaled: allow \"optional:\" prefix on -config",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-14T08:29:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d9aeaa504b7af9bdc5ffc9d42413b8114eb92092",
"body": "Load wraps read-phase failures with it so callers can distinguish a\nmissing config from an invalid one.\n\nUpdates #1866\n\nSigned-off-by: Kristoffer Dalby <kristoffer@tailscale.com>",
"is_bot": false,
"headline": "ipn/conffile: add ErrNoConfig for absent config sources",
"author_name": "Kristoffer Dalby",
"author_login": "kradalby",
"committed_at": "2026-07-14T08:29:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "318807bdb9b96c59f2499e39028723c38df30850",
"body": "routerConfigLocked previously computed router.Config.Routes with\npeerRoutes, a from-scratch pass over cfg.Peers on every reconfig.\nThe route manager already maintains the same set incrementally (ULA\nand CGNAT coarsening included) and updateRouteManagerPrefs runs\nearlier in authReconfig, so its OS ro\n[…]\n behavior. This removes a consumer of cfg.Peers, which is on\nits way out.\n\nUpdates #12542\n\nChange-Id: I4a5b7a63d530e3fe1b70f0faf3f49def6a10be2e\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal: derive the OS routes from the route manager",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-14T02:18:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8eb18d902e593f3ef880c341feecfd3e546c14d2",
"body": "For dns.controld.com premium resolvers we synthesized per-resolver IPv6\naddresses by encoding the resolver ID into the 2606:1a40::/48 range, but\nthose are legacy plaintext-DNS (port 53) endpoints that refuse TCP :443.\nDoH now dials Control D's shared anycast IPs (the resolver ID stays in the\nURL path), fixing SERVFAIL on IPv6-only/NAT64 networks where the v4\nanycast fallback isn't reachable.\n\nFixes #20430\n\nSigned-off-by: Brendan Creane <bcreane@gmail.com>",
"is_bot": false,
"headline": "net/dns/publicdns: use Control D anycast IPs for premium DoH (#20434)",
"author_name": "Brendan Creane",
"author_login": "bcreane",
"committed_at": "2026-07-13T23:47:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "55b1a4de74d72e3c6a25f82dab1631f2060281ef",
"body": "AddReportHistoryForTest temporarily swapped out Client.TimeNow without\nholding any lock, racing with concurrent GetReport calls reading it\nfrom ReSTUN goroutines during tests. Instead, pass the current time to\naddReportHistoryAndSetPreferredDERP explicitly so the test helper never\nneeds to touch the field.\n\nFixes #20438\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I9c4f0a2f9427b5f1d3e8b06a49f0d2b71c3ee8a4",
"is_bot": false,
"headline": "net/netcheck: don't mutate Client.TimeNow in AddReportHistoryForTest",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-13T22:20:36Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b803ba048cbc055919f715cc562cd9337c011b92",
"body": "…#20431)\n\nThis commit updates the path matching logic in getServeHandler for malformed\nrequest targets like \"*\" (e.g. \"GET *\") and \"\" (e.g. \"CONNECT\" authority-form).\nThose paths never reduce to \"/\" as absolute path would. An absolute path check\nwas added and an additional check on no further reduce was added in the loop.\n\nFixes tailscale/corp#44814\n\nSigned-off-by: kevinliang10 <kevinliang@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal: update getServeHandler path handling on malformed url (…",
"author_name": "KevinLiang10",
"author_login": "KevinLiang10",
"committed_at": "2026-07-13T22:15:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9cb1147805facce7c2810bac0cabddc26dbdd237",
"body": "… Engine interface\n\nEngine.PeerForIP was pure delegation to the callback that LocalBackend\ninstalls via SetPeerForIPFunc, so external callers going through the\nengine were taking a pointless round trip: LocalBackend called\nb.e.PeerForIP, which called right back into LocalBackend, and the\nnetstack Us\n[…]\ns created, since the backend doesn't\nexist yet when netstack is wired up.\n\nUpdates #12542\n\nChange-Id: Ib1e1a4fa5c84ee0dcb9ce5d1910047f2bab9453c\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "wgengine,ipn/ipnlocal,tsnet,cmd/tailscaled: remove PeerForIP from the…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-13T22:15:16Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c436dec43c8abf7f251b40f94faebfe9ad125374",
"body": "Add TestTailscaleSSH to tstest/natlab/vmtest, exercising the Tailscale\nSSH server (tailscale up --ssh, not a system sshd) end to end: an\nUbuntu client node SSHes over the tailnet into an Ubuntu server node\nas both root and a non-root user, and into a gokrazy node.\n\nThe gokrazy sessions exercise the \n[…]\nther with a\npermissive any-principal policy.\n\nUpdates tailscale/corp#44813\nUpdates #13038\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I3f6b9c41a72e05d8c94dd7f6ab1937cf24b81c92",
"is_bot": false,
"headline": "tstest, cmd/tta: add Tailscale SSH end-to-end VM test",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-13T22:04:51Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2506ede862702a9a2405bb30a1279fe1f4d2127c",
"body": "…er route table\n\nThe engine kept its own longest-prefix-match table (peerByIPRoute),\nrebuilt from the full peer list on every reconfig, to route outbound\npackets and answer PeerKeyForIP. That's now the route manager's job:\nLocalBackend already installs a PeerByIPPacketFunc backed by the\nRouteManager\n[…]\ns trie only covers peers that already\nexist and can't lazily create them.\n\nUpdates #12542\n\nChange-Id: I25100399e273ed6c2bb1f6136b7cd81bc83e7313\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "wgengine,ipn/ipnlocal: remove Engine.PeerKeyForIP and the engine's pe…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-13T21:38:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3c800dcd71f1f8e0b2f24d175a48c2bc6576629c",
"body": "The Discover tests step runs under set -euo pipefail, so when every\nTest function in a file is filtered out by the exclude regex (as with\nvnetperf_test.go, whose TestVnetPerf* tests need special invocation),\nthe final grep -vE produces no output and exits 1, failing the whole\nstep. Tolerate empty re\n[…]\nre test\nfile containing only helpers and no Test functions.\n\nUpdates tailscale/corp#44805\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: If20c9a1de37e97b1553bd7d5559e2b876a45c19b",
"is_bot": false,
"headline": ".github/workflows: fix natlab test discovery with fully-excluded files",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-13T20:35:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f831469c27b97d47fc5f105cc71a1297d756379b",
"body": "…p deltas\n\nPreviously, any peer added or removed by an incremental netmap delta\nwas only visible to wireguard-go after a full authReconfig: wgcfg's\nReconfigDevice re-installed a PeerLookupFunc closing over a freshly\nbuilt map of every peer's allowed IPs, doing O(n) work per change.\n\nInstead, install\n[…]\null peer set. Making those\ndelta-aware is the next step before gating it.\n\nUpdates #12542\n\nChange-Id: I3ba8c7c324bca0ad0269279d03f53b1f17fb63a2\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "wgengine,ipn/ipnlocal: sync wireguard-go peers incrementally on netma…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-13T20:35:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ff1c7ef23c05214633f4c7b454f9492db2b8a1d5",
"body": "…ed per node\n\nGive nodeBackend a RouteManager and keep it in sync as routing\ninputs change: full netmaps resync the whole peer set (removals plus\nno-op-cheap upserts), incremental netmap deltas mirror their peer\nupserts and removes into the same mutation batch, and\nauthReconfigLocked pushes the rout\n[…]\nts snapshots yet; the wgengine data plane and OS\nrouter wiring come next.\n\nUpdates #12542\n\nChange-Id: I677b6b2c9efb8e41b3d27071bd9db73e01640d3b\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal,net/routemanager: keep a routemanager.RouteManager updat…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-13T17:20:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ce050f1ca1371c6b6f59172fb0d746d213a6193d",
"body": "Selecting an exit node that doesn't resolve to any current peer (a\nnonexistent node, or MDM's \"auto:any\" placeholder before it is\nresolved) installs the blackhole default routes, so internet traffic\nis dropped rather than escaping to the local network. That behavior\nis documented on ipn.Prefs.ExitNo\n[…]\nthat moves\nOS route computation to net/routemanager and must preserve it.\n\nUpdates #12542\n\nChange-Id: I0f63b0d5ce46061a74c69b75f7f83f115da7c3d4\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal: test the unresolved-exit-node blackhole routes",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-13T16:04:17Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "18a95394df769a66f1c3a915bc3fa597a554531f",
"body": "LocalBackend.Start previously shut down the previous control client in\na goroutine, letting it run concurrently with the new one. An in-flight\nlite map update carrying stale Hostinfo.RequestTags could then be\nprocessed by the control plane after the new client had already changed\nthe node's tags. Co\n[…]\nerifying that Start waits for the old client to shut down.\n\nUpdates #20365\nUpdates #18052\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: If8c8e145bdadcef1b1b8fe6209453cf5f5a8d616",
"is_bot": false,
"headline": "ipn/ipnlocal: shut down old control client before starting new one",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-13T15:28:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "505330d09f0b0c11a6fa35f6fbdbb488c03d55ec",
"body": "This reverts commit ca9f6971e542a0c2df6e756e2b28f1bde945cf89.\n\nThe dependency updates broke the K8s E2E tests. Reverting so the\nupdates can be re-landed with the tests passing.\n\nflake.nix, shell.nix, and flakehashes.json were regenerated with\ntool/updateflakes rather than reverted, since a later commit\n(6fdffd9e5) also updated them for the gowebdav bump.\n\nChange-Id: Id4afd7788d305a674841168e2a66a0009212ffd3\n\nSigned-off-by: Fernando Serboncini <fserb@tailscale.com>",
"is_bot": false,
"headline": "Revert \"go.mod: Update vulnerable dependencies (#20388)\" (#20420)",
"author_name": "Fernando Serboncini",
"author_login": "fserb",
"committed_at": "2026-07-13T14:56:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "125fd88c305b296717019bb8b9867b0973c06ec7",
"body": "FreeBSD guests downloaded their test binaries from vnet's\nfiles.tailscale VIP at roughly 250 kB/s in CI, and transfers sometimes\nwedged outright for many minutes, which is why TestSubnetRouterFreeBSD\ntimed out in about a third of its runs. Locally the same path moves\ndata at 100+ MB/s, so the proble\n[…]\nMTEST_NO_KVM=1\nforces TCG for reproducing slow-host behavior.\n\nFixes tailscale/corp#44805\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I1a7945a7e9c7d083b0ea2a3530eda0e9757dff18",
"is_bot": false,
"headline": "tstest/natlab: fix vnet TCP throughput collapse to slow guests",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-13T13:21:45Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "296f6c1f78a5a50b79b8c8d6663431f9bc483a43",
"body": "PeerByStableID did an O(n peers) scan, and an upcoming change needs\nthe same StableNodeID-to-NodeID resolution whenever prefs change (to\nresolve the selected exit node for the route manager, which keys\npeers by NodeID because that is the identity netmap delta mutations\ncarry). Maintain a nodeByStabl\n[…]\ndr and nodeByKey indexes, updated on full netmaps and on\ndelta mutations.\n\nUpdates #12542\n\nChange-Id: Id1e5105a7470b02312533f0f46b69e6945cd62f0\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal: index peers by stable node ID",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-11T19:12:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d69bf2685a3b31219b5f203b9f7d2f87a187ac3f",
"body": "Updates #cleanup\n\nSigned-off-by: Adriano Sela Aviles <adriano@tailscale.com>",
"is_bot": false,
"headline": "all: apply go fix",
"author_name": "Adriano Sela Aviles",
"author_login": "adrianosela",
"committed_at": "2026-07-11T00:39:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a5102d3fcbe7aa263c51fa689a17417b7a81d839",
"body": "Add a new RouteManager type that tracks per-peer self addresses and\nadvertised routes and incrementally maintains two read-only\nsnapshots: an IP-to-outbound-peer bart table carrying the per-peer\nattributes the data plane needs (jailed state, masquerade addresses),\nand a coarsened OS route set (inclu\n[…]\nchange that wires\nit into ipnlocal and wgengine, to make that PR smaller.\n\nUpdates #12542\n\nChange-Id: Iccc5258024e6f90311835b79fd2d83b2adb0d09d\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "net/routemanager: add incremental route manager",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-10T23:57:09Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "045c9798026ed87143d2b67a818540794c0becb3",
"body": "The guidelines here provide a written version of common guidance around\nour CLI evolution that designers/implementors should consider as they\npropose/implement new or evolving CLI surfaces.\n\nUpdates #engdocs\n\nChange-Id: Idcbc0900a4fda98bd2b29ac8bbc26dc1cb1be48f\nSigned-off-by: James Tucker <james@tailscale.com>",
"is_bot": false,
"headline": "docs: add CLI evolution guidelines",
"author_name": "James Tucker",
"author_login": "raggi",
"committed_at": "2026-07-10T21:55:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "66a51c426f736c9f602221d59b35d0d2bc9a9c2f",
"body": "Updates #cleanup\n\nSigned-off-by: Adriano Sela Aviles <adriano@tailscale.com>",
"is_bot": false,
"headline": "cmd: apply go fix",
"author_name": "Adriano Sela Aviles",
"author_login": "adrianosela",
"committed_at": "2026-07-10T21:26:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2b62cb54a701c101bbd669c92277bc88a968fbea",
"body": "Due to a customer issue, I investigated the Windows Dnscache service more\nintensively. I learned that the only time it attempts to read the NRPT\nfrom group policy is in response to a group policy change notification.\n\nUnder the hypothesis that policy refresh is not effectively delivering GP\nnotifica\n[…]\nn API.\n\nTests have been updated to ensure they check that they are running as\nLocalSystem, which is required for GenerateGPNotification.\n\nFixes #20187\n\nSigned-off-by: Aaron Klotz <aaron@tailscale.com>",
"is_bot": false,
"headline": "net/dns, util/winutil: improve detection of group policy affecting NRPT",
"author_name": "Aaron Klotz",
"author_login": "dblohm7",
"committed_at": "2026-07-10T19:53:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a68be1973974ddeb7e1f743aabbbead0e43d01f6",
"body": "A connection to a Tailscale Service IP on a port the service does\nnot serve was forwarded to the underlying host. `acceptTCP` fell through to\nthe isTailscaleIP case (a VIP is in the Tailscale IP range), which rewrote\nthe dial target to 127.0.0.1:<port> and forwardTCP'd the connection onto\nwhatever u\n[…]\nch the guard.\nLayer 3 services are unaffected: their traffic is released to the host in\ninjectInbound and never reaches acceptTCP.\n\nFixes #20362\n\nSigned-off-by: kevinliang10 <kevinliang@tailscale.com>",
"is_bot": false,
"headline": "wgengine/netstack: reject unserved ports on Service (VIP) IPs (#20363)",
"author_name": "KevinLiang10",
"author_login": "KevinLiang10",
"committed_at": "2026-07-10T18:06:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7771ce4e58029470f1198ce45df7d6a2a938c26f",
"body": "…ally\n\n[This commit is pulled out of a branch that ultimately removes the\nwgcfg.Config.Peers field and removes all O(n peers) processing when\nhandling deltas]\n\nmagicsock.Conn.UpdatePeers existed so wgengine.Reconfig could tell\nmagicsock the set of WireGuard peers from cfg.Peers, used only to\ngarbage\n[…]\nr, so do that bookkeeping there and delete the API and its\ncfg.Peers use.\n\nUpdates #12542\n\nChange-Id: Id07551fc1950239f08a73a9ab02d69ce78d0de0c\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "wgengine/magicsock: delete Conn.UpdatePeers, derive peer state intern…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-10T17:47:44Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3872880617733ca92d8d698dcc692ad0fd63e1f6",
"body": "Previously cloner only handled literal slices for values, like\n`map[string][]int`. This adds support for named types with an underlying\ntype of slice, like `map[string]IntSlice` with `type IntSlice []int`.\n\nUpdates tailscale/corp#44077\n\nSigned-off-by: Andrew Lytvynov <awly@tailscale.com>",
"is_bot": false,
"headline": "cmd/cloner: handle named slices as map values (#20387)",
"author_name": "Andrew Lytvynov",
"author_login": "awly",
"committed_at": "2026-07-10T15:56:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0e79b322a9c9782fa122b37fd2b12bcb2dd6df28",
"body": "Export the machine's boot time (the btime line from Linux's\n/proc/stat) as node_boot_time_seconds, named to match what\nPrometheus's node exporter uses for the same value. Combined with\nprocess_start_unix_time, this can be used to distinguish process\nrestarts from whole node restarts.\n\nThe value is p\n[…]\n available, so non-Linux\nsystems don't export a bogus zero.\n\nUpdates tailscale/corp#44743\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I5f53186b97bb1482bd1a5387c0910b0ae26544ff",
"is_bot": false,
"headline": "tsweb/varz: add node_boot_time_seconds expvar",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-10T15:47:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "16f600df8c1b1f66ed5de8ea89eb9056ab42d22e",
"body": "Fixes #19941\n\nChange-Id: I69e63a8036f50cfee2ed770a88f92ce344412f4d\nSigned-off-by: scientificworld <scientificworld@users.noreply.github.com>",
"is_bot": false,
"headline": "ipn/conf: add ConfigVAlpha.AdvertiseExitNode",
"author_name": "scientificworld",
"author_login": "scientificworld",
"committed_at": "2026-07-10T14:24:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6fdffd9e5e043959877732a16e08be164dad2cfa",
"body": "For https://github.com/studio-b12/gowebdav/pull/87\n\nFixes #20295\n\nChange-Id: I8ae6ff6969c84fcd510f0e15e0487fbfe9f7c821\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "go.mod: bump github.com/studio-b12/gowebdav",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-10T13:12:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b3d0ebcca3ca5b603912d6ed6f874a41615d50b4",
"body": "…d in\n\nLike the earlier RemoteConfig change, gate Hostinfo.AllowsUpdate on\nfeature.IsRegistered(\"clientupdate\") in addition to the\nbuildfeatures.HasClientUpdate build-tag const. tsnet binaries don't\nimport feature/clientupdate even though ts_omit_clientupdate isn't\nset, so they shouldn't tell contro\n[…]\nd make tsnet's dep test verify it\ndoesn't depend on feature/clientupdate.\n\nUpdates #12614\n\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>\nChange-Id: I526ef11f2a4141f5fce161b1f77263324014b5c4",
"is_bot": false,
"headline": "ipn/ipnlocal: only send AllowsUpdate if clientupdate feature is linke…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-10T02:08:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ac84eb490054032d519df69d6a855abf6fb36a8c",
"body": "The netmap.NetworkMap type is deprecated and going away, and\nreconfigAppConnectorLocked only needed its SelfNode field anyway.\nTake a tailcfg.NodeView instead and check its validity in place of\nthe old nil netmap check.\n\nUpdates #12542\n\nChange-Id: Id617845b67416404500cca438ce4ac0372cd8a8e\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "ipn/ipnlocal: pass self node view to reconfigAppConnectorLocked",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-09T22:04:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ca9f6971e542a0c2df6e756e2b28f1bde945cf89",
"body": "This change updates vulnerable dependencies with a direct fix path. Updated:\n * github.com/prometheus/prometheus@v0.311.3 - Direct dependency addressing https://pkg.go.dev/vuln/GO-2026-5710 and https://pkg.go.dev/vuln/GO-2026-5662\n * github.com/go-openapi/swag@v0.27.0 - Needed to fix mutal depende\n[…]\nainer CVEs, in total: https://pkg.go.dev/vuln/GO-2026-5758 https://pkg.go.dev/vuln/GO-2026-5475 https://pkg.go.dev/vuln/GO-2026-5378\n\nUpdates #cleanup\n\nSigned-off-by: Mike Jensen <mikej@tailscale.com>",
"is_bot": false,
"headline": "go.mod: Update vulnerable dependencies (#20388)",
"author_name": "Mike Jensen",
"author_login": "jentfoo",
"committed_at": "2026-07-09T21:52:34Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7965d496a687919ae38078f9a0428b87eaa5f854",
"body": "We had an internal Google doc about this (Tailscalars:\nhttp://go/clientmod) but that doesn't help open source contributors or\nagents.\n\nSo move the docs to git.\n\nUpdates #12614\n\nChange-Id: I0b0e9f0286b23b4fb1b51ff3d41eba75edf62cdf\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "feature: add README explaining the modular feature system",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-09T20:30:47Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "692f84df8d0ca951fbf2cd640f9d87139ed215d4",
"body": "…ture hook\n\nwgcfg.Config.NetworkLogging carried the network flow logging identity\ninside the WireGuard config, where it was unrelated to WireGuard; it\nlived there mainly so that identity changes would defeat Reconfig's\nErrNoChanges check and reach the netlog startup/shutdown logic.\n\nRemove the field\n[…]\n that removes wgcfg.Config.Peers,\nto make that PR smaller.\n\nUpdates #12542\nUpdates #12614\n\nChange-Id: I41ca7dfe43c51e977c41b5f8e934bd1f0e6e6e24\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "wgengine,wgcfg,feature/netlog: move network flow logging behind a fea…",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-09T19:56:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b7de1753b7bb6fd20801796e885243d277f8351e",
"body": "Nothing uses them. DNS and MTU are handled elsewhere.\n\nThis is pulled out of a future change that removes wgcfg.Config.Peers,\nto make that PR smaller.\n\nUpdates #12542\n\nChange-Id: I2ec8ae38dc6cce08bcc44e6c1f9177311202af89\nSigned-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>",
"is_bot": false,
"headline": "wgengine/wgcfg: remove unused Config DNS and MTU fields",
"author_name": "Brad Fitzpatrick",
"author_login": "bradfitz",
"committed_at": "2026-07-09T17:05:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "69ee776dfb9afb07affcf0477889e9cdbb697a2a",
"body": "The extension's acmeMu was a single lock around getCertPEM. Any\nin-flight ACME flow blocked every other domain. With many domains\n(ProxyGroup ingress) the queue would back up and per-call timeouts\nstarted firing while we were just waiting on the lock -- the cert\nloop treated that as a failure.\n\nRepl\n[…]\nsingle-file. Otherwise two first-time issuances for\ndifferent domains end up with separate accounts at LE.\n\nUpdates #20288\nUpdates tailscale/corp#42164\n\nSigned-off-by: chaosinthecrd <tom@tmlabs.co.uk>",
"is_bot": false,
"headline": "feature/acme: lock ACME per-domain instead of globally (#20303)",
"author_name": "Tom Meadows",
"author_login": "ChaosInTheCRD",
"committed_at": "2026-07-09T13:06:17Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "70244f40e00e01abde01ae70f3789dbbb9cb9ffa",
"body": "Bump the Go toolchain to 1.26.5.\n\nUpdates #cleanup\n\nSigned-off-by: Patrick O'Doherty <patrick@tailscale.com>",
"is_bot": false,
"headline": "go.mod: bump Go to 1.26.5",
"author_name": "Patrick O'Doherty",
"author_login": "patrickod",
"committed_at": "2026-07-09T00:15:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "63efd0693318903e13033dda4b503c75ad7aa24e",
"body": "Signed-off-by: License Updater <noreply+license-updater@tailscale.com>",
"is_bot": false,
"headline": "licenses: update license notices",
"author_name": "License Updater",
"author_login": null,
"committed_at": "2026-07-08T18:14:50Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 99,
"commits_last_year": 1659,
"latest_release_at": "2026-07-14T21:36:13Z",
"latest_release_tag": "v1.98.9",
"releases_from_tags": true,
"days_since_last_push": 5,
"active_weeks_last_year": 50,
"days_since_latest_release": 12,
"mean_days_between_releases": 7.8
},
"community": {
"has_readme": false,
"has_license": false,
"has_description": false,
"has_contributing": false,
"health_percentage": null,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "tailscale.com",
"exists": true,
"license": null,
"keywords": [],
"ecosystem": "go",
"matches_repo": null,
"registry_url": "https://pkg.go.dev/tailscale.com",
"is_deprecated": false,
"latest_version": "v1.102.0",
"repository_url": null,
"versions_count": 231,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": null,
"latest_published_at": "2026-07-23T18:54:05Z",
"latest_version_yanked": null,
"days_since_latest_publish": 3
}
]
},
"popularity": {
"forks": 0,
"stars": 0,
"watchers": 0,
"fork_history": {
"days": [],
"complete": true,
"collected": 0,
"total_forks": 0
},
"star_history": {
"days": [],
"complete": true,
"collected": 0,
"total_stars": 0,
"collected_at": null
},
"open_issues_and_prs": 0
},
"ai_readiness": {
"has_nix": true,
"example_dirs": [
"example",
"examples"
],
"has_llms_txt": false,
"has_dockerfile": true,
"has_mcp_signal": false,
"bootstrap_files": [
"Makefile",
"docs/k8s/Makefile",
"gokrazy/Makefile",
"tool/goexe/Makefile",
"tstest/tailmac/Makefile"
],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [
"client/web/tsconfig.json",
"cmd/tsconnect/tsconfig.json"
],
"toolchain_manifests": [
"go.mod",
"tool/goexe/Cargo.toml"
],
"largest_source_bytes": 311451,
"source_files_sampled": 2317,
"oversized_source_files": 29,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"go.mod"
],
"advisories": {
"error": null,
"scope": null,
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"go"
],
"dependencies": [
{
"name": "filippo.io/mkcert",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.4.4"
},
{
"name": "fyne.io/systray",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.11.1-0.20250812065214-4856ac3adc3c"
},
{
"name": "github.com/Kodeworks/golang-image-ico",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20141118225523-73f0f4cfade9"
},
{
"name": "github.com/akutz/memconn",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.1.0"
},
{
"name": "github.com/alexbrainman/sspi",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20231016080023-1a75b4708caa"
},
{
"name": "github.com/andybalholm/brotli",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.1.0"
},
{
"name": "github.com/atotto/clipboard",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.1.4"
},
{
"name": "github.com/aws/aws-sdk-go-v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.42.1"
},
{
"name": "github.com/aws/aws-sdk-go-v2/config",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.32.17"
},
{
"name": "github.com/aws/aws-sdk-go-v2/feature/s3/manager",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.17.58"
},
{
"name": "github.com/aws/aws-sdk-go-v2/service/ec2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.316.1"
},
{
"name": "github.com/aws/aws-sdk-go-v2/service/s3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.75.3"
},
{
"name": "github.com/aws/aws-sdk-go-v2/service/ssm",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.45.0"
},
{
"name": "github.com/axiomhq/hyperloglog",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20240319100328-84253e514e02"
},
{
"name": "github.com/bradfitz/go-tool-cache",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260216153636-9e5201344fe5"
},
{
"name": "github.com/bradfitz/monogok",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260630033929-b1eef977b41f"
},
{
"name": "github.com/bradfitz/qemu-guest-kragent",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20240513123539-55a43ea02a03"
},
{
"name": "github.com/bramvdbogaerde/go-scp",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.4.0"
},
{
"name": "github.com/chromedp/cdproto",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260321001828-e3e3800016bc"
},
{
"name": "github.com/chromedp/chromedp",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.15.1"
},
{
"name": "github.com/cilium/ebpf",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.16.0"
},
{
"name": "github.com/coder/websocket",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.8.14"
},
{
"name": "github.com/coreos/go-iptables",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.7.1-0.20240112124308-65c67c9f46e6"
},
{
"name": "github.com/coreos/go-systemd",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20191104093116-d3cd4ed1dbcf"
},
{
"name": "github.com/creachadair/mds",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.25.13"
},
{
"name": "github.com/creachadair/msync",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.8.1"
},
{
"name": "github.com/creachadair/taskgroup",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.13.2"
},
{
"name": "github.com/creack/pty",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.1.24"
},
{
"name": "github.com/dblohm7/wingoes",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20240119213807-a09d6be7affa"
},
{
"name": "github.com/digitalocean/go-smbios",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20180907143718-390a4f403a8e"
},
{
"name": "github.com/diskfs/go-diskfs",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.9.3"
},
{
"name": "github.com/distribution/reference",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.6.0"
},
{
"name": "github.com/djherbis/times",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.6.0"
},
{
"name": "github.com/dsnet/try",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.3"
},
{
"name": "github.com/elastic/crd-ref-docs",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.12"
},
{
"name": "github.com/evanw/esbuild",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.19.11"
},
{
"name": "github.com/fogleman/gg",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.3.0"
},
{
"name": "github.com/frankban/quicktest",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.14.6"
},
{
"name": "github.com/fxamacker/cbor/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.9.0"
},
{
"name": "github.com/gaissmai/bart",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.26.1"
},
{
"name": "github.com/go-json-experiment/json",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260214004413-d219187c3433"
},
{
"name": "github.com/go-logr/zapr",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.3.0"
},
{
"name": "github.com/go-ole/go-ole",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.3.0"
},
{
"name": "github.com/go4org/hashtriemap",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20251130024219-545ba229f689"
},
{
"name": "github.com/go4org/plan9netshell",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20250324183649-788daa080737"
},
{
"name": "github.com/godbus/dbus/v5",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v5.2.2"
},
{
"name": "github.com/gokrazy/breakglass",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20251229072214-9dbc0478d486"
},
{
"name": "github.com/gokrazy/firmware",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260522070551-527ce0ed43cf"
},
{
"name": "github.com/gokrazy/gokrazy",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260418085648-c38c3134b8a7"
},
{
"name": "github.com/gokrazy/kernel.amd64",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260705070735-de680abf072b"
},
{
"name": "github.com/gokrazy/kernel.arm64",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260705071517-37841c4d6ff1"
},
{
"name": "github.com/gokrazy/kernel.rpi",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20251127164438-9778ec0261de"
},
{
"name": "github.com/gokrazy/rpi-eeprom",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260518070910-95f7328a8228"
},
{
"name": "github.com/gokrazy/serial-busybox",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20250119153030-ac58ba7574e7"
},
{
"name": "github.com/golang/groupcache",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20241129210726-2c02b8208cf8"
},
{
"name": "github.com/golang/snappy",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.4"
},
{
"name": "github.com/golangci/golangci-lint",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.57.1"
},
{
"name": "github.com/google/go-cmp",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.7.0"
},
{
"name": "github.com/google/go-containerregistry",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.21.5"
},
{
"name": "github.com/google/go-tpm",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.9.4"
},
{
"name": "github.com/google/gopacket",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.1.19"
},
{
"name": "github.com/google/nftables",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.2.1-0.20240414091927-5e242ec57806"
},
{
"name": "github.com/google/uuid",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.6.0"
},
{
"name": "github.com/goreleaser/nfpm/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.33.1"
},
{
"name": "github.com/hashicorp/go-hclog",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.6.2"
},
{
"name": "github.com/hashicorp/raft",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.7.2"
},
{
"name": "github.com/hashicorp/raft-boltdb/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.3.1"
},
{
"name": "github.com/hdevalence/ed25519consensus",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.2.0"
},
{
"name": "github.com/huin/goupnp",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.3.0"
},
{
"name": "github.com/illarion/gonotify/v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.0.2"
},
{
"name": "github.com/inetaf/tcpproxy",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20250203165043-ded522cbd03f"
},
{
"name": "github.com/insomniacslk/dhcp",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20240129002554-15c9b8791914"
},
{
"name": "github.com/jellydator/ttlcache/v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.1.0"
},
{
"name": "github.com/jsimonetti/rtnetlink",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.4.1"
},
{
"name": "github.com/kballard/go-shellquote",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20180428030007-95032a82bc51"
},
{
"name": "github.com/kdomanski/iso9660",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.4.0"
},
{
"name": "github.com/klauspost/compress",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.18.5"
},
{
"name": "github.com/kortschak/wol",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20200729010619-da482cc4850a"
},
{
"name": "github.com/mattn/go-colorable",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.1.14"
},
{
"name": "github.com/mattn/go-isatty",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.22"
},
{
"name": "github.com/mdlayher/genetlink",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.3.2"
},
{
"name": "github.com/mdlayher/netlink",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.7.3-0.20250113171957-fbb4dce95f42"
},
{
"name": "github.com/mdlayher/sdnotify",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.0"
},
{
"name": "github.com/miekg/dns",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.1.58"
},
{
"name": "github.com/mitchellh/go-ps",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.0"
},
{
"name": "github.com/peterbourgon/ff/v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.4.0"
},
{
"name": "github.com/pires/go-proxyproto",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.8.1"
},
{
"name": "github.com/pkg/errors",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.9.1"
},
{
"name": "github.com/pkg/sftp",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.13.6"
},
{
"name": "github.com/prometheus/client_golang",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.23.2"
},
{
"name": "github.com/prometheus/common",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.69.0"
},
{
"name": "github.com/prometheus/prometheus",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.49.2-0.20240125131847-c3b8ef1694ff"
},
{
"name": "github.com/robert-nix/ansihtml",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.1"
},
{
"name": "github.com/safchain/ethtool",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.3.0"
},
{
"name": "github.com/skip2/go-qrcode",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20200617195104-da1b6568686e"
},
{
"name": "github.com/studio-b12/gowebdav",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.13.0"
},
{
"name": "github.com/tailscale/certstore",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.1.1-0.20260409135935-3638fb84b77d"
},
{
"name": "github.com/tailscale/depaware",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20251001183927-9c2ad255ef3f"
},
{
"name": "github.com/tailscale/gliderssh",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.3.4-0.20260716005906-1a0f895faf28"
},
{
"name": "github.com/tailscale/goexpect",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20210902213824-6e8c725cea41"
},
{
"name": "github.com/tailscale/golang-x-crypto",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20250404221719-a5573b049869"
},
{
"name": "github.com/tailscale/hujson",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260302212456-ecc657c15afd"
},
{
"name": "github.com/tailscale/mkctr",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260107121656-ea857e3e500b"
},
{
"name": "github.com/tailscale/netlink",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.1.1-0.20240822203006-4d49adab4de7"
},
{
"name": "github.com/tailscale/peercred",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20250107143737-35a0c7bd7edc"
},
{
"name": "github.com/tailscale/policybottest",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260626205140-6863b672b210"
},
{
"name": "github.com/tailscale/setec",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20251203133219-2ab774e4129a"
},
{
"name": "github.com/tailscale/ts-gokrazy",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260630224145-b83088f2e52e"
},
{
"name": "github.com/tailscale/web-client-prebuilt",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20250124233751-d4cd19a26976"
},
{
"name": "github.com/tailscale/wf",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20240214030419-6fbb0a674ee6"
},
{
"name": "github.com/tailscale/wireguard-go",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260715223240-2e01ba5b00f0"
},
{
"name": "github.com/tailscale/xnet",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20240729143630-8497ac4dab2e"
},
{
"name": "github.com/tc-hib/winres",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.2.1"
},
{
"name": "github.com/tcnksm/go-httpstat",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.2.0"
},
{
"name": "github.com/toqueteos/webbrowser",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.2.0"
},
{
"name": "github.com/u-root/u-root",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.14.0"
},
{
"name": "github.com/vishvananda/netns",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.5"
},
{
"name": "go.uber.org/zap",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.27.0"
},
{
"name": "go4.org/mem",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20240501181205-ae6ca9944745"
},
{
"name": "go4.org/netipx",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20231129151722-fdeea329fbba"
},
{
"name": "golang.org/x/crypto",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.54.0"
},
{
"name": "golang.org/x/exp",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260410095643-746e56fc9e2f"
},
{
"name": "golang.org/x/mod",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.37.0"
},
{
"name": "golang.org/x/net",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.56.0"
},
{
"name": "golang.org/x/oauth2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.36.0"
},
{
"name": "golang.org/x/sync",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.22.0"
},
{
"name": "golang.org/x/sys",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.47.0"
},
{
"name": "golang.org/x/term",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.45.0"
},
{
"name": "golang.org/x/time",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.15.0"
},
{
"name": "golang.org/x/tools",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.47.0"
},
{
"name": "golang.zx2c4.com/wintun",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20230126152724-0fa3db229ce2"
},
{
"name": "golang.zx2c4.com/wireguard",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260522210424-ecfc5a8d5446"
},
{
"name": "golang.zx2c4.com/wireguard/windows",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.5.3"
},
{
"name": "gopkg.in/square/go-jose.v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.6.0"
},
{
"name": "gvisor.dev/gvisor",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260224225140-573d5e7127a8"
},
{
"name": "helm.sh/helm/v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.19.0"
},
{
"name": "honnef.co/go/tools",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.7.0"
},
{
"name": "k8s.io/api",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.34.0"
},
{
"name": "k8s.io/apimachinery",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.34.0"
},
{
"name": "k8s.io/apiserver",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.34.0"
},
{
"name": "k8s.io/client-go",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.34.0"
},
{
"name": "sigs.k8s.io/controller-runtime",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.19.4"
},
{
"name": "sigs.k8s.io/controller-tools",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.17.0"
},
{
"name": "sigs.k8s.io/kind",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.30.0"
},
{
"name": "sigs.k8s.io/yaml",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.6.0"
},
{
"name": "software.sslmate.com/src/go-pkcs12",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.4.0"
},
{
"name": "tailscale.com/client/tailscale/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.9.0"
},
{
"name": "github.com/benbjohnson/immutable",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.4.3"
},
{
"name": "github.com/AlekSi/pointer",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.2.0"
},
{
"name": "github.com/aws/aws-sdk-go-v2/feature/ec2/imds",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.18.23"
},
{
"name": "github.com/aws/aws-sdk-go-v2/service/sts",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.42.1"
},
{
"name": "github.com/aws/smithy-go",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.27.3"
},
{
"name": "github.com/fatih/color",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.18.0"
},
{
"name": "github.com/fsnotify/fsnotify",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.9.0"
},
{
"name": "github.com/gorilla/csrf",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.7.3"
},
{
"name": "github.com/mdlayher/socket",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.5.0"
},
{
"name": "github.com/prometheus/client_model",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.6.2"
},
{
"name": "github.com/sourcegraph/go-diff",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.7.0"
},
{
"name": "github.com/stretchr/testify",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.11.1"
},
{
"name": "github.com/tailscale/go-winio",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20231025203758-c4f33415bf55"
},
{
"name": "github.com/ulikunitz/xz",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.5.15"
},
{
"name": "golang.org/x/image",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.41.0"
},
{
"name": "gopkg.in/yaml.v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.0.1"
},
{
"name": "k8s.io/apiextensions-apiserver",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.34.0"
},
{
"name": "k8s.io/utils",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20250604170112-4c0f3b243397"
}
],
"all_dependencies": {
"error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"source": null,
"packages": [],
"collected": false,
"truncated": false,
"total_count": null,
"direct_count": null,
"indirect_count": null
}
},
"maintainership": {
"issues": {
"open_prs": 0,
"merged_prs": 0,
"open_issues": 0,
"closed_ratio": null,
"closed_issues": 0,
"closed_unmerged_prs": 0
},
"bus_factor": 3,
"bot_contributors": 1,
"top_contributors": [
{
"type": "User",
"login": "bradfitz",
"commits": 3441,
"avatar_url": "https://avatars.githubusercontent.com/u/2621?v=4"
},
{
"type": "User",
"login": "danderson",
"commits": 881,
"avatar_url": "https://avatars.githubusercontent.com/u/1918?v=4"
},
{
"type": "User",
"login": "josharian",
"commits": 401,
"avatar_url": "https://avatars.githubusercontent.com/u/67496?v=4"
},
{
"type": "User",
"login": "raggi",
"commits": 278,
"avatar_url": "https://avatars.githubusercontent.com/u/348?v=4"
},
{
"type": "User",
"login": "andrew-d",
"commits": 267,
"avatar_url": "https://avatars.githubusercontent.com/u/1079173?v=4"
},
{
"type": "User",
"login": "jwhited",
"commits": 255,
"avatar_url": "https://avatars.githubusercontent.com/u/10344482?v=4"
},
{
"type": "User",
"login": "awly",
"commits": 214,
"avatar_url": "https://avatars.githubusercontent.com/u/1146263?v=4"
},
{
"type": "User",
"login": "irbekrm",
"commits": 208,
"avatar_url": "https://avatars.githubusercontent.com/u/24879183?v=4"
},
{
"type": "User",
"login": "dsnet",
"commits": 195,
"avatar_url": "https://avatars.githubusercontent.com/u/6354026?v=4"
},
{
"type": "User",
"login": "crawshaw",
"commits": 186,
"avatar_url": "https://avatars.githubusercontent.com/u/161319?v=4"
}
],
"contributors_sampled": 99,
"top_contributor_share": 0.367
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"checklocks.yml",
"cigocacher.yml",
"codeql-analysis.yml",
"docker-base.yml",
"docker-file-build.yml",
"flakehub-publish-tagged.yml",
"golangci-lint.yml",
"govulncheck.yml",
"installer.yml",
"kubemanifests.yaml",
"natlab-basic.yml",
"natlab-test.yml",
"pin-github-actions.yml",
"policybot-test.yml",
"request-dataplane-review.yml",
"request-k8s-review.yml",
"ssh-integrationtest.yml",
"test.yml",
"update-flake.yml",
"update-webclient-prebuilt.yml",
"vet.yml",
"webclient.yml",
"zizmor.yml"
],
"has_docs_dir": true,
"linter_configs": [
".golangci.yml"
],
"has_editorconfig": false,
"has_linter_config": true,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"Cargo.lock",
"go.sum",
"yarn.lock"
],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 6,
"reason": "binaries present in source code",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": null,
"reason": "no pull request found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 0,
"reason": "Found 0/30 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 10,
"reason": "project has 36 contributing companies or organizations",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 10,
"reason": "update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 10,
"reason": "project is fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 0,
"reason": "project was created within the last 90 days. Please review its contents carefully",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": null,
"reason": "packaging workflow not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 7,
"reason": "dependency not pinned by hash detected -- score normalized to 7",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 10,
"reason": "SAST tool detected: CodeQL",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 10,
"reason": "security policy file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": null,
"reason": "no releases found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 0,
"reason": "70 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "82cfea90ca1f3bbfd8f224d88c939f8264eb2ff1",
"ran_at": "2026-07-27T18:03:16Z",
"aggregate_score": 5.1,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": true,
"has_security_policy": true,
"has_dependabot_config": true
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": null,
"oldest_open_prs": [],
"last_merged_pr_at": null,
"ci_last_conclusion": null,
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/siteexperts/tailscale",
"host": "github.com",
"name": "tailscale",
"owner": "siteexperts"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 56,
"inputs": {
"security": 51,
"vitality": 89,
"community": 12,
"governance": 50,
"engineering": 68
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "excellent",
"name": "Vitality",
"value": 89,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "excellent",
"name": "Development activity",
"note": null,
"notes": [],
"value": 89,
"inputs": {
"commits_last_year": 1659,
"human_commit_share": 1,
"days_since_last_push": 5,
"active_weeks_last_year": 50
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 5 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 5
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "50/52 weeks with commits",
"points": 34.6,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 50
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "1659 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 1659
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 88,
"inputs": {
"releases_count": 99,
"latest_release_tag": "v1.98.9",
"releases_from_tags": true,
"days_since_latest_release": 12,
"mean_days_between_releases": 7.8
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "99 version tags (no GitHub releases)",
"points": 16.2,
"status": "partial",
"details": [
{
"code": "version_tags_no_releases",
"params": {
"count": 99
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 12 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 12
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~7.8 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 7.8
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "critical",
"name": "Community & Adoption",
"value": 12,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 1,
"inputs": {
"forks": 0,
"stars": 0,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "0 stars",
"points": 0,
"status": "missed",
"details": [
{
"code": "stars",
"params": {
"count": 0
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "0 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 0
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "0 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 0
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "critical",
"name": "Community health",
"note": null,
"notes": [],
"value": 25,
"inputs": {
"has_readme": false,
"has_license": false,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (BSD-3-Clause)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "BSD-3-Clause"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "moderate",
"name": "Sustainability & Governance",
"value": 50,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "good",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 74,
"inputs": {
"bus_factor": 3,
"contributors_sampled": 99,
"top_contributor_share": 0.367
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "3 contributor(s) cover half of all commits",
"points": 36,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 3
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 37% of commits",
"points": 14.2,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 37
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "99 contributors",
"points": 13.5,
"status": "met",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 99
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 36 contributing companies or organizations",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "critical",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): Issue resolution, PR acceptance. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"issue_resolution",
"pr_acceptance"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 1,
"inputs": {
"merged_prs": 0,
"open_issues": 0,
"closed_issues": 0,
"issue_closed_ratio": null,
"closed_unmerged_prs": 0
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "no issues or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_issues_or_data",
"params": {}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "no decided pull requests or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_decided_prs_or_data",
"params": {}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "at_risk",
"name": "Ownership & stewardship",
"note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"verified_domain"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 30,
"inputs": {
"followers": 0,
"owner_type": "User",
"is_verified": null,
"owner_login": "siteexperts",
"public_repos": 1,
"account_age_days": 3594
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "personal (user) account",
"points": 10,
"status": "partial",
"details": [
{
"code": "owner_personal",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": "not applicable to user accounts",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_applicable_to_user_accounts",
"params": {}
}
],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "0 followers of siteexperts",
"points": 0,
"status": "missed",
"details": [
{
"code": "owner_followers",
"params": {
"count": 0,
"login": "siteexperts"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "1 public repos, account ~9 yr old",
"points": 14.2,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 1
}
},
{
"code": "account_age_years",
"params": {
"years": 9
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"tailscale.com"
],
"ecosystems": "go",
"any_deprecated": false,
"min_days_since_publish": 3
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "1 package(s) on go",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 1,
"ecosystems": "go"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 3 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 3
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "231 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 231
}
}
],
"max_points": 20
},
{
"key": "not_deprecated",
"name": "Not deprecated",
"detail": "active, not deprecated or yanked",
"points": 20,
"status": "met",
"details": [
{
"code": "package_not_deprecated",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "moderate",
"name": "Engineering Quality",
"value": 68,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "good",
"name": "Engineering practices",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 80,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": true,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "23 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 23
}
}
],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": ".golangci.yml",
"points": 16,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".golangci.yml"
}
}
],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "moderate",
"name": "Documentation",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"topics": [],
"has_wiki": true,
"homepage": "https://tailscale.com",
"has_readme": false,
"has_docs_dir": true,
"has_description": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 30
},
{
"key": "documentation_directory",
"name": "Documentation directory",
"detail": null,
"points": 25,
"status": "met",
"details": [],
"max_points": 25
},
{
"key": "documentation_homepage_site",
"name": "Documentation / homepage site",
"detail": "https://tailscale.com",
"points": 15,
"status": "met",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "moderate",
"name": "Security",
"value": 51,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "moderate",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): CI-Tests, Packaging, Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"ci_tests",
"packaging",
"signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 51,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 15,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 3,
"scorecard_aggregate": 5.1
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "binaries present in source code",
"points": 4.5,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 36 contributing companies or organizations",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "update tool detected",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is fuzzed",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "project was created within the last 90 days. Please review its contents carefully",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow not detected",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 7",
"points": 3.5,
"status": "partial",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool detected: CodeQL",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "70 existing vulnerabilities detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "high_risk_jurisdiction_exposure",
"band": "excellent",
"name": "High-Risk Jurisdiction Exposure",
"note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
"notes": [
{
"code": "jurisdiction_evidence_limits",
"params": {}
}
],
"value": 100,
"inputs": {
"meaning": "self-published location evidence; not nationality or citizenship",
"red_flag": false,
"exposures": [],
"policy_countries": [
"Russia",
"Iran",
"North Korea"
],
"review_only_matches": 0,
"assessed_self_published_locations": 18
},
"components": [
{
"key": "policy_exposure_multiplier",
"name": "Policy exposure multiplier",
"detail": "no confirmed policy-scope location match",
"points": 100,
"status": "met",
"details": [
{
"code": "jurisdiction_no_match",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "moderate",
"name": "AI Readiness",
"value": 66,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "at_risk",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.96,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "no CLAUDE.md / AGENTS.md / editor rules",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_instructions",
"params": {}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "96 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 96,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "good",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 84,
"inputs": {
"has_nix": true,
"has_tests": true,
"lockfiles": [
"Cargo.lock",
"go.sum",
"yarn.lock"
],
"has_dockerfile": true,
"typed_language": true,
"bootstrap_files": [
"Makefile",
"docs/k8s/Makefile",
"gokrazy/Makefile",
"tool/goexe/Makefile",
"tstest/tailmac/Makefile"
],
"has_devcontainer": false,
"has_linter_config": true,
"typecheck_configs": [
"client/web/tsconfig.json",
"cmd/tsconnect/tsconfig.json"
],
"agent_commit_share": 0,
"toolchain_manifests": [
"go.mod",
"tool/goexe/Cargo.toml"
],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": "Makefile, docs/k8s/Makefile, gokrazy/Makefile, tool/goexe/Makefile, tstest/tailmac/Makefile",
"points": 18,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Makefile, docs/k8s/Makefile, gokrazy/Makefile, tool/goexe/Makefile, tstest/tailmac/Makefile"
}
}
],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": ".golangci.yml",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".golangci.yml"
}
}
],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": "client/web/tsconfig.json, cmd/tsconnect/tsconfig.json",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "client/web/tsconfig.json, cmd/tsconnect/tsconfig.json"
}
}
],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "Dockerfile, Nix, lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Dockerfile, Nix, lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "no agent-authored commits among the last 100",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_authored_commits",
"params": {
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "dependency automation configured, none observed in the sampled commits",
"points": 5,
"status": "partial",
"details": [
{
"code": "dependency_bot_config_only",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 7",
"points": 7,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 99,
"inputs": {
"primary_language": "Go",
"largest_source_bytes": 311451,
"source_files_sampled": 2317,
"oversized_source_files": 29
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Go (statically typed)",
"points": 45,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "Go"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "29/2317 source files over 60KB",
"points": 54.3,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 2317,
"oversized": 29
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "at_risk",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"example_dirs": [
"example",
"examples"
],
"has_mcp_signal": false,
"api_schema_files": []
},
"components": [
{
"key": "api_schema_openapi_graphql_proto",
"name": "API schema (OpenAPI/GraphQL/proto)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 40
},
{
"key": "mcp_server",
"name": "MCP server",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "runnable_examples",
"name": "Runnable examples",
"detail": "example, examples",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "example, examples"
}
}
],
"max_points": 40
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"Community profile unavailable",
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
],
"report_type": "repository",
"generated_at": "2026-07-27T18:03:37.959438Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/s/siteexperts/tailscale.svg",
"full_name": "siteexperts/tailscale",
"license_state": "standard",
"license_spdx": "BSD-3-Clause"
}