Omnidev

    • Docs
    • About

Getting Started

  • Quick Start
  • Environment Setup
  • Docker Setup
  • Railway
  • Ralph CLI

Coolify

  • Ports & routing
  • Remote MCP

Security

  • Secure Deployment
  • Sandbox Architecture
  • Sandbox Quick Reference
  • Credentials Management
  • Password Reset

API

  • API Operations
  • API Authentication

Features

  • Merge Request Automation

Integrations

  • n8n Workflows
  • n8n Templates
  • n8n Async Patterns
  • Prompt Templates
© 2026 Omnidev. All rights reserved.

Sandbox Quick Reference

Quick reference for sandbox features. Test and verify security measures in your Omnidev deployment.

Sandbox Quick Reference

Commands below use the production Compose container name omnidev-app (container_name in docker/docker-compose.prod.yml). In development the container is often omnidev-dev. Run docker compose -f docker/docker-compose.yml ps to see the actual name on your machine.

TL;DR

Git is blocked for Claude Code, everything else is accessible.

  • ❌ Claude Code CANNOT run git commands
  • ✅ Claude Code CAN use rm, curl, wget, npm, and all other tools
  • ✅ Your app has FULL access to git via /opt/internal/bin/git

How It Works

For Claude Code

In Claude Code's context:

git --version

Output: [BLOCKED] git access denied

curl --version

Output: curl 7.x.x (works normally)

rm file.txt

Works normally

For Your Application

In your Next.js app:

import { createSandboxedGit } from '@/lib/git/sandbox';

const git = createSandboxedGit('/app/workspaces/repo');
await git.clone('https://...', '/app/workspaces/repo');

Works perfectly - uses /opt/internal/bin/git

File Locations

WhatWhereWho Can Access
Real git binary/opt/internal/bin/gitApp only
Git wrapper (blocker)/usr/bin/gitEveryone (returns error)
Claude Code wrapper/usr/local/bin/claude-code-wrapperApp (to run Claude)
Standard tools/usr/bin/*, /bin/*Everyone

Running Claude Code (Sandboxed)

From Your App

The execution module automatically uses the wrapper (defaults defined in code):

const result = await askClaudeCode('Analyze this code', {
  workingDirectory: '/app/workspaces/my-repo',
  workspaceId: '123',
});

Manual Testing (Inside Container)

Sandboxed execution:

/usr/local/bin/claude-code-wrapper /app/workspaces/repo -p "hello"

What happens:

  1. Changes to /app/workspaces/repo
  2. Removes /opt/internal/bin from PATH
  3. Nullifies all git env vars
  4. Runs: claude-code -p "hello"
  5. Claude Code sees git as blocked

Verification

Automated (CI/CD)

The sandbox is automatically verified in the GitLab CI/CD pipeline:

  • Stage: docker-test
  • Job: docker-sandbox-verify
  • When: On every push to master/main and merge requests
  • Tests:
    • ✓ Git blocking verification
    • ✓ Internal git accessibility
    • ✓ Standard tools accessibility (curl, wget)
    • ✓ Full verification script execution

View results in your GitLab pipeline → docker-test stage → docker-sandbox-verify job

Quick Test (Inside Container)

Test git blocking:

docker exec omnidev-app git --version

Expected: [BLOCKED] git access denied

Test internal git:

docker exec omnidev-app /opt/internal/bin/git --version

Expected: git version 2.x.x

Test standard tools (should work):

docker exec omnidev-app curl --version

Expected: curl 7.x.x

Full Verification

Run comprehensive sandbox tests:

docker exec omnidev-app /app/scripts/verify-sandbox.sh

Common Scenarios

Scenario 1: Claude Code Needs to Download Dependencies

Claude Code can do this:

curl -O https://example.com/file.zip
wget https://cdn.example.com/library.tar.gz
npm install
pip install -r requirements.txt

✅ All work normally

Scenario 2: Claude Code Tries to Commit Changes

Claude Code tries:

git add .
git commit -m "changes"

❌ Blocked - returns error message

Scenario 3: Your App Manages Git Workflow

Your app does:

const git = createSandboxedGit(workspacePath);
await git.add('.');
await git.commit('Changes from Claude Code analysis');
await git.push();

✅ Works perfectly - app has full git access

Troubleshooting

Problem: "git not found" in app

Solution: Check that simple-git is using the internal binary:

import { verifyGitBinary } from '@/lib/git/sandbox';
const isOk = await verifyGitBinary();
console.log('Git accessible:', isOk);

Problem: Claude Code still runs git

Solution: Verify git is blocked:

docker exec omnidev-app git --version

Should output: [BLOCKED] git access denied

Problem: Claude Code can't download files

Solution: This is NOT expected. Verify curl/wget are not blocked:

docker exec omnidev-app curl --version

Should work normally, NOT be blocked

Architecture Summary

┌────────────────────────────────────────────┐
│           Docker Container                 │
│                                            │
│  /usr/bin/git ────────┐                    │
│  (blocking script)    │                    │
│                       ▼                    │
│                 [BLOCKED]                  │
│                       ▲                    │
│                       │                    │
│                 Claude Code                │
│                 (tries git)                │
│                                            │
│  /opt/internal/bin/git ────┐               │
│  (real binary)             │               │
│                            ▼               │
│                       Your App             │
│                    (uses git ✓)            │
│                                            │
└────────────────────────────────────────────┘

Security Checklist

  • /usr/bin/git is a blocking script
  • /opt/internal/bin/git exists and works
  • Wrapper script at /usr/local/bin/claude-code-wrapper
  • Application uses createSandboxedGit() for all git ops
  • Verification script passes all tests

Quick Commands

Build with sandbox:

docker compose -f docker/docker-compose.yml build

Run with sandbox enabled:

docker compose -f docker/docker-compose.yml up -d

Verify sandbox:

docker exec omnidev-app /app/scripts/verify-sandbox.sh

Check git blocking:

docker exec omnidev-app git --version

Check internal git:

docker exec omnidev-app /opt/internal/bin/git --version

View logs:

docker logs omnidev-app | grep CLAUDE

Shell into container:

docker exec -it omnidev-app bash

Key Files

  • src/web/Dockerfile - Lines 20-31: Git isolation setup
  • docker/docker-compose.yml - Lines 20-25: Sandbox environment vars
  • claude-code-wrapper.sh - Sandboxed execution wrapper
  • src/lib/git/sandbox.ts - Sandboxed git configuration
  • src/lib/git/core.ts - Uses sandboxed git
  • src/lib/claudeCode/execution.ts - Uses wrapper when sandboxed
  • scripts/verify-sandbox.sh - Verification tests
  • Sandbox Architecture - Full documentation

Need Help?

  1. Read full docs: Sandbox Architecture
  2. Run verification: docker exec omnidev-app /app/scripts/verify-sandbox.sh
  3. Check logs: docker logs omnidev-app | grep -i "sandbox\|git\|claude"
  4. Test manually: docker exec -it omnidev-app bash

Last Updated: 2025-11-25

PreviousSandbox ArchitectureNextCredentials Management

On this page

  • Sandbox Quick Reference
  • TL;DR
  • How It Works
  • File Locations
  • Running Claude Code (Sandboxed)
  • Verification
  • Common Scenarios
  • Troubleshooting
  • Architecture Summary
  • Security Checklist
  • Quick Commands
  • Key Files
  • Need Help?