Skip to content

Commit c3a84e5

Browse files
stranmaclaude
andcommitted
fix: address CodeRabbit review feedback
- Move gh api from allow to ask (exfiltration risk via raw API calls) - Add git push --force/--f to deny list (remote repo is not disposable) - Remove stale tier references from settings.local.json.example - Fix P.3.2 reference to deleted agent in DEVELOPMENT_PROCESS.md - Update test expectations for gh api and force push changes Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
1 parent f266946 commit c3a84e5

4 files changed

Lines changed: 13 additions & 12 deletions

File tree

.claude/settings.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"Bash(git describe *)", "Bash(git shortlog *)", "Bash(git rev-list *)",
2020
"Bash(gh pr create *)", "Bash(gh pr view *)", "Bash(gh pr list *)",
2121
"Bash(gh pr checks *)", "Bash(gh pr diff *)", "Bash(gh pr edit *)",
22-
"Bash(gh pr close *)", "Bash(gh api *)",
22+
"Bash(gh pr close *)",
2323
"Bash(gh run list *)", "Bash(gh run view *)", "Bash(gh run watch *)",
2424
"Bash(gh issue list *)", "Bash(gh issue view *)",
2525
"Bash(gh repo view *)", "Bash(gh release list *)", "Bash(gh release view *)",
@@ -32,6 +32,7 @@
3232
],
3333
"deny": [
3434
"Bash(gh secret *)", "Bash(gh auth *)", "Bash(gh ssh-key *)", "Bash(gh gpg-key *)",
35+
"Bash(git push --force *)", "Bash(git push -f *)",
3536
"Bash(git clean *)", "Bash(git config *)",
3637
"Bash(*git remote add *)", "Bash(*git remote set-url *)", "Bash(*git remote remove *)",
3738
"Bash(*git remote rename *)", "Bash(*git remote set-head *)",
@@ -43,6 +44,7 @@
4344
"Bash(gh pr merge *)", "Bash(gh pr reopen *)", "Bash(gh pr comment *)",
4445
"Bash(gh pr review *)", "Bash(gh pr ready *)", "Bash(gh workflow run *)",
4546
"Bash(gh workflow enable *)", "Bash(gh workflow disable *)",
47+
"Bash(gh api *)",
4648
"Bash(gh issue create *)", "Bash(gh issue comment *)",
4749
"Bash(gh issue close *)", "Bash(gh issue edit *)",
4850
"Bash(git init *)", "Bash(git clone *)",

.claude/settings.local.json.example

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,7 @@
55
"Precedence: global < project settings.json < settings.local.json",
66
"Use this for: local hook overrides, extra permissions, MCP server configs"
77
],
8-
"__devcontainer_tiers": [
9-
"In devcontainers, this file is auto-generated from .devcontainer/permissions/tier{1,2,3}.json.",
10-
"Set PERMISSION_TIER env var before building (default: 2).",
11-
" Tier 1 (Assisted): File ops auto-allowed, bash asks per-command",
12-
" Tier 2 (Autonomous): Bash(*) with curated deny list -- zero prompts",
13-
" Tier 3 (Full Trust): Bash(*) with minimal deny -- requires branch protection",
14-
"See docs/DEVCONTAINER_PERMISSIONS.md for full details."
15-
],
8+
"__note": "In devcontainers, settings.json is the single baseline for all environments.",
169

1710
"hooks": {
1811
"PreToolUse": [],

docs/DEVELOPMENT_PROCESS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ next phase for P-scope work.
120120

121121
**P.3 Execute** (repeat per phase)
122122
1. Run Standard Path (S.1 through S.7) for the phase
123-
2. Update `docs/IMPLEMENTATION_PLAN.md` (use built-in `Plan` agent)
123+
2. Update `docs/IMPLEMENTATION_PLAN.md`
124124
3. Write phase handoff note (2-5 sentences: what completed, deviations, risks, dependencies, intentional debt)
125125

126126
**P.4 Finalize** -- Merge. Version bump and changelog consolidation if applicable.

tests/test_permissions.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,11 @@ def test_git_config_is_denied(self, settings: dict[str, Any]) -> None:
302302
def test_uv_self_is_denied(self, settings: dict[str, Any]) -> None:
303303
assert evaluate("Bash(uv self update)", settings) == "deny"
304304

305+
def test_git_push_force_is_denied(self, settings: dict[str, Any]) -> None:
306+
"""Force push affects the remote repo (not disposable) -- must be denied."""
307+
assert evaluate("Bash(git push --force origin main)", settings) == "deny"
308+
assert evaluate("Bash(git push -f origin main)", settings) == "deny"
309+
305310
def test_rm_rf_is_not_allowed(self, settings: dict[str, Any]) -> None:
306311
assert evaluate("Bash(rm -rf /)", settings) != "allow"
307312

@@ -440,8 +445,9 @@ def test_web_fetch_requires_confirmation(self, settings: dict[str, Any]) -> None
440445
def test_chained_commands_fall_through(self, settings: dict[str, Any]) -> None:
441446
assert evaluate("Bash(cd /foo && ls)", settings) == "none"
442447

443-
def test_gh_api_is_allowed(self, settings: dict[str, Any]) -> None:
444-
assert evaluate("Bash(gh api repos/owner/repo/pulls)", settings) == "allow"
448+
def test_gh_api_requires_confirmation(self, settings: dict[str, Any]) -> None:
449+
"""gh api can create gists/issues -- requires confirmation to prevent exfiltration."""
450+
assert evaluate("Bash(gh api repos/owner/repo/pulls)", settings) == "ask"
445451

446452
def test_gh_pr_review_operations_require_confirmation(self, settings: dict[str, Any]) -> None:
447453
"""PR comment/review/ready are state-changing and have data exfiltration risk."""

0 commit comments

Comments
 (0)