Status: Defense Layer 3 (Approval Gates) requires external implementation.
Impact (Control Plane Gateway):
- High-risk operations (
install_package,update_docker_container,update_system_packages, etc.) are DENIED by default across all targets - Setting
SYSTEMMANAGER_ENABLE_APPROVAL=truewithout a webhook will block all approval-required operations on all managed systems - The gateway middleware will return an error:
"Approval webhook not configured" - Target-specific approval constraints in
targets.yamlwill be enforced
Workaround Options (Gateway Architecture):
-
Disable Approval Requirement (Not Recommended)
# In gateway environment configuration SYSTEMMANAGER_ENABLE_APPROVAL=falseThis removes Layer 3 defense entirely across all targets. Only do this if you:
- Fully trust all token holders
- Have comprehensive audit logging enabled on the gateway
- Monitor gateway logs actively for suspicious activity
- Use target-specific capability restrictions in
targets.yaml
-
Implement External Approval Webhook
# In gateway environment configuration SYSTEMMANAGER_ENABLE_APPROVAL=true SYSTEMMANAGER_APPROVAL_WEBHOOK=https://your-approval-service.ts.net/approveYour webhook must handle gateway-specific context:
- Accept POST requests with JSON body:
{ "tool": "install_package", "args": {"package_name": "nginx"}, "target": "web-server-01", "user": "user@tailnet.ts.net", "risk_level": "CRITICAL", "gateway_id": "gateway-001" } - Return HTTP 200 with
{"approved": true}or{"approved": false, "reason": "..."} - Implement your own approval logic (Slack notifications, PagerDuty, etc.)
- Consider target-specific approval policies
- Accept POST requests with JSON body:
-
Use Target-Specific Capability Restrictions
# In targets.yaml - restrict capabilities per target targets: production-web: id: "production-web" capabilities: - "system:read" - "container:read" # No write capabilities for production development-web: id: "development-web" capabilities: - "system:read" - "system:write" - "container:read" - "container:write" # Allow write operations in development
-
Use Scopes to Restrict Access
# Mint tokens without dangerous scopes python scripts/mint_token.py \ --agent "monitoring-agent" \ --scopes "system:read,container:read,network:diag" \ --ttl 30d
This prevents the token from calling high-risk operations entirely.
Future Plans:
- Built-in approval UI (web-based)
- Slack/Discord approval bot templates
- Time-based auto-approval windows
TailOpsMCP serves plain HTTP on port 8080.
Safe Deployments:
- ✅ Inside Tailscale network (encrypted WireGuard tunnel)
- ✅ Behind TLS-terminating reverse proxy (nginx, Caddy, Traefik)
- ✅ Localhost-only access (
127.0.0.1:8080)
Unsafe Deployments:
- ❌ Exposed to public internet
- ❌ Port forwarded through firewall
- ❌ On untrusted LANs
- ❌ Mixed Tailscale + non-Tailscale clients
Why This Matters:
- Bearer tokens are sent in HTTP
Authorizationheaders - Without TLS, tokens can be intercepted via:
- Network sniffing (MITM attacks)
- Compromised routers/switches
- Malicious devices on the same network
Mitigation:
-
Use Tailscale (recommended) - provides transparent encryption
-
Deploy Reverse Proxy:
# nginx example server { listen 443 ssl; server_name tailopsmcp.example.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
-
Never expose port 8080 directly
Older versions ran as root user:
[Service]
User=root
Group=rootRisk: If compromised, attacker has full system access.
Now runs as dedicated systemmanager user:
[Service]
User=systemmanager
Group=systemmanagerBenefits:
- Limited blast radius - attacker only gets
systemmanageruser privileges - Docker access via group membership (not root)
- Cannot modify system files outside
/var/lib/systemmanager - Additional systemd sandboxing (ProtectSystem, ProtectHome, etc.)
If you installed before this change, update manually:
# 1. Create systemmanager user
sudo useradd --system --no-create-home --shell /usr/sbin/nologin systemmanager
sudo usermod -aG docker systemmanager
# 2. Fix ownership
sudo chown -R systemmanager:systemmanager /opt/systemmanager
sudo chown -R systemmanager:systemmanager /var/lib/systemmanager
sudo chmod 600 /opt/systemmanager/.env
# 3. Update systemd service
sudo nano /etc/systemd/system/systemmanager-mcp.service
# Change User=root to User=systemmanager
# Change Group=root to Group=systemmanager
# Remove /opt/systemmanager from ReadWritePaths
# 4. Reload and restart
sudo systemctl daemon-reload
sudo systemctl restart systemmanager-mcp
# 5. Verify
sudo systemctl status systemmanager-mcp
sudo journalctl -u systemmanager-mcp -n 50The installer:
- Queries GitHub API for latest release tag
- Clones
masterbranch (not the release tag) - Fetches and executes
get.docker.comwithout verification - Fetches and executes
ct/build.funcwithout verification
Risks:
- If GitHub is compromised, malicious code could be injected
- If
get.docker.comis compromised, Docker installation is malicious - Reproducibility issues (master != tagged release)
For Users:
-
Review scripts before piping to bash:
curl -fsSL https://raw.githubusercontent.com/mdlmarkham/TailOpsMCP/master/install.sh > install.sh less install.sh # Review sudo bash install.sh
-
Pin to specific release:
git clone --branch v1.0.0 https://github.com/mdlmarkham/TailOpsMCP.git cd TailOpsMCP sudo bash install.sh -
Verify Docker installation separately:
# Install Docker via package manager instead sudo apt-get install docker.io
For Project (Future):
- Sign releases with GPG
- Verify signatures in installer
- Pin Docker installation to specific version
- Provide checksums for release artifacts
- Clone specific release tag instead of master
- Tool invocations
- User identity (if using TSIDP)
- Scopes used
- Timestamps
- Approval webhook responses
- Token generation events
- Failed authentication attempts
- Rate limiting events
- Session duration
Enable systemd journal forwarding to SIEM:
# Forward to syslog
sudo apt-get install rsyslog
sudo systemctl enable rsyslog
# Or to Loki/Grafana
# Install promtail and configure journal inputMonitor for suspicious patterns:
# High-frequency tool calls
journalctl -u systemmanager-mcp -o json | jq '.MESSAGE' | sort | uniq -c | sort -rn
# Calls to high-risk tools
journalctl -u systemmanager-mcp | grep -E "install_package|update_docker_container|update_system_packages"If you discover a security vulnerability:
- Do NOT open a public GitHub issue
- Email: [your-security-email@example.com]
- Include:
- Description of vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
- Allow 90 days for patch before public disclosure
We will:
- Acknowledge within 48 hours
- Provide status updates every 7 days
- Credit you in security advisory (if desired)
- Issue CVE if applicable
Before deploying to production:
- Running inside Tailscale network (or behind TLS proxy)
- Authentication enabled (
SYSTEMMANAGER_REQUIRE_AUTH=true) - Using TSIDP OIDC (not token-based auth)
- Systemd service runs as
systemmanageruser (not root) - All tokens have expiry dates (
--ttlor--expiry) - High-risk scopes restricted to trusted users only
- Audit logs forwarded to SIEM
- Tailscale ACLs limit access to tagged devices
- Approval webhook implemented (or approval disabled with risk acceptance)
- Regular security updates applied
- Monitoring alerts configured for suspicious activity
Last Updated: 2025-01-16 Applies to: TailOpsMCP v1.0+