Skip to main content

Command Palette

Search for a command to run...

Secure Git Automation for Claude Code with Dev Containers and Fine-Grained PATs

Leverage autonomous AI agents securely using a dedicated GitHub machine user account with fine-grained, project-scoped PATs to automate Claude Code in workspace isolated VS Code Dev Containers.

Updated
7 min readView as Markdown
Secure Git Automation for Claude Code with Dev Containers and Fine-Grained PATs
J
Hi there! I'm a Cloud Engineer & SRE, documenting my transition into AI/ML Platform Engineering. I write technical deep-dives, hands-on implementation guides, CLI helper scripts, and visual architectures covering cloud, infrastructure, orchestration, governance, and modern AI runtimes.

Overview

AI Agents like Claude Code require terminal access to run builds, tests, and git commands. Running them directly on your host machine opens you up to the possibility of an agent executing a rogue script, prompt injection, host system file deletion or running commands that could access secrets saved in ~/.aws or ~/.ssh. Allowing them access to your personal GitHub credentials means the agent can read/write to any of your GitHub repositories.

While AI Agents offer an incredible productivity boost, they are not without risk. To balance security against velocity, it helps to establish four key isolation boundaries:

  • Host Isolation: The agent operates inside a Docker container. The host file system, local SSH keys, and personal credentials should never be mounted or exposed.

  • Identity Isolation: The agent acts as a dedicated GitHub "machine user" and member to the Organization hosting the repo.

  • Credential Isolation: Git operations use an Organization-scoped Fine-Grained PAT restricted to a single repository, scoped to Contents and Pull Requests read/write access.

  • Data Isolation: Claude Code’s session data (.claude/) is isolated inside a named Docker volume and ignored by Git.

We can run AI Agents reliably and with some safety measures by implementing these isolation boundaries and pairing them with these tools:

  • Dedicated GitHub Machine User to separate agent identity from human accounts.

  • Organization-Scoped Fine-Grained PAT to restrict repository access to minimum required permissions.

  • VS Code Dev Containers to provide a consistent, sandbox environment that provides a layer of isolation to host resources.

Pre-requisites

  • VS Code Dev Containers extension installed. Search for it on the marketplace.

  • Docker Desktop or Orbstack (MacOS) installed

Machine User & Fine-Grained Token Pattern

Organization & Machine User Setup

If you haven't already:

  1. Create a free GitHub Organization and transfer your target repository into it.

  2. Ensure Fine-Grained Personal Access Tokens are enabled under Organization Settings.

  3. Invite your dedicated Machine User to the Organization and grant it Write / Collaborator access to the target repository. If you're a Gmail user you can setup your machine user with an alias using: your_gmail+machine_user_name@gmail.com

Issuing the Fine-Grained PAT

Log into GitHub as your Machine User and navigate to Settings > Developer Settings > Personal Access Tokens > Fine-grained tokens. Generate a token using these settings:

Setting

Value

Why It Matters

Resource Owner

Organization

Ensures the token is governed by organizational policies.

Repository Access

Selected repositories

Prevents the token from accessing any other repos in the Org.

Repository Permissions

Contents: Read and write
Pull Requests: Read and write

Grants only what Claude Code needs to push code and open PRs. If you want Claude to create issues, enable those also.

Machine User Token Helper Script

Store Tokens in a Secure Host Folder

Keep all project tokens centrally on your host outside of any Git repository. Name the tokens after your repo-specific names:

~/.gh-tokens/
├── project-a.token
├── project-b.token
└── project-c.token

Create a Shell Alias on Your Host (~/.zshrc / ~/.bashrc)

Add a simple launcher helper function to your host shell profile. Update the GH env vars to match the name of your machine user created in the previous step.

# Dev container token helper
dev-agent() {
  local project_name=$(basename "$PWD")
  local token_file="$HOME/.gh-tokens/${project_name}.token"

  if [ -f "$token_file" ]; then
    export GH_TOKEN=$(cat "$token_file")
    export GIT_AUTHOR_NAME="machine-username"
    export GIT_AUTHOR_EMAIL="machine-username@users.noreply.github.com"

    echo "Loaded project-scoped credentials for ${project_name}"
  else
    echo "Warning: No token file at ${token_file}. Launching with local host inherited credentials."
    unset GH_TOKEN; unset GIT_AUTHOR_NAME; unset GIT_AUTHOR_EMAIL
  fi

  code .
}
💡
You could also create a dev-agent-cli function by installing the dev containers cli with npm install -g @devcontainers/cli and replacing the code command with devcontainer up --workspace-folder .

Setting Up the Dev Container

Create devcontainer.json

Save the following configuration as .devcontainer/devcontainer.json in your repository:

{
  "name": "Claude Agent Workspace (Base Bookworm)",
  "build": {
    "dockerfile": "Dockerfile"
  },
  "features": {
    "ghcr.io/devcontainers/features/github-cli:1": {},
    "ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {},
  },
  // Drop capabilities and block privilege escalation
  "runArgs": [
    "--cap-drop=ALL",
    "--security-opt=no-new-privileges"
  ],
  "mounts": [
    "source=claude-code-config-${devcontainerId},target=/home/vscode/.claude,type=volume"
  ],
  "containerEnv": {
    "CLAUDE_CONFIG_DIR": "/home/vscode/.claude"
  },
  "remoteEnv": {
    "GH_TOKEN": "${localEnv:GH_TOKEN}",
    "GIT_AUTHOR_NAME": "${localEnv:GIT_AUTHOR_NAME}",
    "GIT_AUTHOR_EMAIL": "${localEnv:GIT_AUTHOR_EMAIL}"
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "anthropic.claude-code",
        "shd101wyy.markdown-preview-enhanced"
      ]
    }
  },
  "postCreateCommand": "git config --global user.name \"$GIT_AUTHOR_NAME\" && git config --global user.email \"$GIT_AUTHOR_EMAIL\" && gh auth setup-git",
  "remoteUser": "vscode",
}
  • The claude-code-config-${devcontainerId} mount maps the container path to a persistent, named Docker volume.

  • The ${devcontainerId} keeps credentials scoped to the Docker volume of the launched container. Moving or renaming the local project folder, will cause it to evaluate a new hash, creating a new named volume that forces re-authentication.

  • The CLAUDE_CONFIG_DIR env var stores credentials, history and config files instead of the default ~./claude directory created by the root user.

Create Dockerfile

Save the following simple Dockerfile under .devcontainer/ in your repository:

FROM mcr.microsoft.com/devcontainers/base:bookworm

# Pre-create the directory under the non-root user so named volumes inherit ownership
USER vscode
RUN mkdir -p /home/vscode/.claude
  • You can use this as a base to iterate on depending on your workspace requirements.

  • Running as vscode (a non-root user) in the container allows you to run claude --dangerously-skip-permissions for fully autonomous workflows. However, as mentioned below, running AI Agents in Dev Containers still comes with risks.

Launch the agent Dev Container

💡 For a working example of a Full-Stack Claude Agent Workspace, you can check out my Dev Container setup here.

Whenever you start work on a project:

cd ~/code/project-a

dev-agent

# Working example:
❯ cd ai-dev-tools-zoomcamp-2026/
❯ dev-agent
Loaded project-scoped credentials for ai-dev-tools-zoomcamp-2026
  • Zero sensitive files in the workspace: There is no .envrc, .env, or configuration file inside the project for the agent to inspect.

  • Automatic project matching: dev-agent automatically picks up ~/.gh-tokens/ai-dev-tools-zoomcamp-2026.token based on the folder name, sets GH_TOKEN in that terminal session only, and opens VS Code.

  • Container Isolation: ${localEnv:GH_TOKEN} in devcontainer.json passes the token into the container environment seamlessly.

Verification Inside the Container

Once VS Code builds and opens the Dev Container, launch an integrated terminal inside the container and test the security boundaries:

whoami && id
sudo whoami
# Expected Output: vscode for the user identity, followed by a permission error on sudo.

gh auth status
gh api user --jq '.login'
# Expected Output: gh auth status confirms token authentication, and the API query returns the GitHub machine username.

git fetch origin
git var GIT_AUTHOR_IDENT
# Expected Output: Success. git fetch completes without prompt, and Git outputs the machine user name and email.

git clone https://github.com/your-org/another-private-repo.git /tmp/test-repo
# Expected Output: Failure. Returns HTTP 403 (Forbidden) or HTTP 404 (Not Found), confirming that the token cannot reach or manipulate repositories outside its explicit scope.

Conclusion

While Fine-Grained PATs prevent agents from deleting or reading your repos, and Dev Containers provide a helpful layer of workspace isolation, your host system can still be exposed to unpredictable code execution by AI Agents like Claude Code.

Dev Containers share the host kernel by design. If an AI agent encounters a malicious payload, prompt injection, or executes an unintended command, it is not prevented from:

  • Reading or modifying files mounted directly from your host filesystem.

  • Reaching out to arbitrary external IP addresses/URLs on the open internet.

  • Attempting container escapes via host IPC bridges or exposed Docker sockets.

While Dev Containers don't offer complete host isolation, they do provide a valuable layer of workspace isolation through reproducible, containerized environments. Combine them with a dedicated machine user and scoped, fine-grained PAT's and you get better visibility over your AI Agent's commits without compromising your developer experience.

Additional Resources

Further Exploration

  • Restricting Network Access via iptables / Egress Filtering: Applying custom devcontainer iptables rules or network proxies to restrict outbound URL access to whitelisted endpoints (e.g., only allowing traffic to Anthropic APIs and specific GitHub domains). Ref Anthropic's iptables example.

  • Hardware-Level Isolation with Dedicated Virtual Machines: Running Docker inside isolated local VMs (using tools like Lima on macOS, isolated WSL2 distros on Windows, or QEMU/KVM).

DevEx

Part 1 of 8

Focuses on hands-on developer experience, CLI utilities and tooling, agentic workflows, and real-world implementation guides. Features standalone administrative helper scripts (Boto3 SDK scripts, AWS search utilities, shell tools), local environment debugging, IaC state visualization tools, and agentic developer workflows (Cursor IDE setups, uv environments, custom MCP integrations).

Up next

AWS S3 Object Finder | Boto3 Script

Overview 🔎 Quickly find AWS S3 Objects inside buckets hosting huge volumes of files using my latest Boto3 script! You can easily locate specific objects in your AWS profile by providing a few command