Security model
SnowClaw is designed to be safe to run in your Snowflake account by default. Every security decision below is on by default — you don't have to opt in.
Network egress control
All outbound traffic is deny-by-default. Only explicitly approved hosts (managed via snowclaw network) get Snowflake network rules and external access integrations. The container cannot reach the internet unless you allow it.
Setup auto-detects required hosts from your provider, channel, and tool selections, shows you the diff, and prompts before applying.
SPCS ingress control
Snowflake handles TLS termination and authentication on the single public endpoint (port 18789). There are no open ports or exposed services beyond what SPCS declares — the ingress surface is managed entirely by Snowflake's infrastructure.
The Cortex proxy sidecar is internal only. It does not bind to any public port.
File permissions at runtime
The Docker entrypoint runs as root, locks down config files, and drops to the node user (UID 1000) before starting OpenClaw:
openclaw.json→root:node 440(read-only for gateway, no write for agent)credentials/→root:node 440secrets.json→root:node 440workspace/andskills/→node:node(writable).snowflake/connections.toml→ owned bynodeso Cortex can read/write connection state
The agent process cannot modify its own config or credentials. Two independent layers enforce this: OS permissions and the tools.fs.workspaceOnly: true policy in the generated openclaw.json, which restricts agent file tools to the workspace directory.
Role separation
- Admin role (default:
SYSADMIN) — used by the CLI for provisioning: creates the database, schema, image repo, stage, compute pool, secrets, network rule, and external access integration. Lives on your machine; never enters the container. - Runtime role — owns the SPCS service. Gets only the grants it needs at runtime:
USAGEon DB/schema/EAI/pool,READ+WRITEon the state stage,READon the image repo,MONITORon the pool,READon each secret,BIND SERVICE ENDPOINT ON ACCOUNT, andDATABASE ROLE SNOWFLAKE.CORTEX_USER. Nothing else. You create this role yourself once per Snowflake account, before runningsnowclaw setup, and grant it to the admin role. See Snowflake privileges for the one-time setup SQL.
The container runs under the runtime role. Every Snowflake PAT that lives inside the container ({prefix}_sf_token) is ROLE_RESTRICTION-scoped to the runtime role, so a compromise of that token cannot alter network rules, mint new secrets, or create sibling services.
Snowflake blocks GRANT OWNERSHIP ON SERVICE, so snowclaw deploy hands ownership to the runtime role by having the runtime role create the service in the first place — via a transient CREATE SERVICE grant that's revoked immediately afterwards. See Snowflake privileges for the exact grant matrix, the "transient CREATE SERVICE dance", and the admin-PAT recipe.
Two PATs
SnowClaw uses two separate Snowflake PATs, each minted by you during setup:
- Admin PAT — in
.envasSNOWFLAKE_TOKEN. Used by the CLI on your machine for provisioning andsnowclaw push/pull. Never uploaded to Snowflake as a secret. Should beROLE_RESTRICTION-scoped to the admin role. - Runtime PAT — stored as the
{prefix}_sf_tokenSnowflake secret and bound into both containers asSNOWFLAKE_TOKEN. Used by Cortex Code, snowsql, and the Cortex proxy inside the service.ROLE_RESTRICTION-scoped to the runtime role. The setup wizard prints the exactALTER USER ... ADD PROGRAMMATIC ACCESS TOKENcommand and prompts for the returned value.
SNOWCLAW_MASK_VARS always includes SNOWFLAKE_TOKEN so that if an agent ever smuggled the runtime PAT into an LLM request body, the proxy masker would redact it before it left the sidecar.
Secret masking
The Cortex proxy sidecar scans all outbound LLM messages and replaces known secret values with [REDACTED:VAR_NAME]. Credentials never reach the model, even if the agent tries to include them in a prompt.
Variables listed in SNOWCLAW_MASK_VARS (auto-generated from your .env) are added to the masking set. By default, all token and API key variables are masked. You can extend this list manually.
The masker uses two shape-specific walkers — one for OpenAI-style messages[].content + tool calls, and one for Anthropic-style messages[].content blocks + top-level system. Both preserve cache_control markers and other block metadata.
User-managed secrets
Every KEY=value in .env becomes an individual Snowflake SECRET object at deploy time — never baked into the Docker image. CUSTOM_-prefixed variables are auto-registered with no extra config. Secrets are mounted into the container as env vars at runtime.
Secrets are never retrievable — Snowflake stores them as encrypted blobs. .env is your source of truth.