SuperCharge Claude Code v1.0.0 - Complete Customization Package
Features: - 30+ Custom Skills (cognitive, development, UI/UX, autonomous agents) - RalphLoop autonomous agent integration - Multi-AI consultation (Qwen) - Agent management system with sync capabilities - Custom hooks for session management - MCP servers integration - Plugin marketplace setup - Comprehensive installation script Components: - Skills: always-use-superpowers, ralph, brainstorming, ui-ux-pro-max, etc. - Agents: 100+ agents across engineering, marketing, product, etc. - Hooks: session-start-superpowers, qwen-consult, ralph-auto-trigger - Commands: /brainstorm, /write-plan, /execute-plan - MCP Servers: zai-mcp-server, web-search-prime, web-reader, zread - Binaries: ralphloop wrapper Installation: ./supercharge.sh
This commit is contained in:
125
plugins/claude-code-safety-net/src/core/analyze/find.ts
Normal file
125
plugins/claude-code-safety-net/src/core/analyze/find.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import { getBasename, stripWrappers } from '../shell.ts';
|
||||
|
||||
import { hasRecursiveForceFlags } from './rm-flags.ts';
|
||||
|
||||
const REASON_FIND_DELETE = 'find -delete permanently removes files. Use -print first to preview.';
|
||||
|
||||
export function analyzeFind(tokens: readonly string[]): string | null {
|
||||
// Check for -delete outside of -exec/-execdir blocks
|
||||
if (findHasDelete(tokens.slice(1))) {
|
||||
return REASON_FIND_DELETE;
|
||||
}
|
||||
|
||||
// Check all -exec and -execdir blocks for dangerous commands
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
const token = tokens[i];
|
||||
if (token === '-exec' || token === '-execdir') {
|
||||
const execTokens = tokens.slice(i + 1);
|
||||
const semicolonIdx = execTokens.indexOf(';');
|
||||
const plusIdx = execTokens.indexOf('+');
|
||||
// If no terminator found, shell-quote may have parsed it as an operator
|
||||
// In that case, treat the rest of the tokens as the exec command
|
||||
const endIdx =
|
||||
semicolonIdx !== -1 && plusIdx !== -1
|
||||
? Math.min(semicolonIdx, plusIdx)
|
||||
: semicolonIdx !== -1
|
||||
? semicolonIdx
|
||||
: plusIdx !== -1
|
||||
? plusIdx
|
||||
: execTokens.length; // No terminator - use all remaining tokens
|
||||
|
||||
let execCommand = execTokens.slice(0, endIdx);
|
||||
// Strip wrappers (env, sudo, command)
|
||||
execCommand = stripWrappers(execCommand);
|
||||
if (execCommand.length > 0) {
|
||||
let head = getBasename(execCommand[0] ?? '');
|
||||
// Handle busybox wrapper
|
||||
if (head === 'busybox' && execCommand.length > 1) {
|
||||
execCommand = execCommand.slice(1);
|
||||
head = getBasename(execCommand[0] ?? '');
|
||||
}
|
||||
if (head === 'rm' && hasRecursiveForceFlags(execCommand)) {
|
||||
return 'find -exec rm -rf is dangerous. Use explicit file list instead.';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if find command has -delete action (not as argument to another option).
|
||||
* Handles cases like "find -name -delete" where -delete is a filename pattern.
|
||||
*/
|
||||
export function findHasDelete(tokens: readonly string[]): boolean {
|
||||
let i = 0;
|
||||
let insideExec = false;
|
||||
let execDepth = 0;
|
||||
|
||||
while (i < tokens.length) {
|
||||
const token = tokens[i];
|
||||
if (!token) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Track -exec/-execdir blocks
|
||||
if (token === '-exec' || token === '-execdir') {
|
||||
insideExec = true;
|
||||
execDepth++;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// End of -exec block
|
||||
if (insideExec && (token === ';' || token === '+')) {
|
||||
execDepth--;
|
||||
if (execDepth === 0) {
|
||||
insideExec = false;
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip -delete inside -exec blocks
|
||||
if (insideExec) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Options that take an argument - skip the next token
|
||||
if (
|
||||
token === '-name' ||
|
||||
token === '-iname' ||
|
||||
token === '-path' ||
|
||||
token === '-ipath' ||
|
||||
token === '-regex' ||
|
||||
token === '-iregex' ||
|
||||
token === '-type' ||
|
||||
token === '-user' ||
|
||||
token === '-group' ||
|
||||
token === '-perm' ||
|
||||
token === '-size' ||
|
||||
token === '-mtime' ||
|
||||
token === '-ctime' ||
|
||||
token === '-atime' ||
|
||||
token === '-newer' ||
|
||||
token === '-printf' ||
|
||||
token === '-fprint' ||
|
||||
token === '-fprintf'
|
||||
) {
|
||||
i += 2; // Skip option and its argument
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found -delete outside of -exec and not as an argument
|
||||
if (token === '-delete') {
|
||||
return true;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user