@objctp/opencode-shell-routines 1.2.0
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/LICENSE +21 -0
- package/README.md +114 -0
- package/agents/shell-architect.md +88 -0
- package/agents/shell-expert.md +60 -0
- package/commands/shell-audit.md +47 -0
- package/commands/shell-batch-exec.md +48 -0
- package/commands/shell-new.md +57 -0
- package/commands/shell-routines-setup.md +66 -0
- package/commands/shell-test-run.md +46 -0
- package/opencode.json +19 -0
- package/package.json +34 -0
- package/plugins/shell-hooks.ts +150 -0
- package/scripts/lib-batch.sh +297 -0
- package/scripts/lib-common.sh +332 -0
- package/skills/shell-batch-operations/SKILL.md +97 -0
- package/skills/shell-batch-operations/assets/batch-template.sh +124 -0
- package/skills/shell-batch-operations/examples/data-pipeline.sh +157 -0
- package/skills/shell-batch-operations/examples/file-batch.sh +140 -0
- package/skills/shell-batch-operations/references/decision-tree.md +53 -0
- package/skills/shell-best-practices/SKILL.md +313 -0
- package/skills/shell-best-practices/assets/library.sh +142 -0
- package/skills/shell-best-practices/assets/minimal.sh +54 -0
- package/skills/shell-best-practices/assets/posix.sh +180 -0
- package/skills/shell-best-practices/assets/standard.sh +203 -0
- package/skills/shell-best-practices/references/patterns.md +386 -0
- package/skills/shell-best-practices/references/security.md +195 -0
- package/skills/shell-debugging/SKILL.md +115 -0
- package/skills/shell-debugging/examples/debug-session.md +165 -0
- package/skills/shell-debugging/references/debugging-guide.md +336 -0
- package/skills/shell-profiling/SKILL.md +154 -0
- package/skills/shell-profiling/examples/profile-session.md +225 -0
- package/skills/shell-profiling/references/optimisation-patterns.md +373 -0
- package/skills/shell-profiling/references/profiling-tools.md +318 -0
- package/skills/shell-profiling/scripts/bench.sh +82 -0
- package/skills/shell-profiling/scripts/trace-aggregate.sh +34 -0
- package/skills/shell-review/SKILL.md +61 -0
- package/skills/shell-review/examples/sample-review.md +42 -0
- package/skills/shell-review/references/guidelines.md +48 -0
- package/skills/shell-review/references/review-template.md +56 -0
- package/skills/shell-security/SKILL.md +128 -0
- package/skills/shell-security/examples/dangerous-command-review.md +231 -0
- package/skills/shell-security/examples/secure-script-example.sh +317 -0
- package/skills/shell-security/references/dangerous-commands.md +561 -0
- package/skills/shell-security/references/security-patterns.md +30 -0
- package/skills/shell-security/references/sensitive-files.md +525 -0
- package/skills/shell-security/scripts/security-audit.sh +208 -0
- package/skills/shell-test/SKILL.md +237 -0
- package/skills/shell-test/examples/test-example.md +74 -0
- package/skills/shell-test/references/advanced-patterns.md +52 -0
- package/skills/shell-test/references/assertions.md +184 -0
- package/skills/shell-test/references/test-template.md +60 -0
- package/skills/shell-test/scripts/public-coverage.sh +93 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
# Dangerous Commands Reference
|
|
2
|
+
|
|
3
|
+
Catalogue of destructive and dangerous shell commands with risk levels, explanations, and safer alternatives.
|
|
4
|
+
|
|
5
|
+
## Severity Levels
|
|
6
|
+
|
|
7
|
+
- **Fatal** — Can destroy system or cause catastrophic data loss
|
|
8
|
+
- **Severe** — Can cause significant damage or security breaches
|
|
9
|
+
- **Moderate** — Can cause issues under certain conditions
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Fatal Commands
|
|
14
|
+
|
|
15
|
+
### `rm -rf /`
|
|
16
|
+
|
|
17
|
+
**What:** Recursively deletes all files from root directory
|
|
18
|
+
|
|
19
|
+
**Why it's dangerous:**
|
|
20
|
+
- Deletes everything without confirmation
|
|
21
|
+
- Modern systems have `--preserve-root` protection, but it can be overridden
|
|
22
|
+
- Common accidents with variables: `rm -rf $VAR /important-dir` when VAR is empty
|
|
23
|
+
|
|
24
|
+
**Examples of dangerous usage:**
|
|
25
|
+
```bash
|
|
26
|
+
rm -rf / # Attempts to delete root
|
|
27
|
+
rm -rf --no-preserve-root / # Overrides protection
|
|
28
|
+
rm -rf "$TARGET_DIR" / # Space after variable if TARGET_DIR is empty
|
|
29
|
+
rm -rf $DIR/* # Unquoted variable with glob
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Safer alternatives:**
|
|
33
|
+
```bash
|
|
34
|
+
# Add --preserve-root explicitly
|
|
35
|
+
rm -rf --preserve-root "$TARGET_DIR"
|
|
36
|
+
|
|
37
|
+
# Validate directory first
|
|
38
|
+
[[ -d "$TARGET_DIR" ]] || { echo "Error: Invalid directory" >&2; exit 1; }
|
|
39
|
+
rm -rf -- "$TARGET_DIR"
|
|
40
|
+
|
|
41
|
+
# Add confirmation for destructive operations
|
|
42
|
+
rm -rfI "$TARGET_DIR" # -I prompts once before removing more than 3 files
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Auto-fix:** Yes (add `--preserve-root` flag)
|
|
46
|
+
|
|
47
|
+
**Fix command:**
|
|
48
|
+
```bash
|
|
49
|
+
sed -i 's/rm -rf /rm -rf --preserve-root /g' file.sh
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
> **Portability:** these `sed -i` one-liners use GNU syntax. On macOS/BSD use `sed -i ''` (or `sed -i.bak` and remove the backup).
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### `dd` with destructive targets
|
|
57
|
+
|
|
58
|
+
**What:** Low-level copy command that can overwrite any device
|
|
59
|
+
|
|
60
|
+
**Why it's dangerous:**
|
|
61
|
+
- Writes directly to devices without safety checks
|
|
62
|
+
- One typo can destroy disk data: `dd if=/dev/zero of=/dev/sda`
|
|
63
|
+
- No confirmation prompts
|
|
64
|
+
|
|
65
|
+
**Examples of dangerous usage:**
|
|
66
|
+
```bash
|
|
67
|
+
dd if=/dev/zero of=/dev/sda # Wipes entire disk
|
|
68
|
+
dd if=/dev/random of=/dev/sda1 # Corrupts partition
|
|
69
|
+
dd if=file of=/dev/sda bs=1M count=100 # Overwrites disk start
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Safer alternatives:**
|
|
73
|
+
```bash
|
|
74
|
+
# Use dedicated wipe tools with confirmation
|
|
75
|
+
wipe /dev/sda
|
|
76
|
+
|
|
77
|
+
# Or add extensive validation
|
|
78
|
+
DEVICE="/dev/sda"
|
|
79
|
+
[[ -b "$DEVICE" ]] || { echo "Not a block device" >&2; exit 1; }
|
|
80
|
+
echo "About to wipe $DEVICE - press Ctrl+C to abort"
|
|
81
|
+
read -r
|
|
82
|
+
dd if=/dev/zero of="$DEVICE"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Auto-fix:** No (requires intent verification)
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Severe Commands
|
|
90
|
+
|
|
91
|
+
### Fork Bombs
|
|
92
|
+
|
|
93
|
+
**What:** Processes that spawn themselves recursively, exhausting system resources
|
|
94
|
+
|
|
95
|
+
**Why it's dangerous:**
|
|
96
|
+
- Crashes system by exhausting process table and memory
|
|
97
|
+
- Can prevent legitimate processes from running
|
|
98
|
+
- Requires system reboot to recover
|
|
99
|
+
|
|
100
|
+
**Examples of dangerous usage:**
|
|
101
|
+
```bash
|
|
102
|
+
:(){ :|:& };: # Classic bash fork bomb
|
|
103
|
+
bomb() { bomb|bomb& }; bomb # Named version
|
|
104
|
+
foo() { foo & }; foo # Simpler variant
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Safer alternatives:**
|
|
108
|
+
```bash
|
|
109
|
+
# Use process limits with ulimit
|
|
110
|
+
ulimit -u 100 # Limit to 100 processes
|
|
111
|
+
# Then run the process with monitoring
|
|
112
|
+
|
|
113
|
+
# Or use proper job control with supervision
|
|
114
|
+
while true; do
|
|
115
|
+
worker &
|
|
116
|
+
(( count++ >= MAX_WORKERS )) && break
|
|
117
|
+
done
|
|
118
|
+
wait
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Auto-fix:** No (requires architecture review)
|
|
122
|
+
|
|
123
|
+
**Detect:** `grep -nE ':\s*\(\)\s*\{.*\|.*:&\s*\}\s*;' file.sh`
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### `chmod -R 777` on system directories
|
|
128
|
+
|
|
129
|
+
**What:** Makes files world-writable, recursively
|
|
130
|
+
|
|
131
|
+
**Why it's dangerous:**
|
|
132
|
+
- Any user can modify system files
|
|
133
|
+
- Escalates privileges for attackers
|
|
134
|
+
- Breaks security boundaries
|
|
135
|
+
|
|
136
|
+
**Examples of dangerous usage:**
|
|
137
|
+
```bash
|
|
138
|
+
chmod -R 777 /etc # Makes all config world-writable
|
|
139
|
+
chmod -R 777 /var/www # Web root becomes modifiable by anyone
|
|
140
|
+
chmod 777 ~/.ssh # SSH keys become readable
|
|
141
|
+
chmod -R a+rwx /app # Same as 777
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Safer alternatives:**
|
|
145
|
+
```bash
|
|
146
|
+
# Use specific permissions
|
|
147
|
+
chmod -R 755 /var/www/html # Directories: rwxr-xr-x
|
|
148
|
+
chmod 644 /var/www/html/*.php # Files: rw-r--r--
|
|
149
|
+
chmod 700 ~/.ssh # SSH directory: rwx------
|
|
150
|
+
chmod 600 ~/.ssh/id_rsa # Private keys: rw-------
|
|
151
|
+
|
|
152
|
+
# Use setfacl for granular permissions
|
|
153
|
+
setfacl -m u:www-data:rw /app/file.txt
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Auto-fix:** Yes (replace 777 with 755 for directories)
|
|
157
|
+
|
|
158
|
+
**Fix command:**
|
|
159
|
+
```bash
|
|
160
|
+
sed -i -E 's/chmod\s+777/chmod 755/g; s/chmod\s+-R\s+777/chmod -R 755/g' file.sh
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Detect:** `grep -nE 'chmod\s+777|chmod\s+a+rwx|chmod\s+-R.*777' file.sh`
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
### `crontab -r`
|
|
168
|
+
|
|
169
|
+
**What:** Removes all cron jobs without confirmation
|
|
170
|
+
|
|
171
|
+
**Why it's dangerous:**
|
|
172
|
+
- Destroys scheduled tasks immediately
|
|
173
|
+
- No "undo" option
|
|
174
|
+
- Typo: `crontab -r` instead of `crontab -e` is common
|
|
175
|
+
|
|
176
|
+
**Examples of dangerous usage:**
|
|
177
|
+
```bash
|
|
178
|
+
crontab -r # Deletes all cron jobs
|
|
179
|
+
crontab -r -u user # Deletes another user's crontab
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Safer alternatives:**
|
|
183
|
+
```bash
|
|
184
|
+
# Always use -e to edit
|
|
185
|
+
crontab -e
|
|
186
|
+
|
|
187
|
+
# Backup before modifying
|
|
188
|
+
crontab -l > crontab.bak
|
|
189
|
+
crontab -e
|
|
190
|
+
|
|
191
|
+
# Use explicit confirmation
|
|
192
|
+
confirm_crontab_rm() {
|
|
193
|
+
echo "This will delete ALL cron jobs. Type 'yes' to confirm:"
|
|
194
|
+
read -r response
|
|
195
|
+
[[ "$response" == "yes" ]] && crontab -r
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Auto-fix:** Partial (warn user, suggest backup)
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
### `kill -9 -1` or `killall -9`
|
|
204
|
+
|
|
205
|
+
**What:** Sends SIGKILL to all processes
|
|
206
|
+
|
|
207
|
+
**Why it's dangerous:**
|
|
208
|
+
- Terminates everything including shell itself
|
|
209
|
+
- Can cause data loss
|
|
210
|
+
- System becomes unstable
|
|
211
|
+
|
|
212
|
+
**Examples of dangerous usage:**
|
|
213
|
+
```bash
|
|
214
|
+
kill -9 -1 # Kill all processes
|
|
215
|
+
killall -9 program # Kill ALL instances by name
|
|
216
|
+
pkill -9 -f pattern # Kill processes matching pattern
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Safer alternatives:**
|
|
220
|
+
```bash
|
|
221
|
+
# Use SIGTERM first for graceful shutdown
|
|
222
|
+
killall program # No -9, allows graceful shutdown
|
|
223
|
+
|
|
224
|
+
# Target specific process IDs
|
|
225
|
+
kill $PID
|
|
226
|
+
|
|
227
|
+
# Use pgrep to find exact processes
|
|
228
|
+
pgrep -f "exact_pattern" | xargs kill
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Auto-fix:** Partial (warn, suggest specific targeting)
|
|
232
|
+
|
|
233
|
+
**Detect:** `grep -nE 'kill\s+-9\s+-1|killall\s+-9|pkill\s+-9' file.sh`
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Moderate Risk
|
|
238
|
+
|
|
239
|
+
### `: > /etc/passwd` or `echo > /etc/passwd`
|
|
240
|
+
|
|
241
|
+
**What:** Truncates or overwrites critical system files
|
|
242
|
+
|
|
243
|
+
**Why it's dangerous:**
|
|
244
|
+
- Destroys system authentication
|
|
245
|
+
- Makes system unusable
|
|
246
|
+
- Requires recovery media to fix
|
|
247
|
+
|
|
248
|
+
**Examples of dangerous usage:**
|
|
249
|
+
```bash
|
|
250
|
+
> /etc/passwd # Truncates password file
|
|
251
|
+
echo "line" >> /etc/sudoers # Corrupts sudoers (must use visudo)
|
|
252
|
+
cat > /etc/shadow # Overwrites shadow file
|
|
253
|
+
: > /etc/hosts # Clears hostname mappings
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Safer alternatives:**
|
|
257
|
+
```bash
|
|
258
|
+
# Use proper tools for system files
|
|
259
|
+
vipw # Edit /etc/passwd safely
|
|
260
|
+
visudo # Edit /etc/sudoers with validation
|
|
261
|
+
echo "127.0.0.1 localhost" > /tmp/hosts && mv /tmp/hosts /etc/hosts
|
|
262
|
+
|
|
263
|
+
# Validate before writing to system files
|
|
264
|
+
validate_hosts() {
|
|
265
|
+
grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' "$1" || { echo "Invalid hosts file" >&2; return 1; }
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Auto-fix:** No (requires manual review of intent)
|
|
270
|
+
|
|
271
|
+
**Detect:** `grep -nE '>\s*/etc/(passwd|shadow|sudoers|hosts|group|crontab)' file.sh`
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
### `find / -exec rm {} \;`
|
|
276
|
+
|
|
277
|
+
**What:** Searches and deletes recursively from root
|
|
278
|
+
|
|
279
|
+
**Why it's dangerous:**
|
|
280
|
+
- Searches entire filesystem
|
|
281
|
+
- Any typo in delete command is catastrophic
|
|
282
|
+
- Slow and resource-intensive
|
|
283
|
+
|
|
284
|
+
**Examples of dangerous usage:**
|
|
285
|
+
```bash
|
|
286
|
+
find / -name "*.log" -exec rm {} \; # Deletes all .log files system-wide
|
|
287
|
+
find / -exec rm {} + # Deletes everything find returns
|
|
288
|
+
find /var -type f -delete # Deletes all files in /var
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**Safer alternatives:**
|
|
292
|
+
```bash
|
|
293
|
+
# Limit search scope
|
|
294
|
+
find /var/log -name "*.log" -mtime +30 -delete
|
|
295
|
+
|
|
296
|
+
# Use -print0 and -0 for safe handling
|
|
297
|
+
find /var/log -name "*.log" -print0 | xargs -0 rm
|
|
298
|
+
|
|
299
|
+
# Add depth limit
|
|
300
|
+
find /path -maxdepth 3 -name "pattern" -exec rm {} \;
|
|
301
|
+
|
|
302
|
+
# Preview before deleting
|
|
303
|
+
find /path -name "pattern" -ls
|
|
304
|
+
find /path -name "pattern" -delete
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Auto-fix:** Partial (warn if searching from root)
|
|
308
|
+
|
|
309
|
+
**Detect:** `grep -nE 'find\s+/\s+-exec.*rm' file.sh`
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
### `mv ~ /dev/null` or `rm -rf .*`
|
|
314
|
+
|
|
315
|
+
**What:** Deletes home directory or traverses upwards
|
|
316
|
+
|
|
317
|
+
**Why it's dangerous:**
|
|
318
|
+
- `~` expands to home directory
|
|
319
|
+
- `.*` includes `..` which traverses to parent
|
|
320
|
+
- Can delete directories outside current path
|
|
321
|
+
|
|
322
|
+
**Examples of dangerous usage:**
|
|
323
|
+
```bash
|
|
324
|
+
rm -rf .* # Deletes .* including ../.. (parent directories)
|
|
325
|
+
mv ~ /dev/null # Moves home directory to null device
|
|
326
|
+
rm -rf $HOME/* # If HOME is unset, might delete from /
|
|
327
|
+
rm -rf * .* # Deletes current dir AND parent dirs
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**Safer alternatives:**
|
|
331
|
+
```bash
|
|
332
|
+
# Be explicit about what to delete
|
|
333
|
+
rm -rf .[!.]* ..?* # Excludes . and ..
|
|
334
|
+
|
|
335
|
+
# Always validate HOME
|
|
336
|
+
: "${HOME:?HOME variable is not set}"
|
|
337
|
+
rm -rf "$HOME"/temp/*
|
|
338
|
+
|
|
339
|
+
# Use find for precise control
|
|
340
|
+
find . -maxdepth 1 -name '.*' ! -name '.' ! -name '..' -delete
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**Auto-fix:** Yes (warn about `.*` pattern)
|
|
344
|
+
|
|
345
|
+
**Detect:** `grep -nE 'rm\s+-rf.*\.\*|mv\s+.*~/dev/null' file.sh`
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Common Mistake Patterns
|
|
350
|
+
|
|
351
|
+
### Space After Variable
|
|
352
|
+
|
|
353
|
+
**What:** Unquoted variable with space after it
|
|
354
|
+
|
|
355
|
+
**Why it's dangerous:**
|
|
356
|
+
- Empty variable causes next argument to be deleted
|
|
357
|
+
- Example: `rm -rf $VAR /path` when VAR is empty becomes `rm -rf /path`
|
|
358
|
+
|
|
359
|
+
**Examples:**
|
|
360
|
+
```bash
|
|
361
|
+
rm -rf $TARGET_DIR /backup # If TARGET_DIR is empty → deletes /backup
|
|
362
|
+
rm $FILE /important # If FILE is empty → deletes /important
|
|
363
|
+
cat $FILE > /etc/config # If FILE is empty → truncates config
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**Safer alternatives:**
|
|
367
|
+
```bash
|
|
368
|
+
# Always quote variables
|
|
369
|
+
rm -rf -- "$TARGET_DIR" /backup
|
|
370
|
+
|
|
371
|
+
# Or validate first
|
|
372
|
+
: "${TARGET_DIR:?Variable is empty or unset}"
|
|
373
|
+
rm -rf -- "$TARGET_DIR" /backup
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**Auto-fix:** Yes (add quotes)
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
### Wrong Directory in `cd`
|
|
381
|
+
|
|
382
|
+
**What:** Deletes files in wrong directory due to cd failure
|
|
383
|
+
|
|
384
|
+
**Why it's dangerous:**
|
|
385
|
+
- `cd` fails silently with `set +e`
|
|
386
|
+
- Subsequent commands run in wrong directory
|
|
387
|
+
|
|
388
|
+
**Examples:**
|
|
389
|
+
```bash
|
|
390
|
+
cd /nonexistent || rm -rf * # cd fails, deletes current dir
|
|
391
|
+
cd /tmp; rm -rf * # If cd fails, rm runs in current dir
|
|
392
|
+
cd "$DIR"; rm -rf * # DIR might be empty or wrong
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**Safer alternatives:**
|
|
396
|
+
```bash
|
|
397
|
+
# Always check cd success
|
|
398
|
+
cd /nonexistent || exit 1
|
|
399
|
+
rm -rf *
|
|
400
|
+
|
|
401
|
+
# Or use subshell
|
|
402
|
+
(
|
|
403
|
+
cd /nonexistent || exit
|
|
404
|
+
rm -rf *
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
# Use `set -e` to fail on errors
|
|
408
|
+
set -e
|
|
409
|
+
cd /nonexistent
|
|
410
|
+
rm -rf * # Never reached if cd fails
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
**Auto-fix:** Partial (warn if cd not checked)
|
|
414
|
+
|
|
415
|
+
**Detect:** `grep -nE 'cd\s+[^|;]*$' file.sh` (cd at end of line without `||`)
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
### Unquoted Glob in `rm`
|
|
420
|
+
|
|
421
|
+
**What:** Glob expands unexpectedly
|
|
422
|
+
|
|
423
|
+
**Why it's dangerous:**
|
|
424
|
+
- Special characters in filenames cause expansion
|
|
425
|
+
- File named `-rf` could be parsed as flag
|
|
426
|
+
|
|
427
|
+
**Examples:**
|
|
428
|
+
```bash
|
|
429
|
+
rm $filename # If filename="-rf" → becomes rm -rf
|
|
430
|
+
rm * # Expands to all files, including dangerous ones
|
|
431
|
+
rm $@ # User can inject flags
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**Safer alternatives:**
|
|
435
|
+
```bash
|
|
436
|
+
# Use -- to end option parsing
|
|
437
|
+
rm -- "$filename"
|
|
438
|
+
|
|
439
|
+
# Quote all variables
|
|
440
|
+
rm -- "$filename"
|
|
441
|
+
rm -- "$@"
|
|
442
|
+
|
|
443
|
+
# Use find for complex patterns
|
|
444
|
+
find . -maxdepth 1 -type f -name "pattern" -delete
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**Auto-fix:** Yes (add `--` and quotes)
|
|
448
|
+
|
|
449
|
+
**Detect:** `grep -nE 'rm\s+[a-zA-Z_]\w+' file.sh`
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Dynamic Execution
|
|
454
|
+
|
|
455
|
+
### `eval` with variable expansion
|
|
456
|
+
|
|
457
|
+
**What:** Passing variables to `eval`, allowing arbitrary code execution
|
|
458
|
+
|
|
459
|
+
**Why it's dangerous:**
|
|
460
|
+
- If the variable contains user input, attackers can execute arbitrary commands
|
|
461
|
+
- Common in frameworks that build commands dynamically (test runners, build tools)
|
|
462
|
+
- Hard to audit because the executed code is not visible in the source
|
|
463
|
+
|
|
464
|
+
**Examples of dangerous usage:**
|
|
465
|
+
```bash
|
|
466
|
+
eval "$user_input" # Direct injection vector
|
|
467
|
+
eval "${cmd#eval }" # String manipulation before eval
|
|
468
|
+
eval "function $name() { $body; }" # Dynamic function creation
|
|
469
|
+
eval "args=($input)" # Parsing via eval
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
**Safer alternatives:**
|
|
473
|
+
```bash
|
|
474
|
+
# Use arrays instead of eval for argument building
|
|
475
|
+
args=(--flag "$value")
|
|
476
|
+
command "${args[@]}"
|
|
477
|
+
|
|
478
|
+
# Use declare -f for function existence checks
|
|
479
|
+
declare -f "$func_name" >/dev/null || return 1
|
|
480
|
+
|
|
481
|
+
# Use parameter expansion for string parsing
|
|
482
|
+
result="${var%%pattern*}"
|
|
483
|
+
|
|
484
|
+
# For data parsing, use explicit parsers instead of eval
|
|
485
|
+
while IFS= read -r key value; do
|
|
486
|
+
...
|
|
487
|
+
done < "$config_file"
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
**Auto-fix:** No (requires context review -- many eval uses are intentional, e.g. test frameworks)
|
|
491
|
+
|
|
492
|
+
**Detect:** `grep -nE 'eval\s+\$|eval\s+"[^"]*\$\{' file.sh`
|
|
493
|
+
|
|
494
|
+
**Assessment guide:** Not all dynamic execution is a vulnerability. Classify each finding:
|
|
495
|
+
|
|
496
|
+
| Classification | Criteria | Examples |
|
|
497
|
+
|----------------|----------|---------|
|
|
498
|
+
| **By design** | Script is a developer tool, framework, or CLI that *inherently* executes user-supplied code. The eval/source is the feature, not a bug. | Test runners (`source "$test_file"`), mock frameworks (`eval "function $cmd()..."`), REPL shells, build tools |
|
|
499
|
+
| **Needs review** | Script processes external input (files, network, arguments) from untrusted sources. The eval/source handles data the developer does not fully control. | CGI scripts, CI pipelines reading PR content, scripts that `eval "$(curl ...)"` |
|
|
500
|
+
| **Safe** | Variable is internally generated and fully controlled. No external input reaches the eval. | `eval "args=($input)"` where `$input` came from `printf '%q'`, internal temp paths from `mktemp` |
|
|
501
|
+
|
|
502
|
+
**How to judge:** Read the script's purpose first. If it is a testing framework, plugin loader, or build tool, most dynamic execution findings will be "by design." If it is a deployment script, cron job, or web-facing tool, treat every finding as "needs review" unless proven otherwise. Report "by design" findings as informational, not as actionable security issues.
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
506
|
+
### Dynamic `source` with variable path
|
|
507
|
+
|
|
508
|
+
**What:** Sourcing files from variable paths
|
|
509
|
+
|
|
510
|
+
**Why it's dangerous:**
|
|
511
|
+
- If the path is user-controlled, an attacker can load malicious code
|
|
512
|
+
- Common in plugin loaders and configuration systems
|
|
513
|
+
- The sourced file executes in the current shell with full privileges
|
|
514
|
+
|
|
515
|
+
**Examples of dangerous usage:**
|
|
516
|
+
```bash
|
|
517
|
+
source "$config_file" # Variable path
|
|
518
|
+
. "$plugin_path" # Dot-source equivalent
|
|
519
|
+
source "${BASHUNIT_BOOTSTRAP:-}" # Environment-controlled path
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
**Safer alternatives:**
|
|
523
|
+
```bash
|
|
524
|
+
# Validate path before sourcing
|
|
525
|
+
case "$config_file" in
|
|
526
|
+
*.sh) ;;
|
|
527
|
+
*) echo "Invalid config file" >&2; return 1 ;;
|
|
528
|
+
esac
|
|
529
|
+
[ -f "$config_file" ] || return 1
|
|
530
|
+
source "$config_file"
|
|
531
|
+
|
|
532
|
+
# Use allowlists for plugin loading
|
|
533
|
+
case "$plugin_name" in
|
|
534
|
+
plugin_a|plugin_b|plugin_c) source "plugins/${plugin_name}.sh" ;;
|
|
535
|
+
*) echo "Unknown plugin: $plugin_name" >&2; return 1 ;;
|
|
536
|
+
esac
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
**Auto-fix:** No (requires context review -- test runners inherently need to source test files)
|
|
540
|
+
|
|
541
|
+
**Detect:** `grep -nE 'source\s+\$\w+|\.\s+\$\w+' file.sh`
|
|
542
|
+
|
|
543
|
+
**Assessment guide:** Same criteria as eval above. `source "$test_file"` in a test runner is "by design." `source "$plugin"` in a web application is "needs review." Always read the script's purpose before classifying.
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
## Quick Reference Table
|
|
548
|
+
|
|
549
|
+
| Pattern | Severity | Auto-Fix | Grep to Detect |
|
|
550
|
+
|---------|----------|----------|----------------|
|
|
551
|
+
| `rm -rf /` | Fatal | Yes (add --preserve-root) | `grep -nE 'rm\s+-rf.*\s+/'` |
|
|
552
|
+
| `dd if=` | Fatal | No (manual review) | `grep -nE 'dd\s+if='` |
|
|
553
|
+
| Fork bomb | Fatal | No (architecture) | `grep -nE ':\s*\(\)\s*\{.*\|.*:&'` |
|
|
554
|
+
| `chmod 777` | Severe | Yes (use 755) | `grep -nE 'chmod\s+777'` |
|
|
555
|
+
| `crontab -r` | Severe | Partial (warn) | `grep -nE 'crontab\s+-r'` |
|
|
556
|
+
| `kill -9 -1` | Severe | Partial (warn) | `grep -nE 'kill\s+-9\s+-1'` |
|
|
557
|
+
| `> /etc/passwd` | Moderate | No (intent) | `grep -nE '>\s*/etc/'` |
|
|
558
|
+
| `find / -exec rm` | Moderate | Partial (warn) | `grep -nE 'find\s+/\s+-exec'` |
|
|
559
|
+
| `rm -rf .*` | Moderate | Yes (warn) | `grep -nE 'rm\s+-rf.*\.\*'` |
|
|
560
|
+
| `eval $var` | Moderate | No (context) | `grep -nE 'eval\s+\$\|eval\s+"[^"]*\$\{'` |
|
|
561
|
+
| `source $var` | Moderate | No (context) | `grep -nE 'source\s+\$\w+\|\.\s+\$\w+'` |
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Security Detection Patterns
|
|
2
|
+
|
|
3
|
+
Conceptual map of detection categories used by the security audit. For the actual grep commands, run `scripts/security-audit.sh` or read its source.
|
|
4
|
+
|
|
5
|
+
For detailed explanations, safer alternatives, and auto-fix commands, consult `dangerous-commands.md`.
|
|
6
|
+
|
|
7
|
+
## Detection Categories
|
|
8
|
+
|
|
9
|
+
| Category | What It Catches |
|
|
10
|
+
|----------|----------------|
|
|
11
|
+
| Destructive commands | `rm -rf /`, `dd` to block devices, `mkfs` |
|
|
12
|
+
| Fork bombs | Recursive function pipes (`:()\{:\|:&\};:`) |
|
|
13
|
+
| System file writes | Redirects to `/etc/passwd`, `/etc/shadow`, `/etc/sudoers` |
|
|
14
|
+
| Hardcoded credentials | `password=`, `api_key=`, `secret=`, `token=` with literal values |
|
|
15
|
+
| Credential formats | AWS keys (`AKIA...`), GitHub tokens (`ghp_...`), OpenAI keys (`sk-...`), Google keys (`AIza...`), Slack tokens (`xoxb-...`) |
|
|
16
|
+
| Insecure permissions | `chmod 777`, `chmod a+rwx`, recursive variants |
|
|
17
|
+
| Trap injection | `trap` commands containing `$` variable expansion |
|
|
18
|
+
| Dangerous sudo | `sudo rm`, `sudo dd`, `sudo mkfs`, `sudo chmod` |
|
|
19
|
+
| System config writes | Appends to `/etc/ssh/`, `/etc/systemd/`, `/etc/network/` |
|
|
20
|
+
| Dynamic execution | `eval $var`, `source $path`, indirect `${cmd}` |
|
|
21
|
+
## Running the Audit
|
|
22
|
+
|
|
23
|
+
Execute the bundled script to scan a file or directory:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
scripts/security-audit.sh path/to/script.sh
|
|
27
|
+
scripts/security-audit.sh path/to/directory/
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The script exits non-zero if any issues are found. Each finding includes the line number and matching code. Use the line numbers to look up detailed explanations and fix commands in `dangerous-commands.md`.
|