| title | Grant GitHub Push Access to a Sandboxed Agent |
|---|---|
| sidebar-title | GitHub Push Access |
| slug | tutorials/github-push-access |
| description | Launch an agent with a GitHub provider, diagnose a denied push, and grant repository-scoped write access. |
| keywords | Generative AI, Cybersecurity, Tutorial, GitHub, Sandbox, Policy, Claude Code |
This tutorial shows how provider access and sandbox policy work together. You attach a GitHub provider that contributes read-only GitHub access, observe a denied push, and add a user policy that permits writes to one repository.
The built-in default policy does not grant network access. Imported provider profiles contribute the endpoints and executable paths needed by their providers.
You need:
- A working OpenShell installation and active gateway.
- An OCI image you built with Claude Code,
git, and the GitHub CLI installed. - An Anthropic API key.
- A GitHub fine-grained personal access token with read and write access to the target repository's contents.
- A scratch GitHub repository that you can push to.
Use two host terminals. Terminal 1 runs the agent. Terminal 2 inspects denials and updates policy.
Review the Claude Code profile
and GitHub profile.
Confirm that their binaries paths match the executables in your image, then
import them directly. If a path or endpoint grant needs to change, edit a local
copy and import it with -f instead.
openshell profile import --url https://raw.githubusercontent.com/NVIDIA/OpenShell/main/providers/claude-code.yaml --global
openshell profile import --url https://raw.githubusercontent.com/NVIDIA/OpenShell/main/providers/github.yaml --globalThe gateway contains no built-in profiles. Import each profile once per gateway at the scope where users need it.
Create provider instances from credentials in your host environment. Passing a credential on the same command line exports it only to that command:
ANTHROPIC_API_KEY=<your-anthropic-key> \
openshell provider create --name my-claude --type claude-code --from-existing
GITHUB_TOKEN=<your-github-token> \
openshell provider create --name my-github --type github --from-existingOpenShell stores the credentials through the configured credential driver. The agent receives opaque placeholders; the sandbox proxy resolves them only for endpoints allowed by the corresponding profile.
In terminal 1, start Claude Code from your image and attach both providers:
openshell sandbox create \
--name github-demo \
--from registry.example.com/your-org/claude-agent:latest \
--provider my-claude \
--provider my-github \
-- claudeTo use an existing sandbox, attach the providers from a host terminal, then start a new agent process so it receives the provider environment variables:
openshell sandbox provider attach <sandbox-name> my-claude
openshell sandbox provider attach <sandbox-name> my-github
openshell sandbox connect <sandbox-name>Ask the agent to create a file and push it to your scratch repository. Replace
<org> and <repo> with the repository owner and name:
Create `hello_world.py`, commit it, and push it to
`https://github.com/<org>/<repo>.git`. Use the GitHub credentials already
available in the environment. Do not ask me to paste a token.The push fails. The GitHub profile permits clone and fetch operations but does
not permit git-receive-pack, the Git Smart HTTP operation used for a push.
The credential remains attached and endpoint-scoped; changing the token would
not grant the missing network authority.
In terminal 2, inspect recent sandbox logs:
openshell logs github-demo --since 5m --source sandboxYou should see a denial for a request resembling this one:
[1775014140.412] [sandbox] [OCSF ] [ocsf] HTTP:POST [MED] DENIED POST http://github.com:443/<org>/<repo>.git/git-receive-pack [policy:_provider_my_github engine:l7] [reason:L7_REQUEST deny POST github.com:443/<org>/<repo>.git/git-receive-pack reason=POST /<org>/<repo>.git/git-receive-pack not permitted by policy]
_provider_my_github is the rule that OpenShell composes from the attached
my-github provider. Policy events are INFO-level log records, so do not filter
them out with --level warn.
You can also run openshell term to inspect policy decisions in the terminal
dashboard.
policy set replaces the complete base policy, so start from the sandbox's
current one. In terminal 2, print it:
openshell policy get github-demo --baseThe command prints revision details followed by the policy. Save only the policy
YAML as github-push.yaml. Keep its filesystem, Landlock, and process settings
unchanged, because OpenShell rejects removed filesystem paths and changed
Landlock or process settings on a running sandbox.
Add these entries under network_policies, creating the section if it is
missing. Replace <org> and <repo>, and adjust binaries to match your
image:
network_policies:
github_repository_push:
name: github-repository-push
endpoints:
- host: github.com
port: 443
protocol: rest
enforcement: enforce
rules:
- allow:
method: GET
path: "/<org>/<repo>.git/info/refs*"
- allow:
method: POST
path: "/<org>/<repo>.git/git-upload-pack"
- allow:
method: POST
path: "/<org>/<repo>.git/git-receive-pack"
binaries:
- path: /usr/bin/git
- path: /usr/local/bin/git
github_repository_api:
name: github-repository-api
endpoints:
- host: api.github.com
port: 443
protocol: rest
enforcement: enforce
rules:
- allow:
method: "*"
path: "/repos/<org>/<repo>/**"
binaries:
- path: /usr/bin/gh
- path: /usr/local/bin/ghThe first entry grants Git Smart HTTP operations only for the selected
repository. The second lets gh use REST operations scoped to the same
repository. The attached GitHub provider continues to supply credential
placement and its broader read-only rules.
Apply the policy and wait for the new revision to load:
openshell policy set github-demo --policy github-push.yaml --waitNetwork policy changes hot-reload without recreating the sandbox. Provider rules are composed with this user-authored base policy.
Ask the agent to retry the push. Then confirm that the proxy allowed the scoped request:
openshell logs github-demo --since 5m
openshell policy get github-demo --fullThe push succeeds for the selected repository. Requests to push to another repository remain denied.
Delete the sandbox when you are finished:
openshell sandbox delete github-demo- Review Profiles for endpoint-scoped credential placement.
- Review Manage Sandbox Policies for incremental policy updates and policy history.
- Review the Policy Schema for REST, GraphQL, and other protocol rules.