Credential model

How Backstop handles credentials — what it stores, what it never stores, and how database URLs flow through the system.

What Backstop stores

Backstop stores only what it needs to operate:

StoredWhereRetention
Bearer tokens (hashed)In-process (token file at startup)Until gateway restart
Audit eventsS3 / local storageConfigurable (default: 90 days)
Parquet snapshotsS3Until explicitly deleted
Approval recordsS3 / local storageConfigurable

What Backstop never stores:

  • Database credentials (connection strings are never written to disk or logs)
  • Query results (only metadata and row counts appear in audit events)
  • Bearer tokens in plaintext in logs
  • Any data from the rows returned by SELECT queries

Database credentials

Database URLs are passed to the gateway at startup via environment variable:

BACKSTOP_DB_URL=postgresql://postgres:password@localhost:5432/mydb

The URL is held in process memory only. It is never written to disk, never included in audit events, and never returned through any API endpoint.

If an agent passes db_url in an execute_query request (to override the gateway default), that URL is also held in memory for the duration of the request only. It does not appear in logs or audit records.


Bearer token lifecycle

Tokens are defined in a JSON file and loaded at gateway startup:

BACKSTOP_TOKENS=/etc/backstop/tokens.json backstop-gateway

The gateway reads the file once on startup. Changing the file requires a restart. Token values are never logged — only the token id field appears in audit events.

Token revocation

To revoke a token: remove it from tokens.json and restart the gateway. There is no hot-reload mechanism — the restart is required.

Token storage recommendations

  • Store tokens.json in a secrets manager (AWS Secrets Manager, HashiCorp Vault, Kubernetes Secrets)
  • Pass the file path via environment variable, not the tokens themselves
  • Restrict filesystem read access to the gateway process only (chmod 600 tokens.json)
  • Rotate tokens on a regular schedule — quarterly at minimum

S3 credentials

Backstop accesses S3 for snapshot storage. Credentials are passed via environment:

BACKSTOP_S3_ACCESS_KEY=...
BACKSTOP_S3_SECRET_KEY=...

Or via instance role / workload identity (recommended for cloud deployments):

# AWS: no access key needed if running on an EC2 instance with an IAM role
BACKSTOP_STORAGE_URL=s3://prod-snapshots

Backstop uses the AWS SDK's standard credential chain — instance metadata, environment variables, ~/.aws/credentials — in that order.


What agents can observe

An agent calling execute_query receives:

  • The query result (rows or command result)
  • safety_metadata — risk level, policy decision, table name, affected row estimates
  • approval_id and snapshot_id when relevant

An agent cannot observe:

  • Other agents' queries or results
  • The token file or any other token values
  • Database credentials or connection strings
  • The full audit log (that requires metadata:read scope, which agents should not have)

Snapshot data security

Parquet snapshots stored in S3 contain real table data. Treat them with the same access controls as your database:

  • Enable S3 bucket encryption (SSE-S3 or SSE-KMS)
  • Restrict bucket access to the gateway and sidecar IAM roles only
  • Enable S3 access logging on the snapshot bucket
  • Set a lifecycle policy to expire old snapshots (default retention: 30 days)