Claude Code Settings 🤖¶
This page documents the permission and runtime configuration in .claude/settings.json.
For the trust assumptions and the two-layer containment model behind these rules, see security.md.
For the OS-level sandbox configuration, see sandbox.md.
For general agent workflow rules, see common.md.
For the Claude Code reference, see docs.claude.com.
Permission Model 🔐¶
Claude Code evaluates each tool call against the lists in permissions:
List |
Behavior |
|---|---|
|
Executes automatically without prompting. |
|
Pauses and asks the operator for approval before executing. |
|
Rejects the call unconditionally, even if |
deny takes precedence over allow. settings.local.json MAY extend project permissions locally but MUST NOT weaken deny rules defined here.
For Bash specifically, the wildcard allow entry Bash(*) auto-allows every invocation that does not match a deny or ask rule. The legacy sandbox.autoAllowBashIfSandboxed: true flag remains enabled as defence-in-depth, but the Bash(*) entry is now the primary gate, so shell shapes the sandbox heuristic used to decline (env-prefixes, &&/| chains, quoted multi-word args, redirections) no longer need per-shape allow entries.
Allow Permissions ✅¶
The allowlist covers the Bash(*) wildcard plus the non-Bash tools (Read, Edit, Write, WebSearch) and per-domain WebFetch entries (the wildcard form is inert, see row below). The real gating for Bash lives in the ask and deny lists below: mutating gh/docker/git shapes land in ask, and structurally destructive shapes (rm -rf*, sudo*, shell loops, git push --force*, mutating gh api verbs, etc.) are blocked outright by deny. The sandbox (allowWrite, denyRead, allowedDomains) bounds the blast radius of everything that does execute.
Permission |
When |
Why |
Security |
|---|---|---|---|
|
Every shell invocation the agent makes: |
A single wildcard replaces 15+ per-shape entries ( |
The sandbox ( |
|
Every task that inspects a file. |
Core IDE operation. The agent cannot understand code without it. |
Scope is limited by |
|
Every task that modifies an existing file. |
Core IDE operation. Required for any code change. |
Write scope is bounded by |
|
Every task that creates a new file. |
Core IDE operation. Required for scaffolding and new file creation. |
Same sandbox boundary as |
|
Looking up documentation, error messages, or package information. |
Allows the agent to resolve unknown APIs and tooling questions without leaving the terminal. |
Outbound query only. No local data is uploaded. |
|
Fetching repository pages, issue/PR views, raw file content, and project-specific upstream docs (currently Decidim). These form the near-daily baseline for this project’s web research. |
An explicit per-domain allowlist is required because the wildcard form |
Read-only HTTP fetches. Credentials in URLs are still discouraged. Egress is bounded by the sandbox network configuration (see sandbox.md) and any host-level firewall. |
Gating Model for Bash 🚦¶
Because Bash is allowed wholesale, the operational safety of shell invocations rests on three layers, in order of precedence:
deny(precedence 1): structurally destructive shapes are blocked outright, even when sandboxed. Covers shell loops (for/while/until), cross-repogit -C *, force-push/reset/clean/amend,rm -rf*,sudo*, privilegedghverbs (secret/ssh-key/gpg-key/variable/extension/workflow enable/workflow disable/repo delete/pr merge/issue transfer), and mutatinggh apiverbs (DELETE/PUT, secrets/keys/collaborators/merge paths).ask(precedence 2): mutatinggh/docker/gitverbs andSkill(update-config*)pause for operator review. Every image mutation (docker run/build/push/login),gh apiwith a non-GET verb or a body-flag orgraphql, every knownghmutating verb (21 of them viagh * <verb>*),git commit*, and anything touching.claude/settings.jsonroutes through here.Sandbox (precedence 3): everything else runs under
allowWrite/denyRead/allowedDomains. Writes outsideallowWritefail withEROFS; reads from the default~/.sshprivate keys,~/.gnupg,~/.aws, etc. are denied; outbound connections to anything not inallowedDomainsfail.
The sandbox.autoAllowBashIfSandboxed: true flag is retained as belt-and-suspenders. If Bash(*) were ever removed, the sandbox auto-allow would still cover the common shapes, but it is no longer the primary gate.
Consequences in practice:
No allowlist edits are needed when introducing new make targets, scripts, tooling, or shell shapes (redirects, pipes, env-prefixes, quoted args).
Read-only inspection commands (
grep,find,ls,cat,git log,docker ps, etc.) just work.Mutating commands that stay inside
allowWrite(e.g.make test,pip install,docker build, though builds still route throughask) just work under the sandbox.Mutating commands that target paths outside
allowWrite(e.g.mv ~/file /etc/) fail at the sandbox layer with EROFS.Outbound network calls are bounded by
sandbox.network.allowedDomains(see sandbox.md).
The trade-off is that deny now carries the full weight of “what the agent must never do from the shell”. New destructive patterns MUST be added to deny. They can no longer be caught implicitly by an absent allow entry.
Ask Permissions ⚠️¶
These operations pause and require explicit operator approval before executing, even when sandboxed.
Permission |
When |
Why approval is required |
Security |
|---|---|---|---|
|
Creating a permanent history entry. |
The operator MUST review the staged diff and message before committing. |
Commits are persistent and visible to all contributors after push. |
|
Publishing changes to the remote. |
Cannot be undone without a force-push. |
Exposes changes to all repository collaborators and CI. |
|
Starting a container. The bare |
Each invocation carries a unique risk profile depending on flags. |
Can mount host paths, expose ports, and run privileged containers. This is why the rule stays in |
|
Building a Docker image. Bare |
Image builds execute arbitrary instructions from a |
Reviewer MUST confirm the Dockerfile path, build context, and target tag. |
|
Publishing an image to a registry. Bare |
Registry pushes are remotely-visible and irreversible from the client; pushing to the wrong registry or tag can overwrite existing images consumed by downstream deployments. Authentication state is a persistent side-effect (uses the previously-saved |
Reviewer MUST confirm the target registry, repository, and tag before approval. |
|
Storing registry credentials in the local Docker config ( |
Persistent credential material that survives beyond the session and is consumed by every subsequent |
Reviewer MUST confirm the registry URL. If a password is passed via |
|
Any explicit non-GET HTTP verb against the GitHub API. |
The default |
Captures every mutating call regardless of endpoint. The DELETE/PUT-specific deny rules below take precedence and reject those verbs unconditionally. |
|
Any |
|
Captures every implicit-POST |
|
Any call to the GraphQL endpoint. |
GraphQL mutations bypass the REST-path-based deny rules entirely. A |
Every GraphQL invocation requires per-call review. Path-based deny rules do not apply because GraphQL does not use resource-path URIs; the ask prompt is the primary gate. |
|
Any enterprise-scoped API call. |
Enterprise endpoints administer org membership, billing, and policy across multiple orgs. |
Reviewer MUST confirm the enterprise slug and intended scope. |
|
Any organization-scoped API call. |
Org endpoints govern membership, teams, and org-wide settings. |
Reviewer MUST confirm the org and the specific endpoint. |
|
Reading or mutating Actions permissions on a repo. |
Toggles whether forks may run workflows, restricts the action allowlist, and gates repo-level CI policy. |
Reviewer MUST confirm the policy delta before approval. |
|
Triggering a workflow via |
Equivalent in effect to |
Reviewer MUST confirm the workflow ref and inputs payload. |
|
Reading or mutating branch protection on a specific branch. |
Branch protection gates pushes, merges, and required checks. PUT is already blocked unconditionally; this pattern catches GET-audit and explicit-PATCH paths. |
Reviewer MUST confirm the rule delta. |
|
Reading or mutating Actions environments. |
Environments gate deployment secrets and required reviewers; weakening them exposes secrets to additional workflows. |
Reviewer MUST confirm the environment and gating change. |
|
Reading or mutating repository webhooks. |
Hooks deliver events to external systems; misconfiguration can leak data or break integrations. |
Each call MUST be reviewed for target URL and event scope. |
|
Reading or mutating GitHub releases. |
Release creation and asset uploads are user-visible publishing actions. |
Reviewer MUST confirm the tag and asset payload before approval. |
|
Reading or mutating branch/tag rulesets (branch protection successor). |
Rulesets gate merges and pushes; weakening them affects every contributor. |
Each call MUST be reviewed for the rule scope and required-checks impact. |
|
Any team-scoped API call. |
Team endpoints govern membership and permission grants. |
Reviewer MUST confirm the team and intended change. |
|
Any |
The wildcard in the namespace slot collapses 21 mutating verbs across |
Read-only subcommands ( |
|
Compound subcommands (e.g. |
The single-token |
Catches all current and future compound-verb mutations without requiring per-verb enumeration. |
|
Any |
Whole namespace asked: |
Reviewer MUST confirm intent for every invocation; in particular |
|
Any codespace subcommand (create, ssh, cp, delete, ports, …). |
Codespaces are billable, persistent VMs with full repo + secret access; |
Each invocation MUST be reviewed individually for billing + data-flow impact. |
|
Sets a |
|
Reviewer MUST confirm the key and value, especially for |
|
Copies all labels from one repository into another. |
Mutation against the destination repo. Verb |
Reviewer MUST confirm both source and destination repos. |
|
Switches the local working tree to a PR branch. |
Does not check for uncommitted changes by default; silently overwrites them. The risk is to local state, not remote, but the loss is unrecoverable. |
Reviewer MUST confirm the working tree is clean (or stashed) before approving. |
|
Duplicates an entire Projects v2 board. |
Verb |
Reviewer MUST confirm the source/destination owners and visibility. |
|
Sets the default repository for |
Mutates per-directory |
Reviewer MUST confirm the new default repository. |
|
Syncs a fork against its upstream. |
Pulls upstream commits into the fork (the operator’s repo). Verb |
Reviewer MUST confirm the source/destination repos and that the local working tree tolerates the sync. |
|
Triggering a CI workflow run on the remote. |
Consumes runner minutes, executes with workflow secrets, and produces remotely-visible results. Equivalent in effect to |
Each invocation MUST be reviewed to confirm the target workflow and inputs. |
|
Any invocation of the |
The skill writes |
Each settings change MUST be reviewed before it lands. Approval here is equivalent in blast radius to approving a |
Deny Rules 🚫¶
These operations are unconditionally blocked, regardless of any allow entry or sandbox state. They cover destructive patterns whose blast radius is unacceptable even inside the sandbox (. is allowWrite, so rm -rf . would still erase the working tree and .git/).
Permission |
Reason |
|---|---|
|
Shell control-flow loops ( |
|
DELETE is irreversible from the API surface: deleting a release, branch ref, deploy key, or webhook destroys data with no undo. Both |
|
PUT replaces a resource wholesale. On endpoints like branch protection or rulesets, a PUT silently overwrites the entire policy with whatever payload is sent; partial JSON drops every unspecified field. PATCH (the merge variant) still goes through |
|
Touches GitHub Actions secrets: reading metadata, creating, updating, or deleting. Even GETs leak secret names; mutations rotate credentials CI depends on. Out-of-band secret management only. |
|
Touches Actions variables. Variables are unencrypted secrets-lite: workflows read them like secrets, and they are equally load-bearing for CI. Out-of-band variable management only. |
|
Reads or mutates repository collaborator membership. Mutations escalate access; even GETs leak the contributor list. Access changes belong to a human reviewer. |
|
Reads or mutates repository deploy keys. Deploy keys are full-power repo-auth credentials: adding one creates a persistent backdoor; removing one breaks deployments. Manage out-of-band only. |
|
Merges a pull request via API, bypassing the |
|
Any |
|
Any |
|
Moves an issue (with its history and attachments) into a different repository. The destination repo can be attacker-controlled, equivalent to data exfiltration of the issue’s contents. Issue transfers must be a deliberate human action. |
|
CLI parallel to the |
|
Permanently deletes a repository. No undo from the API; recovery requires GitHub support and is not guaranteed. |
|
Any |
|
Any |
|
Any |
|
Disabling a workflow can silently turn off security-critical CI (CodeQL, security-review, lint gates). Must never be done autonomously. |
|
Re-enabling a workflow can silently restart paused CI (e.g. security scans deliberately disabled during incident response) without operator review. |
|
Running |
|
Force-deletes local branches regardless of merge status. Can destroy unmerged work with no recovery path. |
|
Any invocation of |
|
Replaces the tip commit instead of adding one. The agent cannot see whether the operator committed on top in the meantime (a release commit, a signed commit), so an amend can rewrite a commit it never authored and detach its tags and signature; on a pushed tip it forces a force-push. Follow-up changes land as a new commit. |
|
Rewrites remote history. Can permanently destroy other contributors’ work. |
|
Discards all uncommitted local changes without any recovery path. |
|
Recursive force-delete with no confirmation and no undo. Sandbox |
|
Prevents privilege escalation attempts. The sandbox already blocks privileged operations, but denying |
Environment Overrides 🌳¶
The top-level env block sets process environment variables for every Claude Code session. It is currently used to disable GPG signing for agent-created commits via the additive GIT_CONFIG_COUNT mechanism:
"env": {
"GIT_CONFIG_COUNT": "1",
"GIT_CONFIG_KEY_0": "commit.gpgsign",
"GIT_CONFIG_VALUE_0": "false"
}
Variable |
Effect |
Why |
|---|---|---|
|
Adds |
The sandbox |
Future env entries SHOULD follow the same principle: prefer adjusting environment over weakening sandbox denyRead or extending allowWrite.
Local Overrides 🖥️¶
Contributors MAY extend project permissions via .claude/settings.local.json. This file is git-ignored and applies only to the local machine.
Rule |
Description |
|---|---|
MUST NOT weaken |
Local overrides cannot lift unconditional blocks defined in |
MUST NOT disable the sandbox |
Local overrides MUST NOT set |
Machine-specific entries MUST stay local |
Absolute paths, process IDs, and debug tooling MUST NOT be promoted to |
Shared permissions SHOULD be promoted |
Permissions useful for all contributors SHOULD be added to |
Keep overrides minimal |
Entries already covered by project-level wildcards or by sandbox auto-allow SHOULD be removed from |