Skip to main content

Agent security configuration generator — translates canonical security rules into agent-specific configs

Project description

twsrt logo

Agent security configuration generator — translates canonical security rules into agent-specific configs.

The Problem

AI coding agents (Claude Code, Copilot CLI, etc.) each have their own permission model and configuration format. Maintaining security rules independently per agent leads to configuration drift, and coverage gaps.

Meanwhile, Anthropic's Sandbox Runtime Tool (SRT) enforces OS-level restrictions (filesystem deny, network allowlists) for Bash commands via kernel sandboxing. But SRT cannot control an agent's built-in tools (Read, Write, Edit, WebFetch) — those run inside the agent's own process.

The Solution: Defense in Depth

twsrt tries to bridge the gap. It reads the same SRT policy that enforces OS-level Bash restrictions and translates it into application-level rules for every agent's built-in tools:

                CANONICAL SOURCES (human-maintained)
                ====================================
                ~/.srt-settings.json        — OS-level sandbox rules
                ~/.config/twsrt/bash-rules.json — command deny/ask rules
                          |
                          v
                +-----------------+
                |      twsrt      |  deterministic translation
                |   (generator)   |  + drift detection
                +--------+--------+
                         |
            +------------+------------+
            v            v            v
     Claude Code    Copilot CLI    (future agents)
     settings.json  --flag args

                ENFORCEMENT LAYERS
                ==================
     Layer 1 (OS):  SRT sandbox — kernel-level deny (Bash only)
     Layer 2 (App): Agent permissions — tool-level deny/ask (all tools)

This gives you two layers for the most dangerous attack vector (Bash commands accessing credentials or network) and one consistent layer for built-in tools — all generated from a single source of truth.

Access Path SRT (Layer 1) Agent Permissions (Layer 2) Depth
Bash(cat ~/.aws/credentials) Kernel-enforced deny Tool-level deny Two layers
Read(~/.aws/credentials) Not covered Tool-level deny One layer
Bash(curl evil.com) Network proxy blocks Tool-level deny Two layers
WebFetch(evil.com) Not covered Tool-level allow check One layer

You then start your agent either with SRT builtin (e.g. claude-code, pi-mono via extenstion) or with srt as wrapper, e.g. copilot-cli.

srt -c "copilot \
    --allow-tool 'shell(*)' \
    --allow-tool 'read' \
    --allow-tool 'edit' \
    --allow-tool 'write' \
    --deny-tool 'shell(rm)' \
    --deny-tool 'shell(rmdir)' \
    --deny-tool 'shell(dd)' \
    --deny-tool 'shell(mkfs)' \
    ...

For the full security analysis and threat model see SECURITY_CONCEPT.md.

Overview

twsrt reads two canonical sources:

  • SRT settings (~/.srt-settings.json) — filesystem read/write deny rules, write allow rules, network domain allowlists
  • Bash rules (~/.config/twsrt/bash-rules.json) — command deny/ask rules for Bash execution

It generates security configurations for:

  • Claude Code (~/.claude/settings.json) — permissions.deny, permissions.ask, permissions.allow, sandbox.network
  • Copilot CLI--allow-tool and --deny-tool flag snippets

Key invariant: Source files are never written by twsrt. Target managed sections are never hand-edited.

Installation

# Install as editable uv tool
make install

# Or via pip
pip install twsrt

Usage

Initialize config directory

twsrt init                    # Creates ~/.config/twsrt/ with config.toml + bash-rules.json
twsrt init --force            # Overwrite existing files

Generate agent configs

twsrt generate claude         # Print Claude Code permissions to stdout
twsrt generate copilot        # Print Copilot CLI flags to stdout
twsrt generate                # Generate for all agents

twsrt generate claude --write # Write to ~/.claude/settings.json (selective merge)
twsrt generate claude -n -w   # Dry run: show what would be written

Edit canonical sources

twsrt edit srt                # Open ~/.srt-settings.json in $EDITOR
twsrt edit bash               # Open ~/.config/twsrt/bash-rules.json in $EDITOR
twsrt edit                    # Show available sources

Detect configuration drift

twsrt diff claude             # Compare generated vs existing settings.json
twsrt diff                    # Check all agents

Exit codes: 0 = no drift, 1 = drift detected, 2 = missing file.

Typical workflow

twsrt edit srt                # Add a domain to allowedDomains
twsrt generate claude         # Preview the change
twsrt generate claude --write # Apply (selective merge preserves hooks, MCP, etc.)
twsrt diff claude             # Verify: exit 0 = no drift

Configuration

SRT is a dependency and needs to be installed separately.

~/.srt-settings.json (SRT — prerequisite)

SRT configuration is the primary canonical source that defines OS-level enforcement boundaries. twsrt reads it to generate matching agent-level rules:

{
  "filesystem": {
    "denyRead":  ["~/.aws", "~/.ssh", "~/.gnupg", "~/.netrc"],
    "denyWrite": ["**/.env", "**/*.pem", "**/*.key", "**/secrets/**"],
    "allowWrite": [".", "/tmp", "~/dev"]
  },
  "network": {
    "allowedDomains": [
      "github.com", "*.github.com",
      "pypi.org", "*.pypi.org",
      "registry.npmjs.org"
    ]
  }
}

~/.config/twsrt/config.toml

[sources]
srt = "~/.srt-settings.json"
bash_rules = "~/.config/twsrt/bash-rules.json"

[targets]
claude_settings = "~/.claude/settings.json"
# copilot_output = "~/.config/twsrt/copilot-flags.txt"  # optional, stdout if omitted

~/.config/twsrt/bash-rules.json

{
  "deny": ["rm", "sudo", "git push --force"],
  "ask": ["git push", "git commit", "pip install"]
}

Rule Mapping

SRT / Bash Rule Claude Code Copilot CLI
denyRead directory Tool(path) + Tool(path/**) in deny (SRT enforces)
denyRead file Tool(path) in deny (SRT enforces)
denyWrite pattern Write/Edit/MultiEdit in deny (SRT enforces)
allowWrite path (no output) --allow-tool flags
allowedDomains domain WebFetch(domain:X) in allow + sandbox.network (SRT enforces)
Bash deny cmd Bash(cmd) + Bash(cmd *) in deny --deny-tool 'shell(cmd)'
Bash ask cmd Bash(cmd) + Bash(cmd *) in ask --deny-tool (lossy, warns)

Where Tool = Read, Write, Edit, MultiEdit. Directory vs file detection uses the filesystem at generation time; glob patterns and unknown paths are treated as bare patterns (no /** suffix for globs, /** added for unknown paths).

Development

make test              # Run tests
make lint              # Ruff lint
make format            # Ruff format
make ty                # Type check with ty
make static-analysis   # All of the above

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

twsrt-0.2.0.tar.gz (14.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

twsrt-0.2.0-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file twsrt-0.2.0.tar.gz.

File metadata

  • Download URL: twsrt-0.2.0.tar.gz
  • Upload date:
  • Size: 14.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for twsrt-0.2.0.tar.gz
Algorithm Hash digest
SHA256 f84e4266f328efc9c26182beb4a4872dfbc8accbb9ba1b6f3d74d98445b9b415
MD5 aa71e8fd8a8c7a134f53ffed7983abf0
BLAKE2b-256 8c40dcf916daf230453fa11989399ce9551ac859c10ff9c1520cbf0c62db1b81

See more details on using hashes here.

File details

Details for the file twsrt-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: twsrt-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 13.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.11

File hashes

Hashes for twsrt-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2638e19b1af8bba2c90e8a579a1bbf9d02297c99c3d803b08cd83e349c1ae172
MD5 c01d1774ad4ffecbf08eab3cff11d92e
BLAKE2b-256 e06526f665056feec192b2cf78c5e255cb9e01a1bee1cce06610db26f1ccb750

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page