Skip to content

Security & Privacy: auth_mode, allow_lan_access, and the "Don't Leak Account Info" Design

When you use Antigravity Tools as a "local AI gateway," security concerns usually boil down to just two things: who you're exposing the service to (only this machine, or the entire LAN/public network), and whether external requests need to carry an API Key. This lesson explains the rules in the source code clearly and gives you a minimum security baseline you can follow directly.

What You'll Learn

  • Choose the right allow_lan_access: know how it affects the bind address (127.0.0.1 vs 0.0.0.0)
  • Choose the right auth_mode: understand the actual behavior of off/strict/all_except_health/auto
  • Configure api_key and verify: use curl to instantly see "whether authentication is actually enabled"
  • Know the boundaries of privacy protection: local proxy keys are not forwarded upstream; avoid leaking account emails in error messages to API clients

Your Current Struggles

  • You want your phone/another computer to access, but worry that enabling LAN access means "going naked"
  • You want to enable authentication, but aren't sure whether /healthz should be exempt, afraid you'll break health checks
  • You're worried about leaking local keys, cookies, or account emails to external clients or upstream platforms

When to Use This

  • You're about to enable allow_lan_access (NAS, home LAN, team intranet)
  • You're using cloudflared/reverse proxy to expose the local service to the public (first see Cloudflared One-Click Tunnel)
  • You encounter 401 and need to confirm whether it's "missing key" or "mode mismatch"

🎒 Preparation

Prerequisites

Three fields that will appear repeatedly in this lesson

  • allow_lan_access: whether to allow LAN access.
  • auth_mode: authentication strategy (determines which routes must carry a key).
  • api_key: the local proxy's API Key (only used for local proxy authentication, not forwarded upstream).

What is auth_mode?

auth_mode is Antigravity Tools' "proxy authentication switch + exemption strategy." It decides, when external clients access local proxy endpoints, which requests must carry proxy.api_key, and whether health check routes like /healthz allow access without authentication.

Core Approach

  1. First determine the "exposure surface": when allow_lan_access=false, listen only on 127.0.0.1; when true, listen on 0.0.0.0.
  2. Then determine the "entry key": auth_mode decides whether a key is required, and whether /healthz is exempt.
  3. Finally do "privacy containment": don't forward local proxy keys/cookies upstream; try to avoid including account emails in external error messages.

Follow Along

Step 1: First decide whether you need LAN access (allow_lan_access)

Why You should only enable LAN access when you "need other devices to access"—otherwise, defaulting to local-only access is the simplest security strategy.

In ProxyConfig, the bind address is determined by allow_lan_access:

rust
pub fn get_bind_address(&self) -> &str {
    if self.allow_lan_access {
        "0.0.0.0"
    } else {
        "127.0.0.1"
    }
}

In the GUI's API Proxy page, set the "Allow LAN access" toggle according to your needs.

What you should see

  • When off: the prompt indicates "local-only access" semantics (specific text depends on language pack)
  • When on: the interface shows a prominent risk warning (reminding you this is an "expanded exposure surface")

Step 2: Choose an auth_mode (recommend auto first)

Whyauth_mode isn't just "authentication on/off"—it also determines whether health check endpoints like /healthz are exempt.

The project supports 4 modes (from docs/proxy/auth.md):

  • off: no routes require authentication
  • strict: all routes require authentication
  • all_except_health: all routes except /healthz require authentication
  • auto: automatic mode, derives the actual policy based on allow_lan_access

The derivation logic for auto is in ProxySecurityConfig::effective_auth_mode():

rust
match self.auth_mode {
    ProxyAuthMode::Auto => {
        if self.allow_lan_access {
            ProxyAuthMode::AllExceptHealth
        } else {
            ProxyAuthMode::Off
        }
    }
    ref other => other.clone(),
}

Recommended approach

  • Local-only access: allow_lan_access=false + auth_mode=auto (ultimately equivalent to off)
  • LAN access: allow_lan_access=true + auth_mode=auto (ultimately equivalent to all_except_health)

What you should see

  • In the API Proxy page, the "Auth Mode" dropdown has four options: off/strict/all_except_health/auto

Step 3: Confirm your api_key (regenerate if necessary)

Why As long as your proxy needs external access (LAN/public), api_key should be managed like a password.

By default, ProxyConfig::default() generates a key in sk-... format:

rust
api_key: format!("sk-{}", uuid::Uuid::new_v4().simple()),

In the API Proxy page, you can edit, regenerate, and copy the current api_key.

What you should see

  • The page has an api_key input field, plus edit/regenerate/copy buttons

Step 4: Use /healthz to verify that the "exemption strategy" matches expectations

Why/healthz is the shortest loop: you can confirm "service reachable + authentication policy correct" without actually calling the model.

Replace <PORT> with your own port (default 8045):

bash
curl -sS "http://127.0.0.1:<PORT>/healthz"
powershell
curl.exe -sS "http://127.0.0.1:<PORT>/healthz"

What you should see

json
{"status":"ok"}
If you set auth_mode to strict

strict doesn't exempt /healthz. You need to carry a key:

bash
curl -sS "http://127.0.0.1:<PORT>/healthz" \
  -H "Authorization: Bearer <API_KEY>"

Step 5: Use a "non-health endpoint" to verify 401 (and that it's not 401 after adding key)

Why You need to confirm that the authentication middleware is actually working, not that you selected a mode in the UI but it didn't take effect.

The request body below is intentionally incomplete—its purpose isn't to "succeed," but to verify whether it's blocked by authentication:

bash
# Without key: when auth_mode != off, should directly return 401
curl -i "http://127.0.0.1:<PORT>/v1/messages" \
  -H "Content-Type: application/json" \
  -d "{}"

# With key: should no longer be 401 (may return 400/422 because request body is incomplete)
curl -i "http://127.0.0.1:<PORT>/v1/messages" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <API_KEY>" \
  -d "{}"

What you should see

  • Without key: HTTP/1.1 401 Unauthorized
  • With key: status code is no longer 401

Checkpoint ✅

  • You can clearly state your current exposure surface: local-only (127.0.0.1) or LAN (0.0.0.0)
  • When auth_mode=auto, you can predict the actual effective mode (LAN -> all_except_health, local -> off)
  • You can reproduce "401 without key" with 2 curl commands

Pitfall Warnings

Wrong approach vs Recommended approach

Scenario❌ Common mistake✓ Recommended
Need LAN accessOnly enable allow_lan_access=true, but keep auth_mode=offUse auth_mode=auto, and set a strong api_key
Keep getting 401 after enabling authenticationClient sends a key, but header name is incompatibleProxy is compatible with three headers: Authorization/x-api-key/x-goog-api-key
Enabled authentication but didn't configure keyEnabled authentication while api_key is emptyBackend will directly reject (logs will indicate key is empty)

/healthz exemption only takes effect in all_except_health

Middleware will let requests pass when "effective mode" is all_except_health and path is /healthz; treat it as a "health check endpoint," don't use it as a business API.

Privacy and the "Don't Leak Account Info" Design

1) Local proxy keys are not forwarded upstream

Authentication only happens at the local proxy entry; docs/proxy/auth.md clearly states: proxy API keys are not forwarded upstream.

2) When forwarding to z.ai, deliberately restrict forwardable headers

When requests are forwarded to z.ai (Anthropic-compatible), the code only allows a small set of headers to pass, avoiding forwarding local proxy keys or cookies:

rust
// Only forward a conservative set of headers to avoid leaking the local proxy key or cookies.

3) Token refresh failure errors avoid including account emails

When token refresh fails, the logs record the specific account, but the error returned to the API client is rewritten to not include the email:

rust
// Avoid leaking account emails to API clients; details are still in logs.
last_error = Some(format!("Token refresh failed: {}", e));

Lesson Summary

  • First determine exposure surface (allow_lan_access), then determine entry key (auth_mode + api_key)
  • auth_mode=auto rule is simple: LAN means at least all_except_health, local-only means off
  • Privacy baseline is "don't forward local keys outward, don't leak account emails in external errors"—details are in middleware and upstream forwarding code

Next Lesson Preview

In the next lesson, we'll look at High Availability Scheduling: Rotation, Fixed Accounts, Sticky Sessions, and Retry on Failure, completing the "stable exit" after the "secure entry."


Appendix: Source Code Reference

Click to expand source code locations

Last updated: 2026-01-23

FunctionFile PathLines
Four modes of auth_mode and auto semanticsdocs/proxy/auth.md10-24
ProxyAuthMode enum and default value (default off)src-tauri/src/proxy/config.rs5-18
ProxyConfig key fields and defaults (allow_lan_access, api_key)src-tauri/src/proxy/config.rs174-259
Bind address derivation (127.0.0.1 vs 0.0.0.0)src-tauri/src/proxy/config.rs281-292
---------
Authentication middleware (OPTIONS passthrough, /healthz exemption, three header compatibility)src-tauri/src/proxy/middleware/auth.rs14-78
UI: allow_lan_access and auth_mode toggle/dropdownsrc/pages/ApiProxy.tsx943-1046
UI: api_key edit/reset/copysrc/pages/ApiProxy.tsx1048-1120
---------
disable_account: write disabled/disabled_at/disabled_reason and remove from memory poolsrc-tauri/src/proxy/token_manager.rs942-969
Restrict forwardable headers when forwarding to z.ai (avoid leaking local keys/cookies)src-tauri/src/proxy/providers/zai_anthropic.rs70-89
Account pool disable and UI display behavior (documentation)docs/proxy/accounts.md9-44