damage-control-dev 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- damage_control/__init__.py +9 -0
- damage_control/__main__.py +7 -0
- damage_control/adapter.py +179 -0
- damage_control/audit.py +432 -0
- damage_control/breakglass.py +155 -0
- damage_control/claude_code.py +148 -0
- damage_control/cli.py +173 -0
- damage_control/engine.py +10656 -0
- damage_control/groups.py +114 -0
- damage_control/harness_config.py +205 -0
- damage_control/hook.py +54 -0
- damage_control/install.py +618 -0
- damage_control/packs.py +219 -0
- damage_control/policy.py +323 -0
- damage_control/profile.py +177 -0
- damage_control/rules/aws.json +85 -0
- damage_control/rules/aws.yaml +76 -0
- damage_control/rules/cloud-hosting.json +162 -0
- damage_control/rules/cloud-hosting.yaml +163 -0
- damage_control/rules/containers.json +67 -0
- damage_control/rules/containers.yaml +69 -0
- damage_control/rules/control-plane.json +7 -0
- damage_control/rules/control-plane.yaml +21 -0
- damage_control/rules/core.json +332 -0
- damage_control/rules/core.yaml +441 -0
- damage_control/rules/databases.json +117 -0
- damage_control/rules/databases.yaml +123 -0
- damage_control/rules/firebase.json +34 -0
- damage_control/rules/firebase.yaml +30 -0
- damage_control/rules/gcp.json +60 -0
- damage_control/rules/gcp.yaml +57 -0
- damage_control/rules/git.json +119 -0
- damage_control/rules/git.yaml +120 -0
- damage_control/rules/infrastructure.json +69 -0
- damage_control/rules/infrastructure.yaml +66 -0
- damage_control/rules/mcp-tools.json +11 -0
- damage_control/rules/mcp-tools.yaml +47 -0
- damage_control/rules/outbound.json +40 -0
- damage_control/rules/outbound.yaml +58 -0
- damage_control/rules/payloads.json +120 -0
- damage_control/rules/payloads.yaml +155 -0
- damage_control/rules/publish.json +46 -0
- damage_control/rules/publish.yaml +46 -0
- damage_control/rules/registry.json +10 -0
- damage_control/rules/registry.yaml +11 -0
- damage_control/rules/remote.json +31 -0
- damage_control/rules/remote.yaml +53 -0
- damage_control/rules/tmux.json +17 -0
- damage_control/rules/tmux.yaml +16 -0
- damage_control/ruleset.py +94 -0
- damage_control/tooldefs/aws.json +140 -0
- damage_control/tooldefs/aws.yaml +119 -0
- damage_control/tooldefs/docker.json +146 -0
- damage_control/tooldefs/docker.yaml +123 -0
- damage_control/tooldefs/gcp.json +186 -0
- damage_control/tooldefs/gcp.yaml +158 -0
- damage_control/tooldefs/gh.json +172 -0
- damage_control/tooldefs/gh.yaml +145 -0
- damage_control/tooldefs/git.json +166 -0
- damage_control/tooldefs/git.yaml +143 -0
- damage_control/tooldefs/kubectl.json +101 -0
- damage_control/tooldefs/kubectl.yaml +85 -0
- damage_control/tooldefs/npm.json +77 -0
- damage_control/tooldefs/npm.yaml +65 -0
- damage_control/tooldefs/terraform.json +68 -0
- damage_control/tooldefs/terraform.yaml +57 -0
- damage_control/tooldefs/uv.json +112 -0
- damage_control/tooldefs/uv.yaml +97 -0
- damage_control_dev-0.1.0.dist-info/METADATA +15 -0
- damage_control_dev-0.1.0.dist-info/RECORD +74 -0
- damage_control_dev-0.1.0.dist-info/WHEEL +4 -0
- damage_control_dev-0.1.0.dist-info/entry_points.txt +2 -0
- damage_control_dev-0.1.0.dist-info/licenses/LICENSE +201 -0
- damage_control_dev-0.1.0.dist-info/licenses/NOTICE +4 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bashToolPatterns": [
|
|
3
|
+
{
|
|
4
|
+
"id": "firebase.firebase-projects-delete-deletes-entire-project",
|
|
5
|
+
"pattern": "\\bfirebase\\s+projects:delete\\b",
|
|
6
|
+
"reason": "firebase projects:delete (deletes entire project)",
|
|
7
|
+
"anchored": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "firebase.firebase-firestore-delete-all-collections-wipes-all-data",
|
|
11
|
+
"pattern": "\\bfirebase\\s+firestore:delete\\s+.*--all-collections",
|
|
12
|
+
"reason": "firebase firestore:delete --all-collections (wipes all data)",
|
|
13
|
+
"anchored": true
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "firebase.firebase-database-remove-wipes-realtime-db",
|
|
17
|
+
"pattern": "\\bfirebase\\s+database:remove\\b",
|
|
18
|
+
"reason": "firebase database:remove (wipes Realtime DB)",
|
|
19
|
+
"anchored": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "firebase.firebase-hosting-disable",
|
|
23
|
+
"pattern": "\\bfirebase\\s+hosting:disable\\b",
|
|
24
|
+
"reason": "firebase hosting:disable",
|
|
25
|
+
"anchored": true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "firebase.firebase-functions-delete",
|
|
29
|
+
"pattern": "\\bfirebase\\s+functions:delete\\b",
|
|
30
|
+
"reason": "firebase functions:delete",
|
|
31
|
+
"anchored": true
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Firebase CLI damage control rules
|
|
2
|
+
|
|
3
|
+
bashToolPatterns:
|
|
4
|
+
# ---------------------------------------------------------------------------
|
|
5
|
+
# FIREBASE DESTRUCTIVE OPERATIONS
|
|
6
|
+
# ---------------------------------------------------------------------------
|
|
7
|
+
- id: firebase.firebase-projects-delete-deletes-entire-project
|
|
8
|
+
pattern: '\bfirebase\s+projects:delete\b'
|
|
9
|
+
reason: firebase projects:delete (deletes entire project)
|
|
10
|
+
anchored: true
|
|
11
|
+
|
|
12
|
+
- id: firebase.firebase-firestore-delete-all-collections-wipes-all-data
|
|
13
|
+
pattern: '\bfirebase\s+firestore:delete\s+.*--all-collections'
|
|
14
|
+
reason: firebase firestore:delete --all-collections (wipes all data)
|
|
15
|
+
anchored: true
|
|
16
|
+
|
|
17
|
+
- id: firebase.firebase-database-remove-wipes-realtime-db
|
|
18
|
+
pattern: '\bfirebase\s+database:remove\b'
|
|
19
|
+
reason: firebase database:remove (wipes Realtime DB)
|
|
20
|
+
anchored: true
|
|
21
|
+
|
|
22
|
+
- id: firebase.firebase-hosting-disable
|
|
23
|
+
pattern: '\bfirebase\s+hosting:disable\b'
|
|
24
|
+
reason: firebase hosting:disable
|
|
25
|
+
anchored: true
|
|
26
|
+
|
|
27
|
+
- id: firebase.firebase-functions-delete
|
|
28
|
+
pattern: '\bfirebase\s+functions:delete\b'
|
|
29
|
+
reason: firebase functions:delete
|
|
30
|
+
anchored: true
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bashToolPatterns": [
|
|
3
|
+
{
|
|
4
|
+
"id": "gcp.gcloud-projects-delete-deletes-entire-project",
|
|
5
|
+
"pattern": "\\bgcloud\\s+projects\\s+delete\\b",
|
|
6
|
+
"reason": "gcloud projects delete (DELETES ENTIRE PROJECT)",
|
|
7
|
+
"anchored": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "gcp.gcloud-compute-instances-delete",
|
|
11
|
+
"pattern": "\\bgcloud\\s+compute\\s+instances\\s+delete\\b",
|
|
12
|
+
"reason": "gcloud compute instances delete",
|
|
13
|
+
"anchored": true
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "gcp.gcloud-sql-instances-delete",
|
|
17
|
+
"pattern": "\\bgcloud\\s+sql\\s+instances\\s+delete\\b",
|
|
18
|
+
"reason": "gcloud sql instances delete",
|
|
19
|
+
"anchored": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "gcp.gcloud-container-clusters-delete-gke",
|
|
23
|
+
"pattern": "\\bgcloud\\s+container\\s+clusters\\s+delete\\b",
|
|
24
|
+
"reason": "gcloud container clusters delete (GKE)",
|
|
25
|
+
"anchored": true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "gcp.gcloud-storage-rm-r-recursive-delete",
|
|
29
|
+
"pattern": "\\bgcloud\\s+storage\\s+rm\\s+.*-r",
|
|
30
|
+
"reason": "gcloud storage rm -r (recursive delete)",
|
|
31
|
+
"anchored": true
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "gcp.gcloud-functions-delete",
|
|
35
|
+
"pattern": "\\bgcloud\\s+functions\\s+delete\\b",
|
|
36
|
+
"reason": "gcloud functions delete",
|
|
37
|
+
"anchored": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "gcp.gcloud-iam-service-accounts-delete",
|
|
41
|
+
"pattern": "\\bgcloud\\s+iam\\s+service-accounts\\s+delete\\b",
|
|
42
|
+
"reason": "gcloud iam service-accounts delete",
|
|
43
|
+
"anchored": true
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"pattern": "\\bgcloud\\s+run\\s+deploy\\b",
|
|
47
|
+
"reason": "gcloud run deploy (ships a Cloud Run service)",
|
|
48
|
+
"ask": true,
|
|
49
|
+
"id": "deploy.gcloud-run",
|
|
50
|
+
"anchored": true
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"pattern": "\\bgcloud\\s+app\\s+deploy\\b",
|
|
54
|
+
"reason": "gcloud app deploy (ships an App Engine version)",
|
|
55
|
+
"ask": true,
|
|
56
|
+
"id": "deploy.gcloud-app",
|
|
57
|
+
"anchored": true
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# GCP (gcloud) damage control rules
|
|
2
|
+
|
|
3
|
+
bashToolPatterns:
|
|
4
|
+
# ---------------------------------------------------------------------------
|
|
5
|
+
# GCP (gcloud) DESTRUCTIVE OPERATIONS
|
|
6
|
+
# ---------------------------------------------------------------------------
|
|
7
|
+
- id: gcp.gcloud-projects-delete-deletes-entire-project
|
|
8
|
+
pattern: '\bgcloud\s+projects\s+delete\b'
|
|
9
|
+
reason: gcloud projects delete (DELETES ENTIRE PROJECT)
|
|
10
|
+
anchored: true
|
|
11
|
+
|
|
12
|
+
- id: gcp.gcloud-compute-instances-delete
|
|
13
|
+
pattern: '\bgcloud\s+compute\s+instances\s+delete\b'
|
|
14
|
+
reason: gcloud compute instances delete
|
|
15
|
+
anchored: true
|
|
16
|
+
|
|
17
|
+
- id: gcp.gcloud-sql-instances-delete
|
|
18
|
+
pattern: '\bgcloud\s+sql\s+instances\s+delete\b'
|
|
19
|
+
reason: gcloud sql instances delete
|
|
20
|
+
anchored: true
|
|
21
|
+
|
|
22
|
+
- id: gcp.gcloud-container-clusters-delete-gke
|
|
23
|
+
pattern: '\bgcloud\s+container\s+clusters\s+delete\b'
|
|
24
|
+
reason: gcloud container clusters delete (GKE)
|
|
25
|
+
anchored: true
|
|
26
|
+
|
|
27
|
+
- id: gcp.gcloud-storage-rm-r-recursive-delete
|
|
28
|
+
pattern: '\bgcloud\s+storage\s+rm\s+.*-r'
|
|
29
|
+
reason: gcloud storage rm -r (recursive delete)
|
|
30
|
+
anchored: true
|
|
31
|
+
|
|
32
|
+
- id: gcp.gcloud-functions-delete
|
|
33
|
+
pattern: '\bgcloud\s+functions\s+delete\b'
|
|
34
|
+
reason: gcloud functions delete
|
|
35
|
+
anchored: true
|
|
36
|
+
|
|
37
|
+
- id: gcp.gcloud-iam-service-accounts-delete
|
|
38
|
+
pattern: '\bgcloud\s+iam\s+service-accounts\s+delete\b'
|
|
39
|
+
reason: gcloud iam service-accounts delete
|
|
40
|
+
anchored: true
|
|
41
|
+
|
|
42
|
+
# ---------------------------------------------------------------------------
|
|
43
|
+
# GCP DEPLOYS (ask: true — outward-facing, caught in unattended sessions)
|
|
44
|
+
# ---------------------------------------------------------------------------
|
|
45
|
+
# `gcloud functions deploy` is already ask-tier via the gcp tooldef; these
|
|
46
|
+
# cover the other deploy surfaces (Cloud Run, App Engine).
|
|
47
|
+
- pattern: '\bgcloud\s+run\s+deploy\b'
|
|
48
|
+
reason: gcloud run deploy (ships a Cloud Run service)
|
|
49
|
+
ask: true
|
|
50
|
+
id: deploy.gcloud-run
|
|
51
|
+
anchored: true
|
|
52
|
+
|
|
53
|
+
- pattern: '\bgcloud\s+app\s+deploy\b'
|
|
54
|
+
reason: gcloud app deploy (ships an App Engine version)
|
|
55
|
+
ask: true
|
|
56
|
+
id: deploy.gcloud-app
|
|
57
|
+
anchored: true
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bashToolPatterns": [
|
|
3
|
+
{
|
|
4
|
+
"id": "git.git-reset-hard-use-soft-or-stash",
|
|
5
|
+
"pattern": "\\bgit\\s+reset\\s+(?:(?!--(?:\\s|$))[^\\s;&|]+\\s+)*?--hard\\b",
|
|
6
|
+
"pattern_src": "\\bgit\\s+reset\\s+{ARGS}--hard\\b",
|
|
7
|
+
"reason": "git reset --hard (use --soft or stash)",
|
|
8
|
+
"anchored": true
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "git.git-clean-with-force-directory-flags",
|
|
12
|
+
"pattern": "\\bgit\\s+clean\\s+(?!(?:[^;&|]*\\s)?(?:-(?!-)[a-z]*n[a-z]*(?=[\\s;&|)`]|$)|--dry-run\\b))(?:(?!--(?:\\s|$))[^\\s;&|]+\\s+)*?(?:-(?!-)[a-z]*[fd][a-z]*|--force)(?=[\\s;&|)`]|$)",
|
|
13
|
+
"pattern_src": "\\bgit\\s+clean\\s+(?!(?:[^;&|]*\\s)?(?:-(?!-)[a-z]*n[a-z]*(?=[\\s;&|)`]|$)|--dry-run\\b)){ARGS}(?:-(?!-)[a-z]*[fd][a-z]*|--force)(?=[\\s;&|)`]|$)",
|
|
14
|
+
"reason": "git clean with force/directory flags",
|
|
15
|
+
"anchored": true
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": "git.git-push-force-use-force-with-lease",
|
|
19
|
+
"pattern": "\\bgit\\s+push\\s+.*--force(?!-with-lease)",
|
|
20
|
+
"reason": "git push --force (use --force-with-lease)",
|
|
21
|
+
"anchored": true
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "git.git-push-f-use-force-with-lease",
|
|
25
|
+
"pattern": "\\bgit\\s+push\\s+(?:(?!--(?:\\s|$))[^\\s;&|]+\\s+)*?-(?!-)[a-z]*f[a-z]*(?=[\\s;&|)`]|$)",
|
|
26
|
+
"pattern_src": "\\bgit\\s+push\\s+{ARGS}-(?!-)[a-z]*f[a-z]*(?=[\\s;&|)`]|$)",
|
|
27
|
+
"reason": "git push -f (use --force-with-lease)",
|
|
28
|
+
"anchored": true
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "git.git-stash-clear-deletes-all-stashes",
|
|
32
|
+
"pattern": "\\bgit\\s+stash\\s+clear\\b",
|
|
33
|
+
"reason": "git stash clear (deletes ALL stashes)",
|
|
34
|
+
"anchored": true
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": "git.git-reflog-expire-destroys-recovery-mechanism",
|
|
38
|
+
"pattern": "\\bgit\\s+reflog\\s+expire\\b",
|
|
39
|
+
"reason": "git reflog expire (destroys recovery mechanism)",
|
|
40
|
+
"anchored": true
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "git.git-gc-prune-now-can-lose-dangling-commits",
|
|
44
|
+
"pattern": "\\bgit\\s+gc\\s+.*--prune=now",
|
|
45
|
+
"reason": "git gc --prune=now (can lose dangling commits)",
|
|
46
|
+
"anchored": true
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "git.git-filter-branch-rewrites-entire-history",
|
|
50
|
+
"pattern": "\\bgit\\s+filter-branch\\b",
|
|
51
|
+
"reason": "git filter-branch (rewrites entire history)",
|
|
52
|
+
"anchored": true
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "git.discards-all-uncommitted-changes",
|
|
56
|
+
"pattern": "\\bgit\\s+checkout\\s+--\\s*\\.",
|
|
57
|
+
"reason": "Discards all uncommitted changes",
|
|
58
|
+
"ask": true,
|
|
59
|
+
"anchored": true
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "git.discards-all-uncommitted-changes-2",
|
|
63
|
+
"pattern": "\\bgit\\s+restore\\s+\\.",
|
|
64
|
+
"reason": "Discards all uncommitted changes",
|
|
65
|
+
"ask": true,
|
|
66
|
+
"anchored": true
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "git.rm-tracked-files",
|
|
70
|
+
"pattern": "\\bgit\\s+rm\\b(?!.*--cached)",
|
|
71
|
+
"reason": "git rm deletes tracked files (use rm of a clean file, or confirm)",
|
|
72
|
+
"ask": true,
|
|
73
|
+
"anchored": true
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "git.config-set-redirect-key",
|
|
77
|
+
"pattern": "\\bgit\\s+config\\b(?![^;&|]*\\s(?:--(?:get|unset|list|edit)|-l\\b|-e\\b))[^;&|]*?\\s(?:core\\.(?:worktree|hookspath)|include\\.path|includeif\\.\\S+\\.path)\\s+\\S",
|
|
78
|
+
"reason": "git config redirects the worktree, hooks dir, or an included config",
|
|
79
|
+
"ask": true,
|
|
80
|
+
"anchored": true
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "git.permanently-deletes-a-stash",
|
|
84
|
+
"pattern": "\\bgit\\s+stash\\s+drop\\b",
|
|
85
|
+
"reason": "Permanently deletes a stash",
|
|
86
|
+
"ask": true,
|
|
87
|
+
"anchored": true
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "git.force-deletes-branch-even-if-unmerged",
|
|
91
|
+
"pattern": "\\bgit\\s+branch\\s+(?:(?:(?!--(?:\\s|$))[^\\s;&|]+\\s+)*?-(?!-)[a-z]*(?-i:D)[a-z]*(?=[\\s;&|)`]|$)|(?=(?:[^;&|]*\\s)?(?:-(?!-)[a-z]*d[a-z]*|--delete)(?=[\\s;&|)`]|$))(?=(?:[^;&|]*\\s)?(?:-(?!-)[a-z]*f[a-z]*|--force)(?=[\\s;&|)`]|$)))",
|
|
92
|
+
"pattern_src": "\\bgit\\s+branch\\s+(?:{ARGS}-(?!-)[a-z]*(?-i:D)[a-z]*(?=[\\s;&|)`]|$)|(?=(?:[^;&|]*\\s)?(?:-(?!-)[a-z]*d[a-z]*|--delete)(?=[\\s;&|)`]|$))(?=(?:[^;&|]*\\s)?(?:-(?!-)[a-z]*f[a-z]*|--force)(?=[\\s;&|)`]|$)))",
|
|
93
|
+
"reason": "Force deletes branch (even if unmerged)",
|
|
94
|
+
"ask": true,
|
|
95
|
+
"anchored": true
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"id": "git.deletes-remote-branch",
|
|
99
|
+
"pattern": "\\bgit\\s+push\\s+(?:(?!--(?:\\s|$))[^\\s;&|]+\\s+)*?--delete\\b",
|
|
100
|
+
"pattern_src": "\\bgit\\s+push\\s+{ARGS}--delete\\b",
|
|
101
|
+
"reason": "Deletes remote branch",
|
|
102
|
+
"ask": true,
|
|
103
|
+
"anchored": true
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"id": "git.deletes-remote-branch-old-syntax",
|
|
107
|
+
"pattern": "\\bgit\\s+push\\s+\\S+\\s+:\\S+",
|
|
108
|
+
"reason": "Deletes remote branch (old syntax)",
|
|
109
|
+
"ask": true,
|
|
110
|
+
"anchored": true
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"id": "git.gh-repo-delete-deletes-repository",
|
|
114
|
+
"pattern": "\\bgh\\s+repo\\s+delete\\b",
|
|
115
|
+
"reason": "gh repo delete (deletes repository)",
|
|
116
|
+
"anchored": true
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Git damage control rules
|
|
2
|
+
# Destructive and confirmation-required git operations
|
|
3
|
+
|
|
4
|
+
bashToolPatterns:
|
|
5
|
+
# ---------------------------------------------------------------------------
|
|
6
|
+
# GIT DESTRUCTIVE OPERATIONS
|
|
7
|
+
# ---------------------------------------------------------------------------
|
|
8
|
+
- id: git.git-reset-hard-use-soft-or-stash
|
|
9
|
+
pattern: '\bgit\s+reset\s+(?:(?!--(?:\s|$))[^\s;&|]+\s+)*?--hard\b'
|
|
10
|
+
pattern_src: '\bgit\s+reset\s+{ARGS}--hard\b'
|
|
11
|
+
reason: git reset --hard (use --soft or stash)
|
|
12
|
+
anchored: true
|
|
13
|
+
|
|
14
|
+
- id: git.git-clean-with-force-directory-flags
|
|
15
|
+
pattern: '\bgit\s+clean\s+(?!(?:[^;&|]*\s)?(?:-(?!-)[a-z]*n[a-z]*(?=[\s;&|)`]|$)|--dry-run\b))(?:(?!--(?:\s|$))[^\s;&|]+\s+)*?(?:-(?!-)[a-z]*[fd][a-z]*|--force)(?=[\s;&|)`]|$)'
|
|
16
|
+
pattern_src: '\bgit\s+clean\s+(?!(?:[^;&|]*\s)?(?:-(?!-)[a-z]*n[a-z]*(?=[\s;&|)`]|$)|--dry-run\b)){ARGS}(?:-(?!-)[a-z]*[fd][a-z]*|--force)(?=[\s;&|)`]|$)'
|
|
17
|
+
reason: git clean with force/directory flags
|
|
18
|
+
anchored: true
|
|
19
|
+
|
|
20
|
+
# Note: This blocks --force but NOT --force-with-lease
|
|
21
|
+
- id: git.git-push-force-use-force-with-lease
|
|
22
|
+
pattern: '\bgit\s+push\s+.*--force(?!-with-lease)'
|
|
23
|
+
reason: git push --force (use --force-with-lease)
|
|
24
|
+
anchored: true
|
|
25
|
+
|
|
26
|
+
- id: git.git-push-f-use-force-with-lease
|
|
27
|
+
pattern: '\bgit\s+push\s+(?:(?!--(?:\s|$))[^\s;&|]+\s+)*?-(?!-)[a-z]*f[a-z]*(?=[\s;&|)`]|$)'
|
|
28
|
+
pattern_src: '\bgit\s+push\s+{ARGS}-(?!-)[a-z]*f[a-z]*(?=[\s;&|)`]|$)'
|
|
29
|
+
reason: git push -f (use --force-with-lease)
|
|
30
|
+
anchored: true
|
|
31
|
+
|
|
32
|
+
- id: git.git-stash-clear-deletes-all-stashes
|
|
33
|
+
pattern: '\bgit\s+stash\s+clear\b'
|
|
34
|
+
reason: git stash clear (deletes ALL stashes)
|
|
35
|
+
anchored: true
|
|
36
|
+
|
|
37
|
+
- id: git.git-reflog-expire-destroys-recovery-mechanism
|
|
38
|
+
pattern: '\bgit\s+reflog\s+expire\b'
|
|
39
|
+
reason: git reflog expire (destroys recovery mechanism)
|
|
40
|
+
anchored: true
|
|
41
|
+
|
|
42
|
+
- id: git.git-gc-prune-now-can-lose-dangling-commits
|
|
43
|
+
pattern: '\bgit\s+gc\s+.*--prune=now'
|
|
44
|
+
reason: git gc --prune=now (can lose dangling commits)
|
|
45
|
+
anchored: true
|
|
46
|
+
|
|
47
|
+
- id: git.git-filter-branch-rewrites-entire-history
|
|
48
|
+
pattern: '\bgit\s+filter-branch\b'
|
|
49
|
+
reason: git filter-branch (rewrites entire history)
|
|
50
|
+
anchored: true
|
|
51
|
+
|
|
52
|
+
# ---------------------------------------------------------------------------
|
|
53
|
+
# GIT OPERATIONS REQUIRING CONFIRMATION (ask: true)
|
|
54
|
+
# ---------------------------------------------------------------------------
|
|
55
|
+
- id: git.discards-all-uncommitted-changes
|
|
56
|
+
pattern: '\bgit\s+checkout\s+--\s*\.'
|
|
57
|
+
reason: Discards all uncommitted changes
|
|
58
|
+
ask: true
|
|
59
|
+
anchored: true
|
|
60
|
+
|
|
61
|
+
- id: git.discards-all-uncommitted-changes-2
|
|
62
|
+
pattern: '\bgit\s+restore\s+\.'
|
|
63
|
+
reason: Discards all uncommitted changes
|
|
64
|
+
ask: true
|
|
65
|
+
anchored: true
|
|
66
|
+
|
|
67
|
+
# `git rm` deletes tracked files from the working tree AND the index; unlike a
|
|
68
|
+
# plain rm of a clean file it is a deliberate history-shaping act, rarely
|
|
69
|
+
# right for an agent. `--cached` only unstages (the file stays), so it passes.
|
|
70
|
+
- id: git.rm-tracked-files
|
|
71
|
+
pattern: '\bgit\s+rm\b(?!.*--cached)'
|
|
72
|
+
reason: git rm deletes tracked files (use rm of a clean file, or confirm)
|
|
73
|
+
ask: true
|
|
74
|
+
anchored: true
|
|
75
|
+
|
|
76
|
+
# SET-FORM config (`git config [--global] <key> <value>`, #1133/#9/#28): the
|
|
77
|
+
# same keys `git -c` is asked about (git.config-exec-key), plus the keys that
|
|
78
|
+
# REDIRECT git itself. Reads (`--get*`, `--list`, `--unset*`, `--edit`) and a
|
|
79
|
+
# keyless/valueless call never match.
|
|
80
|
+
# 1) Redirect keys: no benign value exists, always ask.
|
|
81
|
+
- id: git.config-set-redirect-key
|
|
82
|
+
pattern: '\bgit\s+config\b(?![^;&|]*\s(?:--(?:get|unset|list|edit)|-l\b|-e\b))[^;&|]*?\s(?:core\.(?:worktree|hookspath)|include\.path|includeif\.\S+\.path)\s+\S'
|
|
83
|
+
reason: git config redirects the worktree, hooks dir, or an included config
|
|
84
|
+
ask: true
|
|
85
|
+
anchored: true
|
|
86
|
+
|
|
87
|
+
- id: git.permanently-deletes-a-stash
|
|
88
|
+
pattern: '\bgit\s+stash\s+drop\b'
|
|
89
|
+
reason: Permanently deletes a stash
|
|
90
|
+
ask: true
|
|
91
|
+
anchored: true
|
|
92
|
+
|
|
93
|
+
- id: git.force-deletes-branch-even-if-unmerged
|
|
94
|
+
pattern: '\bgit\s+branch\s+(?:(?:(?!--(?:\s|$))[^\s;&|]+\s+)*?-(?!-)[a-z]*(?-i:D)[a-z]*(?=[\s;&|)`]|$)|(?=(?:[^;&|]*\s)?(?:-(?!-)[a-z]*d[a-z]*|--delete)(?=[\s;&|)`]|$))(?=(?:[^;&|]*\s)?(?:-(?!-)[a-z]*f[a-z]*|--force)(?=[\s;&|)`]|$)))'
|
|
95
|
+
pattern_src: '\bgit\s+branch\s+(?:{ARGS}-(?!-)[a-z]*(?-i:D)[a-z]*(?=[\s;&|)`]|$)|(?=(?:[^;&|]*\s)?(?:-(?!-)[a-z]*d[a-z]*|--delete)(?=[\s;&|)`]|$))(?=(?:[^;&|]*\s)?(?:-(?!-)[a-z]*f[a-z]*|--force)(?=[\s;&|)`]|$)))'
|
|
96
|
+
reason: Force deletes branch (even if unmerged)
|
|
97
|
+
ask: true
|
|
98
|
+
anchored: true
|
|
99
|
+
|
|
100
|
+
- id: git.deletes-remote-branch
|
|
101
|
+
pattern: '\bgit\s+push\s+(?:(?!--(?:\s|$))[^\s;&|]+\s+)*?--delete\b'
|
|
102
|
+
pattern_src: '\bgit\s+push\s+{ARGS}--delete\b'
|
|
103
|
+
reason: Deletes remote branch
|
|
104
|
+
ask: true
|
|
105
|
+
anchored: true
|
|
106
|
+
|
|
107
|
+
- id: git.deletes-remote-branch-old-syntax
|
|
108
|
+
pattern: '\bgit\s+push\s+\S+\s+:\S+'
|
|
109
|
+
reason: Deletes remote branch (old syntax)
|
|
110
|
+
ask: true
|
|
111
|
+
anchored: true
|
|
112
|
+
|
|
113
|
+
# ---------------------------------------------------------------------------
|
|
114
|
+
# GITHUB CLI DESTRUCTIVE OPERATIONS (default-on: moved out of the cloud-hosting
|
|
115
|
+
# pack so a fresh install keeps it, #1141)
|
|
116
|
+
# ---------------------------------------------------------------------------
|
|
117
|
+
- id: git.gh-repo-delete-deletes-repository
|
|
118
|
+
pattern: '\bgh\s+repo\s+delete\b'
|
|
119
|
+
reason: gh repo delete (deletes repository)
|
|
120
|
+
anchored: true
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bashToolPatterns": [
|
|
3
|
+
{
|
|
4
|
+
"id": "infrastructure.terraform-destroy-destroys-all-infrastructure",
|
|
5
|
+
"pattern": "\\bterraform\\s+destroy\\b",
|
|
6
|
+
"reason": "terraform destroy (destroys all infrastructure)",
|
|
7
|
+
"anchored": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "infrastructure.pulumi-destroy-destroys-all-resources",
|
|
11
|
+
"pattern": "\\bpulumi\\s+destroy\\b",
|
|
12
|
+
"reason": "pulumi destroy (destroys all resources)",
|
|
13
|
+
"anchored": true
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "infrastructure.serverless-remove-removes-stack",
|
|
17
|
+
"pattern": "\\bserverless\\s+remove\\b",
|
|
18
|
+
"reason": "serverless remove (removes stack)",
|
|
19
|
+
"anchored": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "infrastructure.sls-remove-removes-stack",
|
|
23
|
+
"pattern": "\\bsls\\s+remove\\b",
|
|
24
|
+
"reason": "sls remove (removes stack)",
|
|
25
|
+
"anchored": true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "infrastructure.sam-delete-deletes-sam-application",
|
|
29
|
+
"pattern": "\\bsam\\s+delete\\b",
|
|
30
|
+
"reason": "sam delete (deletes SAM application)",
|
|
31
|
+
"anchored": true
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"pattern": "\\bpulumi\\s+up\\b",
|
|
35
|
+
"reason": "pulumi up (provisions/updates infrastructure)",
|
|
36
|
+
"ask": true,
|
|
37
|
+
"id": "deploy.pulumi-up",
|
|
38
|
+
"anchored": true
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"pattern": "\\b(serverless|sls)\\s+deploy\\b",
|
|
42
|
+
"reason": "serverless deploy (ships a Serverless Framework stack)",
|
|
43
|
+
"ask": true,
|
|
44
|
+
"id": "deploy.serverless",
|
|
45
|
+
"anchored": true
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"pattern": "\\bsam\\s+deploy\\b",
|
|
49
|
+
"reason": "sam deploy (ships an AWS SAM application)",
|
|
50
|
+
"ask": true,
|
|
51
|
+
"id": "deploy.sam",
|
|
52
|
+
"anchored": true
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"pattern": "\\bcdk\\s+deploy\\b",
|
|
56
|
+
"reason": "cdk deploy (ships an AWS CDK stack)",
|
|
57
|
+
"ask": true,
|
|
58
|
+
"id": "deploy.cdk",
|
|
59
|
+
"anchored": true
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"pattern": "\\bansible-playbook\\b",
|
|
63
|
+
"reason": "ansible-playbook (applies configuration to remote hosts)",
|
|
64
|
+
"ask": true,
|
|
65
|
+
"id": "deploy.ansible",
|
|
66
|
+
"anchored": true
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Infrastructure as Code damage control rules
|
|
2
|
+
# Terraform, Pulumi, Serverless Framework, SAM
|
|
3
|
+
|
|
4
|
+
bashToolPatterns:
|
|
5
|
+
# ---------------------------------------------------------------------------
|
|
6
|
+
# INFRASTRUCTURE AS CODE DESTRUCTIVE OPERATIONS
|
|
7
|
+
# ---------------------------------------------------------------------------
|
|
8
|
+
- id: infrastructure.terraform-destroy-destroys-all-infrastructure
|
|
9
|
+
pattern: '\bterraform\s+destroy\b'
|
|
10
|
+
reason: terraform destroy (destroys all infrastructure)
|
|
11
|
+
anchored: true
|
|
12
|
+
|
|
13
|
+
- id: infrastructure.pulumi-destroy-destroys-all-resources
|
|
14
|
+
pattern: '\bpulumi\s+destroy\b'
|
|
15
|
+
reason: pulumi destroy (destroys all resources)
|
|
16
|
+
anchored: true
|
|
17
|
+
|
|
18
|
+
- id: infrastructure.serverless-remove-removes-stack
|
|
19
|
+
pattern: '\bserverless\s+remove\b'
|
|
20
|
+
reason: serverless remove (removes stack)
|
|
21
|
+
anchored: true
|
|
22
|
+
|
|
23
|
+
- id: infrastructure.sls-remove-removes-stack
|
|
24
|
+
pattern: '\bsls\s+remove\b'
|
|
25
|
+
reason: sls remove (removes stack)
|
|
26
|
+
anchored: true
|
|
27
|
+
|
|
28
|
+
- id: infrastructure.sam-delete-deletes-sam-application
|
|
29
|
+
pattern: '\bsam\s+delete\b'
|
|
30
|
+
reason: sam delete (deletes SAM application)
|
|
31
|
+
anchored: true
|
|
32
|
+
|
|
33
|
+
# ---------------------------------------------------------------------------
|
|
34
|
+
# IaC DEPLOYS (ask: true — provision/ship infra, caught in unattended sessions)
|
|
35
|
+
# ---------------------------------------------------------------------------
|
|
36
|
+
# `terraform apply` is already ask-tier via the terraform tooldef; these cover
|
|
37
|
+
# the other IaC apply verbs that were previously `allow`-tier.
|
|
38
|
+
- pattern: '\bpulumi\s+up\b'
|
|
39
|
+
reason: pulumi up (provisions/updates infrastructure)
|
|
40
|
+
ask: true
|
|
41
|
+
id: deploy.pulumi-up
|
|
42
|
+
anchored: true
|
|
43
|
+
|
|
44
|
+
- pattern: '\b(serverless|sls)\s+deploy\b'
|
|
45
|
+
reason: serverless deploy (ships a Serverless Framework stack)
|
|
46
|
+
ask: true
|
|
47
|
+
id: deploy.serverless
|
|
48
|
+
anchored: true
|
|
49
|
+
|
|
50
|
+
- pattern: '\bsam\s+deploy\b'
|
|
51
|
+
reason: sam deploy (ships an AWS SAM application)
|
|
52
|
+
ask: true
|
|
53
|
+
id: deploy.sam
|
|
54
|
+
anchored: true
|
|
55
|
+
|
|
56
|
+
- pattern: '\bcdk\s+deploy\b'
|
|
57
|
+
reason: cdk deploy (ships an AWS CDK stack)
|
|
58
|
+
ask: true
|
|
59
|
+
id: deploy.cdk
|
|
60
|
+
anchored: true
|
|
61
|
+
|
|
62
|
+
- pattern: '\bansible-playbook\b'
|
|
63
|
+
reason: ansible-playbook (applies configuration to remote hosts)
|
|
64
|
+
ask: true
|
|
65
|
+
id: deploy.ansible
|
|
66
|
+
anchored: true
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpToolPolicies": [
|
|
3
|
+
{
|
|
4
|
+
"match": "(write|edit|delete|remove|move|rename|create|append|patch|mkdir|rmdir|copy|upload|chmod|prune|kill|purge)",
|
|
5
|
+
"id": "mcp.writeish-name",
|
|
6
|
+
"tier": "allow",
|
|
7
|
+
"mutates": true,
|
|
8
|
+
"reason": "write-shaped MCP tool name — protected control-plane path arguments are refused"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Per-tool policy for MCP tool calls (#923 option 1).
|
|
2
|
+
#
|
|
3
|
+
# The bash rules match shell command strings; an MCP call is a name plus a JSON
|
|
4
|
+
# object, so coverage does not transfer — a tool is classified HERE instead.
|
|
5
|
+
# First match wins. Fields: `tool` (exact full name) or `match` (regex on the
|
|
6
|
+
# name), `tier` (allow | ask | block; default ask), `mutates` (screen protected
|
|
7
|
+
# control-plane path arguments; defaults true for any non-allow tier), `id`
|
|
8
|
+
# (stable — `unattended_allow` / `disabled_rules` name it), `reason`.
|
|
9
|
+
#
|
|
10
|
+
# Tier semantics are the Bash hook's, unchanged: `ask` is an interactive
|
|
11
|
+
# confirm, demoted to allow under bypassPermissions/auto, and FAIL-CLOSED
|
|
12
|
+
# (block + owner email) in an unattended session unless the id is granted.
|
|
13
|
+
# A tool call names no directory, so a path-scoped grant refuses — grant these
|
|
14
|
+
# ids unscoped, per task, deliberately.
|
|
15
|
+
#
|
|
16
|
+
# WHAT IS CLASSIFIED: the measured dangerous core — the kill/remove/teardown
|
|
17
|
+
# class whose effect is not "a message to a guarded session". Each mirrors the
|
|
18
|
+
# in-CLI safety its command path already carries (merge-verification, dirty
|
|
19
|
+
# refusal, PR guards); the tier is additive on top, giving the tool call the
|
|
20
|
+
# same unattended fail-closed posture its Bash spelling gets from the rules.
|
|
21
|
+
#
|
|
22
|
+
# WHAT IS DELIBERATELY NOT CLASSIFIED (pricing both halves — a wrongful tool
|
|
23
|
+
# refusal in an unattended session is a silent loop):
|
|
24
|
+
# * session_send / session_send_keys / pane_send / msg_send — their effect is
|
|
25
|
+
# a message to a Claude session that runs its OWN damage control; the Bash
|
|
26
|
+
# twin (`agentwire send`) is unruled, and gating only the tool would
|
|
27
|
+
# recreate #923's channel asymmetry in reverse.
|
|
28
|
+
# * everything read-shaped or additive (create/list/status/output) — allow by
|
|
29
|
+
# falling through, with zero-access secret screening still applied to every
|
|
30
|
+
# tool's path arguments.
|
|
31
|
+
#
|
|
32
|
+
# UNCLASSIFIED TOOLS fall through to the final name-shape entry below (the
|
|
33
|
+
# #1036 heuristic, now data a host can edit) and otherwise to allow-with-
|
|
34
|
+
# screening. That default is the design decision #923 names: fail-closed would
|
|
35
|
+
# kill every third-party tool and every future tool until classified.
|
|
36
|
+
|
|
37
|
+
mcpToolPolicies:
|
|
38
|
+
# --- fallback for unclassified tools --------------------------------------
|
|
39
|
+
# The #1036 write-shaped-name heuristic, kept as DATA rather than code: a
|
|
40
|
+
# tool whose name declares a mutating operation gets its path-valued
|
|
41
|
+
# arguments screened against the protected control plane. `allow` tier — the
|
|
42
|
+
# name shape alone never blocks or asks; only a protected path argument does.
|
|
43
|
+
- match: "(write|edit|delete|remove|move|rename|create|append|patch|mkdir|rmdir|copy|upload|chmod|prune|kill|purge)"
|
|
44
|
+
id: mcp.writeish-name
|
|
45
|
+
tier: allow
|
|
46
|
+
mutates: true
|
|
47
|
+
reason: write-shaped MCP tool name — protected control-plane path arguments are refused
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bashToolPatterns": [
|
|
3
|
+
{
|
|
4
|
+
"pattern": "\\btwilio\\s+api[:\\w.]*messages[:\\w.]*create\\b",
|
|
5
|
+
"reason": "twilio messages create (sends an SMS/MMS)",
|
|
6
|
+
"ask": true,
|
|
7
|
+
"id": "outbound.twilio-messages",
|
|
8
|
+
"anchored": true
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"pattern": "\\baws\\s+ses(v2)?\\s+send-email\\b",
|
|
12
|
+
"reason": "aws ses send-email (sends an external email)",
|
|
13
|
+
"ask": true,
|
|
14
|
+
"id": "outbound.aws-ses",
|
|
15
|
+
"anchored": true
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"pattern": "\\baws\\s+sns\\s+publish\\b",
|
|
19
|
+
"reason": "aws sns publish (sends an SMS/notification)",
|
|
20
|
+
"ask": true,
|
|
21
|
+
"id": "outbound.aws-sns",
|
|
22
|
+
"anchored": true
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"pattern": "\\bsendmail\\b",
|
|
26
|
+
"reason": "sendmail (sends external email)",
|
|
27
|
+
"ask": true,
|
|
28
|
+
"id": "outbound.sendmail",
|
|
29
|
+
"anchored": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"pattern": "\\b(mail|mailx)\\s+(?:(?!--(?:\\s|$))[^\\s;&|]+\\s+)*?-s\\b",
|
|
33
|
+
"pattern_src": "\\b(mail|mailx)\\s+{ARGS}-s\\b",
|
|
34
|
+
"reason": "mail -s (sends external email)",
|
|
35
|
+
"ask": true,
|
|
36
|
+
"id": "outbound.mail",
|
|
37
|
+
"anchored": true
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|