Skip to content

Commit 5cf554c

Browse files
authored
Block remote branch deletion and improve force push error messages (#39)
- Block `git push origin --delete` and colon-refspec deletion — deleting remote branches closes associated PRs, which is not recoverable - Block `--force-with-lease` — was bypassing the regex due to word boundary matching; all force push variants now blocked uniformly - Force push error message now suggests `git merge` as the correct workaround instead of leaving the agent to improvise - Fix README: error handling documented as "fails open" but code actually fails closed Co-authored-by: AnExiledDev <AnExiledDev@users.noreply.github.com>
1 parent 4e320ed commit 5cf554c

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
lines changed

.devcontainer/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
## [Unreleased]
44

5+
### Fixed
6+
7+
#### Dangerous Command Blocker
8+
- **Force push block now suggests `git merge` as workaround** — error message explains how to avoid diverged history instead of leaving the agent to improvise destructive workarounds
9+
- **Block `--force-with-lease`** — was slipping through regex; all force push variants now blocked uniformly
10+
- **Block remote branch deletion**`git push origin --delete` and colon-refspec deletion (`git push origin :branch`) now blocked; deleting remote branches closes associated PRs
11+
- **Fixed README** — error handling was documented as "fails open" but code actually fails closed; corrected to match behavior
12+
513
### Added
614

715
#### Documentation

.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ Inspects every Bash command Claude attempts to run against a set of dangerous pa
1414
| Privileged deletion | `sudo rm` |
1515
| World-writable permissions | `chmod 777`, `chmod -R 777` |
1616
| Force push to main/master | `git push --force origin main`, `git push -f origin master` |
17-
| Bare force push | `git push -f`, `git push --force` (no branch specified) |
17+
| Bare force push | `git push -f`, `git push --force`, `git push --force-with-lease` |
18+
| Remote branch deletion | `git push origin --delete`, `git push origin :branch` |
1819
| Git history destruction | `git reset --hard origin/main`, `git clean -f` |
1920
| System directory writes | `> /usr/`, `> /etc/`, `> /bin/`, `> /sbin/` |
2021
| Disk formatting | `mkfs.*`, `dd of=/dev/` |
@@ -47,7 +48,7 @@ Claude calls the Bash tool
4748
### Error Handling
4849

4950
- **JSON parse failure**: Fails closed (exit 2) — if the input can't be read, the command is blocked
50-
- **Other exceptions**: Fails open (exit 0) — logs the error to stderr but does not block
51+
- **Other exceptions**: Fails closed (exit 2) — logs the error to stderr and blocks
5152

5253
### Timeout
5354

.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
import re
1212
import sys
1313

14+
FORCE_PUSH_SUGGESTION = (
15+
"Blocked: force push is not allowed. "
16+
"If you rebased and need to update a remote branch, use "
17+
"`git merge origin/main` instead of `git rebase` to avoid "
18+
"diverged history that requires force push."
19+
)
20+
1421
DANGEROUS_PATTERNS = [
1522
# Destructive filesystem deletion
1623
(
@@ -79,16 +86,30 @@
7986
(r"\brm\s+.*-[^\s]*r[^\s]*f[^\s]*\s+\.\./", "Blocked: rm -rf on parent directory"),
8087
(r"\bfind\s+.*-exec\s+rm\b", "Blocked: find -exec rm is dangerous"),
8188
(r"\bfind\s+.*-delete\b", "Blocked: find -delete is dangerous"),
82-
# Git history destruction
83-
(r"\bgit\s+push\s+-f\b", "Blocked: bare force push - specify remote and branch"),
84-
(
85-
r"\bgit\s+push\s+--force\b",
86-
"Blocked: bare force push - specify remote and branch",
87-
),
89+
# Git history destruction — force push (all variants)
90+
(r"\bgit\s+push\s+-f\b", FORCE_PUSH_SUGGESTION),
91+
(r"\bgit\s+push\s+--force\b", FORCE_PUSH_SUGGESTION),
92+
(r"\bgit\s+push\s+--force-with-lease\b", FORCE_PUSH_SUGGESTION),
8893
(
8994
r"\bgit\s+clean\s+-[^\s]*f",
9095
"Blocked: git clean -f removes untracked files permanently",
9196
),
97+
# Remote branch deletion — closes open PRs and destroys remote history
98+
(
99+
r"\bgit\s+push\s+\S+\s+--delete\b",
100+
"Blocked: deleting remote branches closes any associated pull requests. "
101+
"Do not delete remote branches as a workaround for force push blocks.",
102+
),
103+
(
104+
r"\bgit\s+push\s+--delete\b",
105+
"Blocked: deleting remote branches closes any associated pull requests. "
106+
"Do not delete remote branches as a workaround for force push blocks.",
107+
),
108+
(
109+
r"\bgit\s+push\s+\S+\s+:\S",
110+
"Blocked: push with colon-refspec deletes remote branches and closes "
111+
"associated pull requests. Do not use as a workaround for force push blocks.",
112+
),
92113
]
93114

94115

0 commit comments

Comments
 (0)