ccperm 1.11.0 → 1.11.2
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.
- package/README.ko.md +14 -0
- package/README.md +14 -0
- package/dist/explain.js +31 -0
- package/dist/interactive.js +13 -2
- package/package.json +1 -1
package/README.ko.md
CHANGED
|
@@ -32,6 +32,7 @@ ccperm
|
|
|
32
32
|
| `--verbose` | 모든 권한을 상세 나열하는 텍스트 출력 |
|
|
33
33
|
| `--fix` | deprecated `:*` 패턴을 ` *`로 자동 수정 |
|
|
34
34
|
| `--update` | `npm install -g ccperm@latest`로 자체 업데이트 |
|
|
35
|
+
| `--hey-claude-witness-me` | LLM 친화적 마크다운 감사 브리핑 (위험도 분류 포함) |
|
|
35
36
|
| `--debug` | 스캔 진단 정보 표시 (파일 경로, 소요 시간) |
|
|
36
37
|
| `--help`, `-h` | 도움말 표시 |
|
|
37
38
|
| `--version`, `-v` | 버전 표시 |
|
|
@@ -81,6 +82,19 @@ ccperm은 Claude Code 설정을 세 단계로 구분합니다:
|
|
|
81
82
|
|
|
82
83
|
권한은 합산 방식 — global + shared + local이 런타임에 병합됩니다.
|
|
83
84
|
|
|
85
|
+
## 위험도 분류
|
|
86
|
+
|
|
87
|
+
각 권한에 [Destructive Command Guard (DCG)](https://github.com/Dicklesworthstone/destructive_command_guard)에서 영감을 받은 위험도가 부여됩니다. `--hey-claude-witness-me` 출력과 TUI 정보 모드에서 사용됩니다.
|
|
88
|
+
|
|
89
|
+
| 레벨 | 의미 | 예시 |
|
|
90
|
+
|------|------|------|
|
|
91
|
+
| **CRITICAL** | 되돌릴 수 없는 파괴 또는 전체 시스템 접근 | `rm -rf`, `sudo`, `terraform destroy`, `dd`, `curl \| sh` |
|
|
92
|
+
| **HIGH** | 시스템/원격/인프라에 대한 중대한 변경 | `git push --force`, `chmod`, `aws`, `kubectl`, `ssh` |
|
|
93
|
+
| **MEDIUM** | 제한된 부작용, 빌드/런타임 도구 | `docker`, `npm`, `node`, `curl`, `brew`, `sed` |
|
|
94
|
+
| **LOW** | 읽기 전용 또는 안전한 개발 도구 | `cat`, `ls`, `grep`, `git` (push 제외), `eslint`, `jest` |
|
|
95
|
+
|
|
96
|
+
컨텍스트가 중요합니다 — `git` 단독은 low지만, `git push --force`는 critical로 상승합니다. 명령어 이름뿐 아니라 전체 권한 문자열을 패턴 매칭합니다.
|
|
97
|
+
|
|
84
98
|
## 요구사항
|
|
85
99
|
|
|
86
100
|
- Node.js >= 18
|
package/README.md
CHANGED
|
@@ -32,6 +32,7 @@ By default, ccperm scans all projects under `~` and launches an interactive TUI.
|
|
|
32
32
|
| `--verbose` | Detailed static output with all permissions listed |
|
|
33
33
|
| `--fix` | Auto-fix deprecated `:*` patterns to ` *` |
|
|
34
34
|
| `--update` | Self-update via `npm install -g ccperm@latest` |
|
|
35
|
+
| `--hey-claude-witness-me` | LLM-friendly markdown audit briefing with risk classification |
|
|
35
36
|
| `--debug` | Show scan diagnostics (file paths, timing) |
|
|
36
37
|
| `--help`, `-h` | Show help |
|
|
37
38
|
| `--version`, `-v` | Show version |
|
|
@@ -81,6 +82,19 @@ ccperm distinguishes three levels of Claude Code settings:
|
|
|
81
82
|
|
|
82
83
|
Permissions are additive — global + shared + local are merged at runtime.
|
|
83
84
|
|
|
85
|
+
## Risk Classification
|
|
86
|
+
|
|
87
|
+
Each permission is assigned a risk level inspired by [Destructive Command Guard (DCG)](https://github.com/Dicklesworthstone/destructive_command_guard). Used in `--hey-claude-witness-me` output and the TUI info mode.
|
|
88
|
+
|
|
89
|
+
| Level | Meaning | Examples |
|
|
90
|
+
|-------|---------|----------|
|
|
91
|
+
| **CRITICAL** | Irreversible destruction or full system access | `rm -rf`, `sudo`, `terraform destroy`, `dd`, `curl \| sh` |
|
|
92
|
+
| **HIGH** | Significant changes to system, remote, or infrastructure | `git push --force`, `chmod`, `aws`, `kubectl`, `ssh` |
|
|
93
|
+
| **MEDIUM** | Controlled side effects, build/runtime tools | `docker`, `npm`, `node`, `curl`, `brew`, `sed` |
|
|
94
|
+
| **LOW** | Read-only or safe dev tools | `cat`, `ls`, `grep`, `git` (non-push), `eslint`, `jest` |
|
|
95
|
+
|
|
96
|
+
Context matters — `git` alone is low, but `git push --force` escalates to critical. Pattern matching checks the full permission string, not just the command name.
|
|
97
|
+
|
|
84
98
|
## Requirements
|
|
85
99
|
|
|
86
100
|
- Node.js >= 18
|
package/dist/explain.js
CHANGED
|
@@ -134,35 +134,66 @@ const CRITICAL_PATTERNS = [
|
|
|
134
134
|
[/git\s+reset\s+--hard/, 'Hard reset (destroys uncommitted changes)', 'core.git'],
|
|
135
135
|
[/git\s+clean\s+-f/, 'Remove untracked files permanently', 'core.git'],
|
|
136
136
|
[/git\s+stash\s+clear/, 'Delete all stashed changes', 'core.git'],
|
|
137
|
+
[/git\s+filter-branch/, 'Permanent history rewrite', 'core.git'],
|
|
137
138
|
// containers
|
|
138
139
|
[/docker\s+system\s+prune/, 'Prune all docker data', 'containers.docker'],
|
|
140
|
+
[/docker\s+volume\s+prune/, 'Delete all unused volumes', 'containers.docker'],
|
|
139
141
|
// kubernetes
|
|
140
142
|
[/kubectl\s+delete\s+namespace/, 'Delete entire namespace', 'kubernetes.kubectl'],
|
|
141
143
|
[/kubectl\s+delete.*--all/, 'Delete all resources', 'kubernetes.kubectl'],
|
|
144
|
+
[/kubectl\s+delete\s+pvc/, 'Delete persistent volume claim', 'kubernetes.kubectl'],
|
|
142
145
|
// cloud
|
|
143
146
|
[/aws\s+s3\s+rb|aws\s+s3\s+rm.*--recursive/, 'Delete S3 data', 'cloud.aws'],
|
|
147
|
+
[/aws\s+ec2\s+terminate/, 'Terminate EC2 instances', 'cloud.aws'],
|
|
148
|
+
[/aws\s+rds\s+delete/, 'Delete RDS database', 'cloud.aws'],
|
|
149
|
+
[/aws\s+iam\s+delete/, 'Delete IAM resource', 'cloud.aws'],
|
|
144
150
|
[/terraform\s+destroy/, 'Destroy infrastructure', 'infrastructure.terraform'],
|
|
151
|
+
[/terraform\s+apply\s+.*-auto-approve/, 'Auto-approve infrastructure changes', 'infrastructure.terraform'],
|
|
145
152
|
// system
|
|
146
153
|
[/chmod\s+777|chmod\s+-R/, 'Broad permission change', 'system.permissions'],
|
|
154
|
+
[/chmod\s+000/, 'Remove all file access', 'system.permissions'],
|
|
155
|
+
[/iptables\s+-F/, 'Flush firewall rules', 'system.network'],
|
|
156
|
+
[/\beval\b/, 'Arbitrary code execution', 'system'],
|
|
147
157
|
// catch-all dangerous
|
|
148
158
|
[/mkfs|shred|wipefs/, 'Disk destruction', 'core.filesystem'],
|
|
149
159
|
[/curl.*\|\s*sh|curl.*\|\s*bash|wget.*\|\s*sh/, 'Pipe to shell (remote code execution)', 'networking'],
|
|
160
|
+
// database destructive
|
|
161
|
+
[/DROP\s+DATABASE/i, 'Drop database', 'database'],
|
|
162
|
+
[/DROP\s+TABLE/i, 'Drop table', 'database'],
|
|
163
|
+
[/DROP\s+SCHEMA.*CASCADE/i, 'Drop schema cascade', 'database'],
|
|
164
|
+
[/TRUNCATE/i, 'Truncate table data', 'database'],
|
|
150
165
|
];
|
|
151
166
|
const HIGH_PATTERNS = [
|
|
152
167
|
// core.git
|
|
153
168
|
[/git\s+push/, 'Push to remote', 'core.git'],
|
|
154
169
|
[/git\s+rebase/, 'Rewrite commit history', 'core.git'],
|
|
155
170
|
[/git\s+branch\s+-D/, 'Force delete branch', 'core.git'],
|
|
171
|
+
[/git\s+checkout\s+.*--/, 'Discard uncommitted changes', 'core.git'],
|
|
172
|
+
[/git\s+stash\s+drop/, 'Drop stashed changes', 'core.git'],
|
|
156
173
|
// containers
|
|
157
174
|
[/docker\s+rm/, 'Remove containers', 'containers.docker'],
|
|
158
175
|
[/docker\s+run/, 'Run container', 'containers.docker'],
|
|
176
|
+
[/docker\s+image\s+prune.*--all/, 'Delete all images', 'containers.docker'],
|
|
177
|
+
// kubernetes
|
|
178
|
+
[/kubectl\s+drain/, 'Evict pods from node', 'kubernetes.kubectl'],
|
|
179
|
+
[/kubectl\s+scale.*--replicas=0/, 'Scale to zero (service down)', 'kubernetes.kubectl'],
|
|
180
|
+
[/helm\s+uninstall|helm\s+delete/, 'Uninstall Helm release', 'kubernetes.helm'],
|
|
159
181
|
// cloud
|
|
160
182
|
[/aws\s+ecs/, 'ECS management', 'cloud.aws'],
|
|
161
183
|
[/aws\s+codepipeline/, 'CI/CD pipeline', 'cloud.aws'],
|
|
162
184
|
[/aws\s+ssm/, 'Systems Manager', 'cloud.aws'],
|
|
185
|
+
[/aws\s+lambda\s+delete/, 'Delete Lambda function', 'cloud.aws'],
|
|
186
|
+
[/gcloud.*delete/, 'Delete GCP resource', 'cloud.gcp'],
|
|
187
|
+
// remote
|
|
188
|
+
[/rsync.*--delete/, 'Sync with deletion', 'remote.rsync'],
|
|
163
189
|
// deploy
|
|
164
190
|
[/npm\s+publish/, 'Publish to npm', 'packages'],
|
|
165
191
|
[/vercel\s+--prod/, 'Deploy to production', 'deploy'],
|
|
192
|
+
// database
|
|
193
|
+
[/redis-cli.*FLUSHALL/i, 'Flush all Redis data', 'database.redis'],
|
|
194
|
+
[/redis-cli.*FLUSHDB/i, 'Flush Redis database', 'database.redis'],
|
|
195
|
+
// secrets
|
|
196
|
+
[/vault\s+delete/, 'Delete Vault secret', 'secrets.vault'],
|
|
166
197
|
];
|
|
167
198
|
// Write path risk assessment
|
|
168
199
|
const WRITE_CRITICAL = [
|
package/dist/interactive.js
CHANGED
|
@@ -7,6 +7,15 @@ exports.startInteractive = startInteractive;
|
|
|
7
7
|
const node_readline_1 = __importDefault(require("node:readline"));
|
|
8
8
|
const colors_js_1 = require("./colors.js");
|
|
9
9
|
const explain_js_1 = require("./explain.js");
|
|
10
|
+
function severityTag(s) {
|
|
11
|
+
const labels = {
|
|
12
|
+
critical: `${colors_js_1.RED}CRITICAL${colors_js_1.NC}`,
|
|
13
|
+
high: `${colors_js_1.YELLOW}HIGH${colors_js_1.NC} `,
|
|
14
|
+
medium: `${colors_js_1.DIM}MEDIUM${colors_js_1.NC} `,
|
|
15
|
+
low: `${colors_js_1.DIM}LOW${colors_js_1.NC} `,
|
|
16
|
+
};
|
|
17
|
+
return labels[s];
|
|
18
|
+
}
|
|
10
19
|
// Clean up messy bash permission labels for display
|
|
11
20
|
function cleanLabel(label) {
|
|
12
21
|
let s = label;
|
|
@@ -201,10 +210,12 @@ function renderDetail(state, withPerms, results) {
|
|
|
201
210
|
const clean = cleanLabel(item.name);
|
|
202
211
|
if (state.showInfo) {
|
|
203
212
|
const info = (0, explain_js_1.explain)(group.category, item.name);
|
|
204
|
-
const
|
|
213
|
+
const tag = severityTag(info.risk);
|
|
214
|
+
const tagLen = info.risk.length + 2; // tag visual width (e.g. "CRITICAL" + 2 spaces)
|
|
215
|
+
const nameMax = Math.min(30, w - tagLen - 14);
|
|
205
216
|
const name = clean.length > nameMax ? clean.slice(0, nameMax - 1) + '…' : clean;
|
|
206
217
|
const desc = info.description ? `${colors_js_1.DIM}${info.description}${colors_js_1.NC}` : '';
|
|
207
|
-
navRows.push({ text: ` ${pad(name, nameMax)}
|
|
218
|
+
navRows.push({ text: ` ${pad(name, nameMax)} ${tag} ${desc}`, perm: item.name });
|
|
208
219
|
}
|
|
209
220
|
else {
|
|
210
221
|
const maxLen = w - 8;
|