Skip to content

Commit 78859fd

Browse files
authored
Persist gh cli authentication across container rebuilds (#67)
* Persist gh cli authentication across container rebuilds * Use GH CLI auth for GitHub MCP - Fixes error where the GitHub MCP fails to authenticate * Adds deny permissions to prevent destructive actions by claude * Update readme with gh permissions
1 parent 618eceb commit 78859fd

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

.claude/settings.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,41 @@
77
"permissions": {
88
"additionalDirectories": [
99
"/mnt/data/crucible"
10+
],
11+
"deny": [
12+
"Bash(gh api *)",
13+
"Bash(gh alias delete *)",
14+
"Bash(gh auth logout *)",
15+
"Bash(gh cache delete *)",
16+
"Bash(gh codespace delete *)",
17+
"Bash(gh codespace rebuild *)",
18+
"Bash(gh config clear-cache *)",
19+
"Bash(gh extension remove *)",
20+
"Bash(gh gist delete *)",
21+
"Bash(gh gpg-key delete *)",
22+
"Bash(gh issue delete *)",
23+
"Bash(gh issue transfer *)",
24+
"Bash(gh label delete *)",
25+
"Bash(gh project close *)",
26+
"Bash(gh project delete *)",
27+
"Bash(gh project field-delete *)",
28+
"Bash(gh project item-delete *)",
29+
"Bash(gh project item-archive *)",
30+
"Bash(gh release delete *)",
31+
"Bash(gh release delete-asset *)",
32+
"Bash(gh repo archive *)",
33+
"Bash(gh repo delete *)",
34+
"Bash(gh repo deploy-key delete *)",
35+
"Bash(gh repo rename *)",
36+
"Bash(gh repo transfer *)",
37+
"Bash(gh repo unarchive *)",
38+
"Bash(gh repo visibility *)",
39+
"Bash(gh run cancel *)",
40+
"Bash(gh run delete *)",
41+
"Bash(gh secret delete *)",
42+
"Bash(gh ssh-key delete *)",
43+
"Bash(gh variable delete *)",
44+
"Bash(gh workflow disable *)"
1045
]
1146
}
1247
}

.devcontainer/Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ setopt HIST_VERIFY # don't immediately execute recalled commands
105105
# DEVCONTAINER ZSH HISTORY END
106106
EOF
107107
108+
# Export GitHub token from gh CLI for MCP server auth
109+
RUN echo '' >> /home/vscode/.zshrc && \
110+
echo '# GitHub MCP token from gh CLI' >> /home/vscode/.zshrc && \
111+
echo 'export GITHUB_PERSONAL_ACCESS_TOKEN=$(gh auth token 2>/dev/null)' >> /home/vscode/.zshrc
112+
108113
# Switch back to vscode user
109114
USER vscode
110115

.devcontainer/devcontainer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
"source=crucible-dev-claude,target=/home/vscode/.claude,type=volume",
5050
// SSH keys and config
5151
"source=crucible-dev-ssh,target=/home/vscode/.ssh,type=volume",
52+
// GitHub CLI auth
53+
"source=crucible-dev-gh,target=/home/vscode/.config/gh,type=volume",
5254
// MSBuild files for local library development
5355
"source=${localWorkspaceFolder}/.devcontainer/msbuild/Directory.Build.props,target=/mnt/data/Directory.Build.props,type=bind",
5456
"source=${localWorkspaceFolder}/.devcontainer/msbuild/Directory.Build.targets,target=/mnt/data/Directory.Build.targets,type=bind"

README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Development Environment for [Crucible](https://github.com/cmu-sei/crucible) - a
1212
- [Launch Profiles](#launch-profiles)
1313
- [Default Credentials](#default-credentials)
1414
- [Claude Code](#claude-code)
15+
- [GitHub CLI](#github-cli)
1516
- [Memory Optimization](#memory-optimization)
1617
- [Intelephense PHP Extension](#intelephense-php-extension)
1718
- [UI Development vs Production Mode](#ui-development-vs-production-mode)
@@ -143,6 +144,87 @@ The config file is mounted to `/home/vscode/.aws/config` inside the container an
143144

144145
Once the container is running with valid credentials, run `claude` in the terminal to start Claude Code.
145146

147+
## GitHub CLI
148+
149+
The dev container includes the [GitHub CLI](https://cli.github.com/) (`gh`). The GitHub CLI's authentication is reused by the GitHub MCP server for agentic development.
150+
151+
### Authentication
152+
153+
GitHub CLI authentication is **persisted across container rebuilds** using a bind mount. Credentials stored via `gh auth login` are saved and automatically available inside the container after a rebuild.
154+
155+
To authenticate for the first time:
156+
157+
```bash
158+
gh auth login
159+
```
160+
161+
Follow the prompts to authenticate via browser or token.
162+
163+
### Recommended: Use a Fine-Grained Personal Access Token
164+
165+
We strongly recommend authenticating with a **fine-grained personal access token (PAT)** rather than a full OAuth login. Fine-grained PATs let you limit exactly what `gh` can do on your behalf.
166+
167+
**To create a fine-grained PAT:**
168+
169+
1. Go to **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens**
170+
2. Click **Generate new token**
171+
3. Set an expiration date
172+
4. Under **Repository access**, select only the repositories relevant to your work
173+
5. Under **Permissions**, grant only what you need — a reasonable read-heavy baseline:
174+
175+
| Permission | Access |
176+
|---|---|
177+
| Contents | Read-only |
178+
| Issues | Read and write |
179+
| Pull requests | Read and write |
180+
| Metadata | Read-only (required) |
181+
| Actions | Read-only |
182+
| Secrets | None |
183+
| Administration | None |
184+
185+
6. Click **Generate token**, copy it, then run:
186+
187+
```bash
188+
gh auth login --with-token <<< "your_token_here"
189+
```
190+
191+
> Avoid granting `Administration`, `Secrets`, or `Members` permissions — these allow destructive or sensitive operations that are unlikely to be needed during normal development.
192+
193+
### Claude Code Restrictions
194+
195+
To prevent accidental or unintended destructive actions, Claude Code has been configured to **deny** the following `gh` commands in `.claude/settings.json`:
196+
197+
**Raw API access**
198+
- `gh api` — bypasses all CLI safeguards; denied entirely
199+
200+
**Delete operations**
201+
- `gh alias delete`, `gh cache delete`, `gh codespace delete`
202+
- `gh extension remove`, `gh gist delete`, `gh gpg-key delete`
203+
- `gh issue delete`, `gh label delete`
204+
- `gh project delete`, `gh project field-delete`, `gh project item-delete`, `gh project item-archive`
205+
- `gh release delete`, `gh release delete-asset`
206+
- `gh repo delete`, `gh repo deploy-key delete`
207+
- `gh run delete`, `gh secret delete`, `gh ssh-key delete`, `gh variable delete`
208+
209+
**Repository state changes**
210+
- `gh repo archive`, `gh repo unarchive`
211+
- `gh repo rename`, `gh repo transfer`
212+
- `gh repo visibility` — prevents accidentally making a private repo public
213+
214+
**Operational disruption**
215+
- `gh run cancel` — halts CI runs
216+
- `gh workflow disable` — disables automation
217+
- `gh issue transfer` — moves issues to other repos
218+
- `gh codespace rebuild` — destroys current codespace state
219+
220+
**Credential operations**
221+
- `gh auth logout` — removes stored credentials
222+
- `gh config clear-cache` — wipes cached auth data
223+
224+
Claude will be blocked from running any of the above and will need to ask you to run them manually if they are genuinely required.
225+
226+
227+
146228
## Memory Optimization
147229

148230
The Crucible development environment includes 30+ microservices and can be memory-intensive. Several optimizations are configured to reduce memory usage:

0 commit comments

Comments
 (0)