Paths Subjects Questions Quizzes Pricing Search
Advanced Open Free

Designing a Sandbox and Permission Policy for a Fintech Monorepo

You're setting up Claude Code for a 40-engineer fintech company working in one large monorepo that contains: application code, Terraform for production infrastructure, a secrets/ directory holding locally-decrypted credentials for local dev, and a scripts/deploy/ directory that can push to production. Engineers should be able to use Claude Code productively for day-to-day feature work without constant prompting, but production access needs a hard human checkpoint no individual engineer can quietly relax.

  1. Design the sandbox configuration: what should sandboxed commands be able to read and write by default, and what needs an explicit deny?
  2. Design the permission rules: what goes in allow, what goes in deny, and what goes in ask? Be specific about which of these needs to be enforced at the managed-settings level rather than left to project settings.
  3. A team lead argues the secrets/ deny rule doesn't need to be in managed settings because "it's already in the project's .claude/settings.json, and nobody would remove it." Explain concretely why this reasoning is insufficient for this threat model.
Solution

1. Sandbox configuration:

Enable the built-in Bash sandbox in auto-allow mode so routine local work (tests, builds, linting) doesn't generate constant prompts, but layer explicit protections on top of the defaults rather than trusting them as-is. The sandbox's default read behavior — read access to essentially the whole machine except a short denied list — is not acceptable for this threat model as-is, because it would let a sandboxed command read secrets/ and any host credentials by default. Add sandbox.filesystem.denyRead (or the dedicated sandbox.credentials.files deny entries) for secrets/ and any host credential paths engineers might have (~/.aws/credentials, ~/.ssh/), and keep the default write scope (working directory plus session temp) rather than widening it — there's no reason a routine task needs write access outside the checkout. Because the Bash sandbox does not constrain MCP servers or hooks, and this org has real production access to protect, consider the sandbox runtime or a dev container for any workflow that also uses MCP servers with production access, since those run entirely outside the Bash-only sandbox boundary regardless of how tightly sandbox.filesystem is configured.

2. Permission rules:

  • allow: narrow, specific entries for routine, low-risk commands engineers run constantly — Bash(npm run test *), Bash(npm run lint), and similar. This is what removes the prompt fatigue that would otherwise push engineers toward broader allow rules or bypass modes.
  • deny: Read(./secrets/**) and equivalent rules for any credential directory, applied unconditionally regardless of permission mode. This is the one guarantee that has to hold no matter what mode any individual engineer happens to be running that day.
  • ask: a rule that forces a prompt for anything touching scripts/deploy/ or the Terraform directory, even in auto mode — something like an ask rule scoped to those paths, or to the specific deploy commands. This is the "hard human checkpoint" the scenario asks for: an explicit ask rule forces a prompt even when auto mode's classifier would otherwise judge the action safe, which is exactly the property needed here.
  • The secrets/ deny rule and the deploy-path ask rule both need to live in managed settings with allowManagedPermissionRulesOnly: true set, so no engineer's local or project-level settings edit can remove or relax them. The routine allow rules for tests and lint can safely stay in project-level .claude/settings.json since relaxing those carries little risk and engineers benefit from being able to extend them for their own workflow.

3. Why "it's already in project settings" is insufficient:

A rule in .claude/settings.json is enforced by convention, not by guarantee — any engineer with write access to the repository (which, in a 40-person monorepo, is most of the team) can edit that file in a branch, or a well-meaning engineer chasing a false-positive prompt could narrow the deny rule "temporarily" and forget to revert it. Nothing stops that change from merging like any other PR unless a review process specifically catches it, and even then, an engineer's own .claude/settings.local.json can add competing rules for their own sessions without touching the shared file at all. Managed settings close this gap specifically: with allowManagedPermissionRulesOnly: true, permission rules from project and local settings stop having any effect at all, and only the managed-settings deny rule is consulted — there is no supported way for an individual engineer, however well-intentioned or however much repository access they have, to work around it. For a rule protecting locally-decrypted production credentials, "nobody would remove it" is a social expectation; a managed-settings lock is the actual technical guarantee, and this threat model — a fintech company with real financial and infrastructure exposure — is exactly the kind of environment where that distinction matters enough to be worth the administrative overhead of managed settings.

Share this question

← Back to Claude Code Sandboxing and Security practice

We use cookies for product analytics to improve OmniAtlas. See our Privacy Policy.