Many companies are adopting Anthropic’s Claude Code as their AI Companion. Installing Claude Code CLI is straightforward. But as easy as it is, it also provides by default unrestricted access to the entire filesystem. This is a first approach to implementing some secure by default configurations and guardrails to limit what actions Claude can perform at the macOS level. Despite the fact I’m including useful considerations for companies deploying Claude Code CLI for the first time, this guide is intended for personal usage.
Note on personal usage. I strongly recommend to run claude code CLI using devcontainers to reduce attack surface
1. Understanding configuration scope
There are primarily 4 layers based on 3 different files. The files themselves accept the same settings, and have the same structure. What differentiates them is precedence (and location).
| Layer | Configuration File | Precedence | Enforced | Purpose |
|---|---|---|---|---|
| 1 | /Library/Application Support/ClaudeCode/managed-settings.json |
Highest | Yes | Organization-wide enforced policies |
| 2 | ~/.claude/settings.json |
Below Layer 1 | No | Personal defaults across all projects |
| 3 | .claude/settings.json |
Below Layers 1–2 | No | Project-specific configuration |
| 4 | .claude/settings.local.json |
Lowest | No | User-specific settings for a single project |
2. Base Security Guardrails: Sandbox
2.1 Anthropic Sandbox
The sandbox restricts what Claude can read, write, and reach on the network, preventing it from accessing sensitive files or exfiltrating data even if manipulated. It is enforced at the OS level, in macOS using SeatBelt, below Claude’s own judgment layer.
- When enabled it can restrict:
- Command execution
- Directory reading/listing
- Network access
- Access to specific Marketplaces only
- Access to specific MCPs only
It is recommended to enable the sandbox in the above mentioned [[#1. Understanding configuration scope]], the managed-settings.json file and deploy this file globally using MDM tools.
An example version of this file could look like
{
"permissions": {
"defaultMode": "default",
"deny": [
"Bash(osascript *)",
"Bash(osacompile *)",
"Bash(security *)",
"Bash(screencapture *)",
"Bash(tclsh *)",
"Bash(launchctl *)",
],
"disableBypassPermissionsMode": "disable",
"allowManagedPermissionRulesOnly": true
},
"sandbox": {
"enabled": true,
"allowUnsandboxedCommands": false,
"filesystem": {
"denyRead": [
"~/.ssh",
"~/.gnupg",
"**/.env",
"**/.env.*",
"~/.bashrc",
],
"allowWrite": [
],
"denyWrite": [
"/etc/cron*",
"/etc/periodic/**",
"/var/spool/cron/**",
"~/Library/LaunchAgents/**",
"~/Library/LaunchDaemons/**",
"/Library/LaunchAgents/**",
"/Library/LaunchDaemons/**",
"/System/Library/LaunchAgents/**",
"/System/Library/LaunchDaemons/**",
]
},
"network": {
"allowedDomains": [
"localhost",
"127.0.0.1",
"::1",
"*.your_safe_domain.com",
"*.anthropic.com",
],
"allowManagedDomainsOnly": true,
}
},
"allowManagedMcpServersOnly": false,
"extraKnownMarketplaces": {
"{your_trusted_mkt}": {
"source": {
"source": "url",
"url": "https://{your_trusted_mkt}.com/claude-code/marketplace.json"
}
}
},
"strictKnownMarketplaces": [
{
"source": "github",
"repo": "anthropics/claude-plugins-official"
},
{
"source": "url",
"url": "https://{your_trusted_mkt}.com/claude-code/marketplace.json"
}
],
"disableAllHooks": false
}
Claude use cases vary from individual and organizations, so you will need to find the right set of settings that most accurately captures your use case
One considerations on the file above is that It is set on Blocklist mode, meaning that what it is not explicitly deny it is allowed. The other mode, allowlist, would be safer but it will require a significant operational work for a company environment (recommended for personal usage)
2.2 Permission Rules
I introduced here commands which usage could be risky. Inspiration came from Living off the Land binaries for macOS
Rationale behind some of the commands I choose to introduce in the file (you can do this process as detail as you needed).
| Command | Risk |
|---|---|
osascript / osacompile |
Arbitrary code execution via AppleScript |
security |
Keychain access and credential extraction |
screencapture |
Screen capture and potential data exfiltration |
swift / tclsh |
Alternative code execution paths that bypass python/bash restrictions |
nscurl |
Alternative HTTP client that can bypass curl deny rules |
launchctl |
Persistence through Launch Agents and Launch Daemons |
dscl / dscacheutil |
Local user and directory service enumeration |
sysadminctl / systemsetup |
Account management and system configuration changes |
streamzip |
Archive creation that may facilitate file exfiltration |
- denyWrite. Basically restricting write operations to common directories used for establishing persistence
2.23 Network control layers in Claude
First, lets understand how Claude CLI performs network calls. There are primarily two ways:
- WebFetch. It is the native Claude Code CLI tool for retrieving web pages and docs
- Subprocess commands. Any subprocess command, like curl/wget, run via bash
- WebSearch (not covered here)
The network section on the managed-settings file has impact only on the subprocess commands egress request.
For instance, let’s say that this is my network section
"network": {
"allowedDomains": [
"github.com",
"anthropic.com"
]
}
If I run within Claude Code CLI:
!curl bitbucket.com
it will be blocked as curl is a subprocess of bash.
Now if I ask Claude to run it
Access gitlab.com
it will work, as this request is handled by the webFetch Tool. For blocking webfetch add it in the permissions section
{
"permissions": {
"deny": [
"WebFetch",
]
}
}
or, with more granularity, allow only domain1 and domain2 as follows
{
"permissions": {
"allow": [
"WebFetch(domain:domain1.com)",
"WebFetch(domain:domain2.com)"
],
"deny": [
"WebFetch"
]
}
}
As a final note, for non-personal environments, it is recommended to pair this strategy with independent Egress filtering controls (at the host layer)
3 Additional Recommendation for Enterprise deployments
3.1 Identify and block all non company claude code instances
Once Claude Code is fully deployed company-wide, you might want to ensure that there are no Code instances that are not authenticated through SSO, meaning that they are running on non-company accounts. The risks are:
- Potential data exfiltration
- Endpoint compromise (unrestricted Claude code CLI)
- Logging and monitoring failures (no visibility of what it is being done)
To identify who is running a non-company Claude code account you can inspect the following file:
cat ~/.claude.json | jq '.oauthAccount'
{
"accountUuid": ,
"emailAddress": ,
"organizationUuid": ,
"hasExtraUsageEnabled": ,
"billingType": ,
"subscriptionCreatedAt": ,
"displayName": ,
"organizationRole": ,
"workspaceRole": null,
"organizationName":
}
3.2 Logging, and Monitoring
Claude Code can be configured to use an OpenTelemetry (OTEL) to ship both logs and metrics
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.example.com:4317",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer example-token"
}
}
3.3 Deployment phases and considerations
Consider
- Deploying to test group first
- Gathering feedback, analyze security gaps, issues and fine-tune the managed-settings file
- Tracking the changed to the managed-settings file using git
- Building a CICD pipeline