DEV Community

Cover image for Quantifying the "Vague Anxiety" of Tailscale: tailsnitch Exposes 50 Configuration Mistakes
tumf
tumf

Posted on • Originally published at blog.tumf.dev

Quantifying the "Vague Anxiety" of Tailscale: tailsnitch Exposes 50 Configuration Mistakes

Originally published on 2026-01-07
Original article (Japanese): Tailscaleの『なんとなく不安』を数値化する:tailsnitchが暴く50の設定ミス

In September 2025, Asahi Group Holdings suffered a ransomware attack. The entry point was a vulnerability in their VPN device. In October, Askul was breached through a VPN account of a contracted service provider, leading to the shutdown of their e-commerce site.

Both incidents were the result of the misconception that "as long as we have a VPN, we are safe."

If you have implemented Tailscale, you might be thinking, "It should be safer than traditional VPNs, so I'm fine."

Indeed, Tailscale has advantages over traditional on-premises VPN gateways. With lightweight and audited encryption via WireGuard, device-level zero-trust authentication, and a SaaS architecture that eliminates the risk of exploiting VPN device vulnerabilities—these designs address the weaknesses of traditional VPNs.

However, Tailscale can also be dangerous if misconfigured. Leaving default ACLs unchecked can allow unrestricted access to all devices, and if reusable authentication keys are leaked, attackers can add unauthorized devices. tailsnitch is a security auditing tool that quantifies such "vague anxiety" with over 50 checks, evaluating them on a scale of Critical/High/Medium/Low/Info.

In this article, we will explain how to use tailsnitch and the dangerous configuration mistakes it can detect.

What is tailsnitch?

tailsnitch is an open-source tool that automatically audits the configuration of a Tailscale network (tailnet). Released on December 24, 2025, it garnered over 430 GitHub Stars in just two weeks.

Key features:

  • Over 50 security checks: 7 categories including ACLs, authentication keys, devices, network exposure, SSH, logs, and DNS
  • Severity rating in 5 levels: Critical → High → Medium → Low → Info
  • SOC 2 audit trail output: CSV/JSON output mapped to controls like CC6.1, CC6.2
  • CI/CD integration: Automatic checks during PRs with GitHub Actions
  • Interactive remediation mode: Fix configuration mistakes with the --fix flag

Developed by the security company Adversis, a Tailscale Hardening Guide is also available.

Installation

You can install tailsnitch using one of the following methods.

Prebuilt Binary (Recommended)

Download the latest version from GitHub Releases:

# Remove quarantine attribute for macOS
sudo xattr -rd com.apple.quarantine tailsnitch
chmod +x tailsnitch
sudo mv tailsnitch /usr/local/bin/
Enter fullscreen mode Exit fullscreen mode

Install with Go

go install github.com/Adversis/tailsnitch@latest
Enter fullscreen mode Exit fullscreen mode

Build from Source

git clone https://github.com/Adversis/tailsnitch.git
cd tailsnitch
go build -o tailsnitch .
Enter fullscreen mode Exit fullscreen mode

Authentication Setup

tailsnitch uses the Tailscale API, so you need authentication credentials. You can use either an OAuth Client (recommended) or an API Key.

OAuth Client (Recommended)

The OAuth Client allows you to restrict permissions with scopes and is logged in the audit logs. There is no risk of API keys being invalidated when employees leave.

  1. Create an OAuth Client at https://login.tailscale.com/admin/settings/oauth
  2. Grant the following scopes for read-only auditing:

    • all:read (the easiest)
    • Or individually: policy_file:read, devices:core:read, dns:read, auth_keys:read
  3. Set the environment variables:

export TS_OAUTH_CLIENT_ID="..."
export TS_OAUTH_CLIENT_SECRET="tskey-client-..."
Enter fullscreen mode Exit fullscreen mode

API Key

The API Key inherits the permissions of the user who created it.

  1. Create an API Key at https://login.tailscale.com/admin/settings/keys
  2. Set the environment variable:
export TSKEY="tskey-api-..."
Enter fullscreen mode Exit fullscreen mode

Basic Usage

Audit All Items

tailsnitch
Enter fullscreen mode Exit fullscreen mode

Example of the first run:

+=====================================================================+
|                    TAILSNITCH SECURITY AUDIT                        |
|            Tailnet: example.com                                     |
|            Version: 1.4.0 (build: d717661)                          |
+=====================================================================+

=== ACCESS CONTROLS ===================================================

[CRITICAL] ACL-001: Default 'allow all' policy active
  Your ACL policy omits the 'acls' field. Tailscale applies a
  default 'allow all' policy, granting all devices full access.

  Remediation:
  Define explicit ACL rules following least privilege principle.

  Source: https://tailscale.com/kb/1192/acl-samples
----------------------------------------------------------------------

[HIGH] AUTH-001: Reusable auth keys exist
  Found 2 reusable auth key(s). These can be reused to add
  multiple devices if compromised.

  Details:
    - Key tskey-auth-xxx (expires in 45 days)
    - Key tskey-auth-yyy (expires in 89 days)

  Remediation:
  Store reusable keys in a secrets manager. Prefer one-off keys.
----------------------------------------------------------------------

SUMMARY
======================================================================
  Critical: 1  High: 3  Medium: 5  Low: 2  Info: 8
  Total findings: 19  |  Passed: 33
Enter fullscreen mode Exit fullscreen mode

Filter by Severity

# Show only Critical/High
tailsnitch --severity high

# Specific categories only
tailsnitch --category access   # ACL issues
tailsnitch --category auth     # Authentication key issues
tailsnitch --category device   # Device security
Enter fullscreen mode Exit fullscreen mode

JSON Output and Aggregation with jq

# Output all results in JSON
tailsnitch --json > audit.json

# Extract only failed checks
tailsnitch --json | jq -r '
  .suggestions
  | map(select(.pass == false))
  | .[]
  | [.id, .title, .severity, .remediation]
  | @tsv
' > findings.tsv

# Aggregate by severity
tailsnitch --json | jq '
  .suggestions
  | map(select(.pass == false))
  | group_by(.severity)
  | map({severity: .[0].severity, count: length})
'
Enter fullscreen mode Exit fullscreen mode

Example output:

[
  {"severity": "CRITICAL", "count": 1},
  {"severity": "HIGH", "count": 3},
  {"severity": "MEDIUM", "count": 5}
]
Enter fullscreen mode Exit fullscreen mode

Dangerous Configuration Mistakes Detected

Here are some representative issues that tailsnitch can detect.

Critical: Leaving Default ACLs Unchecked

Issue: If the ACL policy lacks the acls field, Tailscale applies a default 'allow all' policy, granting all devices full access.

[CRITICAL] ACL-001: Default 'allow all' policy active
Enter fullscreen mode Exit fullscreen mode

Impact:

  • Unlimited access from a developer's laptop to the production database
  • A single compromised device puts the entire tailnet at risk

Remediation:

Define minimal ACLs:

{
  "groups": {
    "group:engineering": ["alice@company.com"],
    "group:devops": ["charlie@company.com"]
  },
  "tagOwners": {
    "tag:dev": ["autogroup:admin"],
    "tag:prod": ["autogroup:admin"]
  },
  "acls": [
    {
      "action": "accept",
      "src": ["group:engineering"],
      "dst": ["tag:dev:443", "tag:dev:8080"]
    },
    {
      "action": "accept",
      "src": ["group:devops"],
      "dst": ["tag:prod:22", "tag:prod:443"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

High: Reusable Authentication Keys Exist

Issue: If reusable authentication keys are leaked, attackers can add devices without restriction.

[HIGH] AUTH-001: Reusable auth keys exist
  Found 2 reusable auth key(s):
    - Key tskey-auth-xxx (expires in 45 days)
Enter fullscreen mode Exit fullscreen mode

Impact:

  • Breach through an authentication key committed to a GitHub repository
  • Unauthorized device addition with keys stolen from a CI/CD pipeline

Remediation:

  1. Delete existing reusable keys
  2. Switch to ephemeral (temporary) keys:
# Generate an ephemeral key (usable once)
tailscale up --authkey tskey-auth-xxx --ephemeral
Enter fullscreen mode Exit fullscreen mode
  1. Use OAuth Client in CI/CD

High: Tailnet Lock Disabled

Issue: If Tailnet Lock is disabled, an attacker can add unauthorized devices if the Tailscale coordination server is compromised.

[HIGH] DEV-010: Tailnet Lock disabled
Enter fullscreen mode Exit fullscreen mode

Impact:

  • Trust in the control plane is required
  • Risk of man-in-the-middle attacks by advanced attackers

Remediation:

Enable Tailnet Lock (requires a signing node):

# Initialize lock on a trusted node
tailscale lock init tlpub:<SIGNING_NODE_KEY>

# New devices will require signing
tailscale lock sign nodekey:<NEW_NODE_KEY>
Enter fullscreen mode Exit fullscreen mode

Note: Tailnet Lock can impose operational burdens, hence it is suited for defense industries or companies with strict compliance requirements.

Medium: Outdated Clients Detected

Issue: Older Tailscale clients may have known vulnerabilities.

[MEDIUM] DEV-003: Outdated clients detected
  Found 3 devices running Tailscale < 1.50.0
Enter fullscreen mode Exit fullscreen mode

Remediation:

Enforce version checks with Device Posture:

{
  "postures": {
    "posture:baseline": [
      "node:tsVersion >= '1.50.0'"
    ]
  },
  "acls": [
    {
      "action": "accept",
      "src": ["group:devops"],
      "srcPosture": ["posture:baseline"],
      "dst": ["tag:prod:22"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Medium: Stale Devices Detected

Issue: Devices that have not been used for over 60 days pose a risk of being compromised if they belong to former employees.

[MEDIUM] DEV-004: Stale devices detected
  Found 5 devices not seen in 60+ days
Enter fullscreen mode Exit fullscreen mode

Remediation:

Interactively delete with --fix mode:

tailsnitch --fix
Enter fullscreen mode Exit fullscreen mode

Or delete manually:

tailscale logout --device <device-id>
Enter fullscreen mode Exit fullscreen mode

Interactive Remediation Mode (--fix)

Using the --fix flag allows you to interactively correct issues that can be fixed via the API.

tailsnitch --fix
Enter fullscreen mode Exit fullscreen mode

Fixable items include:

Check Remediation
AUTH-001, AUTH-002, AUTH-003 Delete authentication keys
AUTH-004 Replace with ephemeral keys
DEV-002 Remove tags from user devices
DEV-004 Delete stale devices
DEV-005 Approve unauthorized devices

For items requiring manual intervention, links to the management console will be displayed.

Dry Run (preview changes):

tailsnitch --fix --dry-run
Enter fullscreen mode Exit fullscreen mode

SOC 2 Audit Trail Output

tailsnitch can output the necessary audit trails for SOC 2 in CSV/JSON format.

# CSV format
tailsnitch --soc2 csv > soc2-evidence.csv

# JSON format
tailsnitch --soc2 json > soc2-evidence.json
Enter fullscreen mode Exit fullscreen mode

Example output (CSV):

resource_type,resource_id,resource_name,check_id,check_title,cc_codes,status,details,tested_at
device,node123,prod-server,DEV-001,Tagged devices with key expiry disabled,CC6.1;CC6.3,PASS,Tags: [tag:server] key expiry enabled,2025-01-05T10:30:00Z
key,tskey-auth-xxx,tskey-auth-xxx,AUTH-001,Reusable auth keys exist,CC6.1;CC6.2;CC6.3,FAIL,Reusable key expires in 45 days,2025-01-05T10:30:00Z
Enter fullscreen mode Exit fullscreen mode

Each check is mapped to the following SOC 2 controls (CC):

  • CC6.1: Logical Access Controls
  • CC6.2: Granting Access Rights
  • CC6.3: Removing Access Rights
  • CC6.6: Network Segmentation
  • CC7.1: Detection of Security Events
  • CC7.2: Monitoring Security Incidents

Automated Auditing in CI/CD Pipeline

Example of running automatic checks during ACL changes with GitHub Actions:

# .github/workflows/tailscale-acl.yml
name: Tailscale ACL CI
on:
  pull_request:
    paths: ['policy.hujson']
  push:
    branches: [main]
    paths: ['policy.hujson']

jobs:
  test-acl:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run tailsnitch
        env:
          TS_OAUTH_CLIENT_ID: ${{ secrets.TS_OAUTH_CLIENT_ID }}
          TS_OAUTH_CLIENT_SECRET: ${{ secrets.TS_OAUTH_CLIENT_SECRET }}
        run: |
          curl -L https://github.com/Adversis/tailsnitch/releases/latest/download/tailsnitch-linux-amd64 -o tailsnitch
          chmod +x tailsnitch
          ./tailsnitch --severity high --json > audit.json

      - name: Fail on critical issues
        run: |
          if ./tailsnitch --severity high --json | jq -e '.summary.critical + .summary.high > 0' > /dev/null; then
            echo "Critical or high severity issues found!"
            ./tailsnitch --severity high
            exit 1
          fi
Enter fullscreen mode Exit fullscreen mode

With this configuration, security checks will automatically run on PRs for ACL changes, blocking merges if Critical/High issues are found.

Preventing Configuration Mistakes with ACL Tests

While tailsnitch is a detection tool, adding a tests field within your ACLs can help prevent configuration mistakes from occurring in the first place.

{
  "acls": [
    {
      "action": "accept",
      "src": ["group:engineering"],
      "dst": ["tag:dev:443"]
    }
  ],
  "tests": [
    {
      "src": "group:engineering",
      "deny": ["tag:prod:*", "tag:prod-db:5432"]
    },
    {
      "src": "group:devops",
      "accept": ["tag:bastion:22"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

If tests fail, ACL changes will be rejected. This helps prevent configuration mistakes before they are detected by tailsnitch.

Common Pitfalls

The Danger of autogroup:member

autogroup:member includes all users participating in the tailnet. Since it also includes external users (Shared Nodes), it can unintentionally grant access rights.

Bad Example:

{
  "acls": [
    {
      "action": "accept",
      "src": ["autogroup:member"],
      "dst": ["tag:staging:*"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Good Example:

{
  "acls": [
    {
      "action": "accept",
      "src": ["group:engineering"],
      "dst": ["tag:staging:443"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Overreliance on Subnet Routers

While Subnet Routers are convenient, if compromised, they can provide access to a wide range of networks.

Mitigation:

  1. Enable Stateful Filtering:
tailscale up --advertise-routes=10.0.0.0/24 --stateful-filtering
Enter fullscreen mode Exit fullscreen mode
  1. Protect the Subnet Router itself with security groups or NACLs.

The Trap of SSH autogroup:nonroot

autogroup:nonroot allows SSH access for all users except root, but it also includes users with sudo privileges.

Bad Example:

{
  "ssh": [
    {
      "action": "accept",
      "src": ["group:engineering"],
      "dst": ["tag:prod"],
      "users": ["autogroup:nonroot"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Good Example:

{
  "ssh": [
    {
      "action": "accept",
      "src": ["group:devops"],
      "dst": ["tag:prod"],
      "users": ["deploy"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Regular Audit Operations

Here are operational guidelines for continuously utilizing tailsnitch.

Weekly

  • [ ] Run tailsnitch to check for Critical/High issues
  • [ ] Review the device approval queue
  • [ ] Remove unused authentication keys

Monthly

  • [ ] Cross-check group memberships with the employee roster
  • [ ] Ensure devices of former employees have been removed
  • [ ] Review ACL change history

Quarterly

  • [ ] Audit all access rights (who can access what)
  • [ ] Review third-party access
  • [ ] Reassess Subnet Router configurations

Upon Employee Departure (Immediately)

  • [ ] Remove from Tailscale groups
  • [ ] Delete user from tailnet
  • [ ] Remove created authentication keys
  • [ ] Delete devices
  • [ ] Audit recent ACL changes

Conclusion

While Tailscale addresses many weaknesses of traditional VPNs at the design level, risks from configuration mistakes still exist. By using tailsnitch, you can visualize "vague anxiety" as concrete issues and prioritize addressing them.

Setup takes just five minutes, and integrating it into your CI/CD pipeline allows for automatic checks with every ACL change. You can also output audit trails for SOC 2 compliance.

Personally, I believe that every organization using Tailscale should run tailsnitch at least once a month. Do not leave Critical/High issues unaddressed until they reach zero, and add ACL tests to prevent recurrence—by thoroughly implementing these two practices, you can significantly reduce the risk of large-scale incidents from VPN breaches.

If you're interested, try running tailsnitch on your own tailnet. You might discover unexpected configuration mistakes.

Reference Links

Top comments (0)