Devsecops/developer machine sandboxing#481
Devsecops/developer machine sandboxing#481ElliotFriedman wants to merge 18 commits intosecurity-alliance:developfrom
Conversation
Visual security posture dashboard showing 12 attack vectors as a radial diagram. Nodes are color-coded (red/amber/green) by posture state with click-to-toggle and localStorage persistence. Clicking a node opens a detail card with description, attack tags, and framework guide links. Designed for CSOs to quickly assess and communicate security gaps. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds dev: true flag to sidebar entry per contributing guidelines. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Selected nodes now scale up 10% and show a soft color-matched glow instead of a detached ring outline. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Posts an automated PR comment when threatData.ts is modified, reminding contributors to include all required fields and verify framework links. Follows the same pattern as the existing vocs-config-reminder workflow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clicking a node on the radial map showed the detail card below the map, but on typical viewports the card landed below the fold, so it wasn't obvious anything had happened. Use scrollIntoView with block: "nearest" on the card when it mounts or the selected vector changes, respecting prefers-reduced-motion. Third PR feedback item addressed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moved the page to sit alongside the other Introduction pages. Updated sidebar link, internal cross-link in how-to-navigate, and component import path to match the new location. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The detail card's framework link used a plain <a> tag which caused a full page reload. Switched to react-router-dom's <Link> for client-side navigation, consistent with the rest of the site. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds TagProvider, TagFilter, TagList, and ContributeFooter to match the pattern used by all other Introduction pages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Elliot <elliotfriedman3@gmail.com>
Signed-off-by: Elliot <elliotfriedman3@gmail.com>
Signed-off-by: Elliot <elliotfriedman3@gmail.com>
Signed-off-by: Elliot <elliotfriedman3@gmail.com>
Sidebar Configuration ReminderThis PR includes added, renamed, or removed documentation files:
Please ensure that:
See Contributing Guide – Sidebar & Navigation for more details. This is an automated reminder. If this PR doesn't need sidebar changes, you can ignore this message. |
scode2277
left a comment
There was a problem hiding this comment.
Very needed addition @ElliotFriedman!
Left one comment about Claude Code and a small needed change regarding your username :)
| - DevOps | ||
| contributors: | ||
| - role: wrote | ||
| users: [elliot] |
There was a problem hiding this comment.
| users: [elliot] | |
| users: [ElliotFriedman] |
| - **Regular permissions**: every bash command still goes through the standard approval flow, but OS-level filesystem and network restrictions are still enforced. This adds more friction, but results in better system security properties. | ||
|
|
||
| Start with auto-allow. You can tighten it per-project via settings. | ||
|
|
||
| **Step 3: harden the project config** (`.claude/settings.json`): | ||
|
|
||
| ```json | ||
| { | ||
| "sandbox": { | ||
| "enabled": true, | ||
| "failIfUnavailable": true, | ||
| "allowUnsandboxedCommands": false, | ||
| "filesystem": { | ||
| "denyRead": ["~/"], | ||
| "allowRead": ["."], | ||
| "allowWrite": ["/tmp/build"] | ||
| }, | ||
| "network": { | ||
| "allowedDomains": [ | ||
| "registry.npmjs.org", | ||
| "api.github.com", | ||
| "crates.io" | ||
| ] | ||
| } | ||
| }, | ||
| "permissions": { | ||
| "deny": ["Read(.env)"] | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| - `failIfUnavailable: true`: hard-fails if the sandbox can't start, rather than silently running without isolation | ||
| - `allowUnsandboxedCommands: false`: closes the built-in escape hatch that lets Claude retry a failing command outside the sandbox | ||
| - `denyRead: ["~/"]`: blocks reads from your home directory; SSH keys and shell history are invisible to the agent | ||
| - `allowRead: ["."]`: restores read access to the current project root (inside the denied region) | ||
| - `allowWrite: ["/tmp/build"]`: if a build tool needs to write outside the working directory, grant it here specifically | ||
| - `allowedDomains`: explicit egress allowlist; omit anything you don't actively need | ||
| - `permissions.deny`: blocks Claude's file tools from reading specific sensitive paths. Note that `allowRead` takes precedence over `denyRead` within the sandbox, so project-root secrets like `.env` need to be excluded here instead |
There was a problem hiding this comment.
From my research, i think the permissions.deny: ["Read(.env)"] line could give readers a false sense of security for .env specifically. That rule blocks Claude's built-in Read tool, but cat .env from a bash subprocess goes through the sandbox layer and isn't affected (docs: https://code.claude.com/docs/en/sandboxing -> "built-in file tools use the permission system directly rather than running through the sandbox").
The tricky part is that the obvious fix (adding ./.env to denyRead) doesn't quite work either, because allowRead takes precedence over denyRead in the sandbox as it's a deny-then-allow pattern). So with allowRead: ["."], anything under the project root is readable regardless of what denyRead says.
A few ways we can say it:
- Reframe the example so
denyReadonly protects paths outside the project (~/.ssh,~/.aws, etc.), where the pattern works as documented, and use a separate mechanism for in-tree secrets. - Add an explicit
Bash(cat .env)deny alongside theRead(.env)one, with the same fragility caveat already stated in the limitations section. - Note in the bullet that the two layers protect different vectors (Read tool vs. bash subprocesses) rather than redundant coverage of the same one.
There was a problem hiding this comment.
Good catch, the boundaries are distinct, and the setup likely needs to be tailed to the specific user needs and setup. Just addressed the feedback in the latest commit.
frameworks-volunteer
left a comment
There was a problem hiding this comment.
Model: z-ai/glm-5.1 Reasoning: high Provider: openrouter
Review of PR #481 — Developer Machine Sandboxing.
Security Review
No issues found. No secrets, no injection vectors, no unsafe patterns. Content is documentation only (MDX), no executable code changes.
QA Review
What's good:
- All 6 external reference links return 200
- Sidebar config (vocs.config.tsx), isolation index, and overview page all link to the new page
- Frontmatter format matches existing pages (title, description, tags, contributors)
- Content is accurate, well-structured, and honest about limitations
- Threats table is clear and actionable
- Code examples (settings.json, config.toml, devcontainer.json) are practical
Minor issues:
-
Line 23: "company ending mistakes" should be "company-ending mistakes" (missing hyphen on compound adjective)
-
The PR bundles unrelated changes alongside the new page: governance-proposal-security additions to index.mdx, and VPN/certs/front-end entries in fetched-tags.json. These should ideally be separate PRs for cleaner history, though this is a convention concern, not a correctness one.
Verdict: Approve with minor suggestions. The content is solid and the security guidance is accurate.
Signed-off-by: Elliot <elliotfriedman3@gmail.com>
built with Refined Cloudflare Pages Action⚡ Cloudflare Pages Deployment
|
|
@frameworks-volunteer, how would you link the AI Security (/ai-security) framework with this section? Do they overlap somehow? |
|
Model: Good question. There is overlap, and it's intentional — the architecture separates why (AI Security) from how (DevSecOps isolation). How they connect today: The AI Security section already has a bridge page at
Where this PR's page fits: The new Developer Machine Sandboxing page sits in Missing link: The bridge page Summary: The overlap is by design — AI Security describes the threats, DevSecOps isolation provides the mitigations. The new page belongs in DevSecOps (it's practical config, not threat modeling), but the bridge page should be updated to link to it so AI Security readers can find it. |
|
@frameworks-volunteer Would you kindly suggest a new section that would go below the new proposed contents, after Claude, for opencode (opencode.ai) and Hermes agent (from NousResearch)? No larger than those sections, and similar in contents but with their own thing. For example, Hermes agents allows you to run commands through a remote machine, a docker container, modal, daytona, gVisor... you can pick the backend when you start hermes and configure it at any point. Similarly for opencode, you have plugins like daytona or devcontainers that allow you to do similar things. Put it here as a comment, do not create a new PR for this |
|
Model: Here are suggested sections for OpenCode and Hermes Agent, matching the existing Claude Code / Codex CLI format and length. These would go after the Codex CLI section and before the VS Code dev containers section. OpenCode: sandboxed backends via pluginsOpenCode (opencode.ai) is a terminal-based AI coding agent that delegates command execution to pluggable backends. Instead of running commands directly on the host, OpenCode routes them through a sandbox provider — similar to how an IDE delegates to a language server. This separation means the agent process itself never touches the host filesystem or network; only the backend does, and the backend runs in an isolated environment. Available sandbox backends:
Configuration ( {
"sandbox": {
"provider": "daytona",
"daytona": {
"server": "https://daytona.example.com",
"profile": "sandboxed"
}
}
}Switch backends at any time with Limitations
Hermes Agent: pluggable execution backendsHermes Agent (Nous Research) is a multi-modal AI agent that supports multiple execution backends for running shell commands and tool operations. You select the backend when starting a session and can reconfigure it at any point. The agent process communicates with the backend over a defined interface; the backend decides where and how commands execute. Available backends:
Configuration ( execution:
backend: docker
docker:
image: hermes-sandbox:latest
cap_drop: [ALL]
security_opt: [no-new-privileges]
network_mode: none
volume_mounts:
- "./:/workspace"Switch backends mid-session with Limitations
For the References section, consider adding: |
|
@frameworks-volunteer, how would you update, if you would, @ElliotFriedman's content based on the comment below? Take a look at the article, and decide whether it makes sense to add a clarification or create a new entire category about VScode. Comment I added previously: |
|
Model: I read the full article. My recommendation: add a clarification, not a new category. Here's why, and what I'd add: Why not a new category: The article's findings all pertain to VS Code's Remote extension and how it undermines devcontainer isolation. That is specifically about the trust model of the tool this PR's VS Code section already covers. A separate "VS Code Internals" or "VS Code Remote Extension Risks" category would fragment what should be a single cohesive warning: dev containers are not security sandboxes, and the Remote extension that makes them work is itself the biggest escape vector. The current section already says "Dev containers aren't designed as security sandboxes; convenience shortcuts dominate the defaults" -- but it understates the problem. What to add -- a new subsection under "Limitations": I'd insert a subsection called something like "The Remote extension trust model" (after the existing three bullet points) that covers the key findings from the article. Here's draft content: The Remote extension trust modelThe Dev Containers extension works by deploying a
Mitigations: "remoteEnv": {
"SSH_AUTH_SOCK": "",
"GPG_AGENT_INFO": "",
"GNUPGHOME": "/tmp/gnupg",
"GIT_ASKPASS": ""
},
"settings": {
"remote.containers.copyGitConfig": false
}These disable the default socket forwarding and git config copy. They do NOT address the TerminalService RCE path -- that requires trusting every extension installed in the workspace. Also add to References:
One broader point: The existing intro paragraph says "The container only sees what you explicitly mount. SSH keys, AWS credentials, and anything else under Summary: expand the existing VS Code section's limitations with a focused subsection on the Remote extension trust model, add the references, and fix the misleading intro claim. No new category needed. |
Changes
Adds a new Developer Machine Sandboxing page under the Isolation & Sandboxing section, covering practical sandboxing configurations for Claude Code, Codex CLI, and VS Code dev containers.
The page covers:
settings.jsonwith filesystem and network restrictions, and known limitationsworkspace-write+on-request) and how to persist them inconfig.tomldevcontainer.jsonand the three default footguns to fix (passwordless sudo, Docker socket mount,--network=nonevs egress proxy)Also adds a link to the new page from the DevSecOps overview.
Checklist
vocs.config.tsupdated —developer-machine-sandboxingentry already present under Isolation sidebar; nodev: trueneedednpx just lintto confirm