Security

This page documents TameFlare's security model, including the proxy architecture, cryptographic design, data handling, and operational security guidance.


How HTTPS interception works

TameFlare uses a cloud proxy model for HTTPS interception. The gateway runs at proxy.tameflare.com - there is no local binary to install and no local CA certificate to manage.

How it works

  1. tf run sets HTTPS_PROXY=https://{gateway_token}@proxy.tameflare.com and spawns your process
  2. Your agent's HTTP library sends all outbound requests through the cloud proxy via the standard CONNECT tunnel
  3. The cloud gateway at proxy.tameflare.com:
    • Identifies your gateway by the token in the proxy authorization header
    • Terminates TLS, inspects the request, and applies permission checks
    • If allowed, injects credentials from the encrypted vault and forwards to the real destination
    • If denied, returns 403 immediately
  4. Only traffic metadata (domain, action type, decision, status code, latency) is logged to the dashboard. Request/response bodies are never stored.

Why this is safe

  • No request/response bodies stored. The cloud gateway processes traffic for enforcement but does not persist bodies. Only metadata is logged.
  • Credential isolation. Your agent process never sees real API keys. Credentials are injected by the gateway at request time from an AES-256-GCM encrypted vault.
  • Per-gateway tokens. Each gateway has a unique token. Tokens are validated on every request.
  • EU-hosted infrastructure. Both the dashboard (tameflare.com) and the cloud gateway (proxy.tameflare.com) are hosted in the EU.
  • Same enforcement model as corporate proxies. Organizations like banks and hospitals use proxy-based interception for DLP and compliance. TameFlare applies the same pattern to AI agent traffic.
Note
The .tf/ directory stores your gateway configuration (config.yaml) and local credentials. It is in .gitignore by default. Do not commit gateway tokens to version control.

Proxy compatibility

Most HTTP libraries respect HTTPS_PROXY automatically. tf run sets this for the child process. No additional trust store configuration is needed - the cloud proxy uses a valid public TLS certificate.


Proxy bypass analysis

What tf run enforces

tf run sets HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables for the child process. Most HTTP libraries (Python requests, Node.js axios/fetch, Go net/http) respect these automatically.

What it cannot prevent

TameFlare is honest about its limitations:

Bypass methodCan TameFlare prevent it?Mitigation
Agent ignores HTTP_PROXY env varNoUse OS-level network isolation (firewall rules, network namespaces)
Agent uses raw TCP socketsNoProxy only intercepts HTTP/HTTPS
Agent hardcodes IP addressesNoFirewall rules blocking direct outbound on ports 80/443
Agent uses non-HTTP protocols (gRPC, WebSocket, UDP)NoTameFlare is HTTP/HTTPS only
Agent reads gateway token from envUnlikely (env var scoped to child process)Restrict .tf/config.yaml permissions; use short-lived tokens
Note
For defense in depth, combine TameFlare with OS-level network isolation. On Linux, use iptables or network namespaces to block direct outbound traffic from agent processes. On macOS, use pf firewall rules. This ensures the proxy is the only path to the internet.

Threat model

TameFlare is designed to protect against:

ThreatHow TameFlare mitigates it
Agent calls unauthorized APIsDeny-all default. No connector configured = no access. Agent cannot reach any domain you haven't set up.
Agent bypasses policy checksMode A: Agent doesn't hold external API keys - the Gateway does. Without permission, the request is blocked.
Agent forges a decision tokenTokens are ES256-signed (ECDSA P-256). The private key lives on the control plane. Agents never see it.
Agent replays a used tokenTokens include a nonce. The control plane marks nonces as used on first verification. Replay attempts are rejected.
Agent reuses a token for a different actionTokens carry an action spec hash. The Gateway verifies the hash matches the action being executed.
Credential leakageIn proxy mode, agents never see real API keys. Credentials are injected by the gateway at request time.
Unauthorized dashboard accessRBAC with 4 roles (owner > admin > member > viewer). Session tokens stored in DB. Optional DASHBOARD_PASSWORD for shared access.
Secrets leaked from databaseSlack tokens, GitHub PATs, and other secrets are encrypted at rest with AES-256-GCM when SETTINGS_ENCRYPTION_KEY is configured.
Runaway agent activityRate limiting (120 req/min per agent, configurable). Kill switch halts all traffic instantly. Scoped to all/connector/agent.

What TameFlare does NOT protect against

  • Prompt injection / hallucination content - TameFlare evaluates the action spec, not the LLM reasoning. If a hallucinated action has a valid type and parameters that pass policy checks, it will be allowed.
  • Local file system / shell access - TameFlare operates at the network layer. It cannot prevent an agent from reading files, running shell commands, or accessing local resources. Use OS-level sandboxing (containers, seccomp) for that.
  • Non-HTTP protocols - gRPC, WebSocket upgrades, raw TCP, and UDP are not intercepted by the proxy.
  • Compromised host - If an attacker gains root access to the TameFlare server, they can read the credential vault, modify policies, or extract secrets. Secure your TameFlare deployment like any other production service.
  • Third-party security audit - TameFlare has not yet been audited by a third party. We plan to commission an independent audit as the project matures. The full source code is available for your own review under the Elastic License v2.

Credential vault

The credential vault stores API keys for connectors (GitHub tokens, Stripe keys, OpenAI keys, etc.) encrypted at rest.

How it works

  • Encryption: AES-256-GCM with a key derived from the server's SETTINGS_ENCRYPTION_KEY
  • Storage: Encrypted in the dashboard database (EU-hosted). Credentials entered via the dashboard gateway wizard are stored here.
  • Access pattern: The cloud gateway fetches credentials from the dashboard at config sync time, holds them in memory, and injects them into allowed requests at proxy time.
  • Agent isolation: Agents never see credentials. The proxy adds Authorization headers (or equivalent) after permission checks pass.

Who can access credentials

ActorCan access?How
Agent processNoAgent only sees the proxy URL, never real API keys
Cloud gateway processYesReceives credentials from dashboard at config sync, injects at request time
Dashboard user (admin)PartialCan add/remove credentials via wizard, but stored values are masked
Dashboard user (viewer)NoCannot see or modify credentials
Note
TameFlare protects agent → key access, not operator → key access. Dashboard admins can manage credentials via the wizard. TameFlare governs agent behavior, not operator behavior.

Key loss recovery

If the SETTINGS_ENCRYPTION_KEY is lost:

  1. Encrypted credentials cannot be recovered
  2. Re-add credentials via the dashboard gateway wizard
  3. Generate a new key and re-enter all connector credentials

Control plane secrets

The control plane (Next.js) also encrypts integration secrets (Slack tokens, GitHub PATs configured via Settings) using AES-256-GCM when SETTINGS_ENCRYPTION_KEY is set:

  • Each value encrypted with a unique IV
  • Stored as enc:<base64(iv + ciphertext + auth_tag)> in SQLite
  • If the key is lost, re-enter secrets in the dashboard

Data logging scope

What tf logs

DataLogged?Where
Request URL and pathYesTraffic log (gateway SQLite)
HTTP methodYesTraffic log
Request headersSelected only (Host, Content-Type, User-Agent)Traffic log
Response status codeYesTraffic log
Latency (ms)YesTraffic log
Parsed action type (e.g., github.pr.merge)YesTraffic log + audit log
Decision (allow/deny/require_approval)YesTraffic log + audit log
Agent nameYesTraffic log + audit log
Connector typeYesTraffic log
Approver identity and timestampYesAudit log

What TameFlare does NOT log

DataLogged?Reason
Request bodyNoMay contain PII, secrets, or sensitive business data
Response bodyNoMay contain PII or proprietary data
Authorization headersNoContains API keys (injected by proxy)
Cookie valuesNoSession data
Query parametersPartial (URL logged, but sensitive params like ?token= are not parsed)Privacy
Tip
If your compliance requirements need request/response body logging, implement it at the application layer or use a dedicated DLP tool. TameFlare intentionally avoids logging bodies to minimize data exposure risk.

Inter-component security

Cloud proxy ↔ Dashboard communication

The cloud gateway at proxy.tameflare.com communicates with the dashboard at tameflare.com over HTTPS:

DirectionProtocolAuth
Cloud gateway → Dashboard (config sync, token verification)HTTPSPer-gateway token (gwtk_*)
Cloud gateway → Dashboard (traffic metadata logging)HTTPSPer-gateway token (gwtk_*)

Both components are hosted in the EU. All inter-component traffic is encrypted in transit.

Agent isolation

  • Each gateway has a unique token. Traffic is identified and scoped by gateway token.
  • An agent can only see its own traffic logs via the v1 API (scoped by API key)
  • Agents cannot see other agents' actions, credentials, or permissions
  • The dashboard shows all agents' activity (scoped by RBAC role)

Data residency

The gateway's only outbound traffic is (1) your configured connectors and (2) encrypted control plane sync for configuration and audit metadata:

IntegrationWhat data is sent externallyWhen
None configuredNothing. Zero outbound calls.Always
Slack approvalsAction type, agent name, resource target, approval statusWhen an action requires approval
Webhook callbacksAction type, decision, agent ID (configurable payload)When webhook_url is set on an action request
Configured connectorsThe proxied HTTP request itself (forwarded to the real API)When an action is allowed

Slack notifications do not include credentials, request/response bodies, or policy details.

Note
TameFlare has no third-party trackers, no license-check calls, and no product telemetry. The website uses privacy-friendly analytics (Plausible) for anonymous page views only - no session replay, no ad tracking. The cloud gateway logs only traffic metadata (domain, action type, decision, latency) to the dashboard - never request bodies, response bodies, or API credentials. The SENTRY_DSN and POSTHOG_KEY env vars are disabled by default and only activate if you explicitly set them.

Fail-closed model

TameFlare uses a fail-closed (deny-by-default) security model:

ScenarioBehavior
No connector configured for a domainRequest blocked (403)
No permission rule matchesRequest denied (default deny)
Policy engine encounters an errorAction denied
Gateway cannot reach control planeGateway operates independently using local permissions and cached config.
Approval timeout (5 minutes)Request denied (408)
Kill switch activeAll matching traffic blocked immediately
Rate limit exceededRequest rejected (429) with Retry-After header
Invalid or expired decision tokenExecution rejected
Nonce already usedExecution rejected (replay protection)

There is no "fail-open" mode. If TameFlare cannot make a decision, the default is deny.


Cryptographic design

Decision tokens (ES256)

TameFlare uses ES256 (ECDSA with P-256 curve and SHA-256) for decision tokens, implemented via the jose library.

Token lifecycle:

  1. Agent requests an action via POST /api/v1/actions
  2. Policy engine evaluates and returns a decision
  3. If allow or requires_approval (after approval), the control plane signs a JWT containing:
    • action_request_id - the specific action this token authorizes
    • action_spec_hash - SHA-256 hash of the canonical action spec JSON
    • nonce - unique random value for replay protection
    • iat / exp - issued-at and expiration (5 minutes)
  4. Agent sends the token to POST /api/v1/actions/:id/execute
  5. Gateway forwards the token to the control plane for verification
  6. Control plane verifies signature, checks expiry, validates nonce (marks as used), and confirms action hash matches

Key management:

  • ES256 key pair is generated on first boot and stored in the database
  • The private key never leaves the control plane process
  • There is currently no automatic key rotation - rotate manually by generating a new key pair and restarting

Key loss recovery

If the ES256 private key is lost:

  1. All outstanding (unused) decision tokens become unverifiable
  2. Generate a new key pair and restart the control plane
  3. Agents will need to re-request any pending actions to get new tokens
  4. Historical audit data is unaffected - tokens are verified at execution time, not retroactively

Encryption at rest

Settings encryption

When SETTINGS_ENCRYPTION_KEY is set, TameFlare encrypts sensitive settings (Slack tokens, GitHub PATs, signing secrets) using AES-256-GCM before storing them in the database.

Setup:

# Generate a 256-bit key
openssl rand -hex 32
 
# Set in your environment
SETTINGS_ENCRYPTION_KEY=your_64_char_hex_key_here

How it works:

  • Each value is encrypted with a unique IV (initialization vector)
  • Encrypted values are stored as enc:<base64(iv + ciphertext + auth_tag)>
  • Decryption happens in-memory when settings are read
  • If the key is lost, encrypted settings cannot be recovered - re-enter them in the dashboard

Database

The SQLite database file is not encrypted by default. For production deployments:

  • Use filesystem-level encryption (LUKS, FileVault, BitLocker)
  • Or use Turso (hosted libSQL) which encrypts data at rest
  • Restrict file permissions: chmod 600 local.db

Authentication

Agent authentication

Agents authenticate via API keys in the Authorization: Bearer <key> header.

  • Keys are generated with a cryptographically random value
  • Only the bcrypt hash is stored in the database
  • Keys are prefixed (tf_test_ or tf_live_) for easy identification
  • The prefix is stored separately for lookup without exposing the full key
  • Keys are shown once at creation - they cannot be retrieved later

User authentication

Dashboard users authenticate via email/password:

  • Passwords are hashed with bcrypt (cost factor 10)
  • Sessions are stored in the database (not in-memory) and survive restarts
  • Session tokens are cryptographically random, stored in HTTP-only cookies
  • Legacy mode: DASHBOARD_PASSWORD environment variable for shared access

Rate limiting

  • 120 requests per minute per agent (sliding window)
  • Returns 429 Too Many Requests with Retry-After header
  • Rate limit state is in-memory (resets on restart)

Policy engine safety

The policy engine is not Turing-complete. It evaluates a fixed set of condition operators against action spec fields:

  • No loops, recursion, or arbitrary code execution
  • Maximum nesting depth for any/all combinators is bounded by YAML structure
  • Evaluation is O(policies × rules × conditions) - linear, not exponential
  • A malformed policy cannot crash the engine - parse errors are caught and the policy is skipped

Operational security checklist

ItemStatusAction
SETTINGS_ENCRYPTION_KEY setRequired for productionopenssl rand -hex 32
SIGNING_KEY_PRIVATE/PUBLIC setRequired for productionGenerate with openssl ecparam -genkey -name prime256v1
HTTPS enabledRequired for productionUse a reverse proxy (nginx, Caddy) with TLS
.tf/config.yaml not in version controlRequiredAlready in .gitignore - verify with git status
Gateway tokens rotatedRecommendedRotate tokens periodically in the dashboard
Dashboard password or user authRequiredSet DASHBOARD_PASSWORD or register users at /register
Rate limitingEnabled by default120 req/min per agent
Kill switch testedRecommendedToggle on/off in Settings to verify it works
Audit log retentionRecommendedSet AUDIT_RETENTION_DAYS and run cleanup job
Backup strategyRecommendedCopy .db file or use Turso

Responsible disclosure

If you discover a security vulnerability in TameFlare, please report it responsibly:

  • Email: security@tameflare.com
  • Do not open a public GitHub issue for security vulnerabilities
  • We will acknowledge receipt within 48 hours and provide a timeline for a fix
  • See SECURITY.md for the full disclosure policy, response timeline, and scope

Third-party security audit

TameFlare has not yet undergone a third-party security audit. This is planned and will be prioritized as the project matures.

ItemStatus
Third-party penetration testPlanned - not yet scheduled
SOC 2 compliancePlanned
Code audit by external firmPlanned - seeking firms with Go + Node.js expertise
Bug bounty programNot yet - will consider after first audit

What we do today

  • Source-available code - the entire codebase is inspectable. You can audit it yourself or hire a firm to audit it.
  • SECURITY.md - responsible disclosure process with 48h acknowledgment SLA
  • Dependency scanning - GitHub Dependabot alerts enabled
  • 51 unit tests for the policy engine (conditions, evaluator, nested combinators)
  • Integration test scripts - dogfood.js (99 tests), dogfood-gateway.js (81 tests), simulate-new-user.js (40 tests)

Test coverage

ComponentTestsType
Policy engine (conditions)14 testsUnit (vitest)
Policy engine (evaluator)37 testsUnit (vitest)
API routes99 testsIntegration (dogfood.js)
Gateway proxy81 testsIntegration (dogfood-gateway.js)
New-user flow40 testsEnd-to-end (simulate-new-user.js)
Real agent (7 tasks)7 testsIntegration (test-TameFlare-agent/)

Security-specific test coverage:

  • Auth bypass - tested in dogfood (invalid keys, expired sessions, missing headers)
  • RBAC enforcement - tested per role (owner, admin, member, viewer)
  • Kill switch - tested activation, scoping, and deactivation
  • Rate limiting - tested 429 responses and Retry-After headers
  • Nonce replay - tested token reuse rejection
  • Zod validation - tested malformed payloads, missing fields, extra fields
Note
We are transparent about our current testing state. If you require a formal audit report before adoption, we recommend auditing the source code yourself or engaging a third-party firm. We're happy to assist with scoping.

Next steps