chainwall 0.1.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 +278 -0
- package/commands/security-scan.md +35 -0
- package/dist/auditor/access-mapper.d.ts +3 -0
- package/dist/auditor/access-mapper.d.ts.map +1 -0
- package/dist/auditor/access-mapper.js +15 -0
- package/dist/auditor/access-mapper.js.map +1 -0
- package/dist/auditor/cli-detector.d.ts +7 -0
- package/dist/auditor/cli-detector.d.ts.map +1 -0
- package/dist/auditor/cli-detector.js +63 -0
- package/dist/auditor/cli-detector.js.map +1 -0
- package/dist/auditor/cross-reference.d.ts +4 -0
- package/dist/auditor/cross-reference.d.ts.map +1 -0
- package/dist/auditor/cross-reference.js +16 -0
- package/dist/auditor/cross-reference.js.map +1 -0
- package/dist/auditor/env-auditor.d.ts +9 -0
- package/dist/auditor/env-auditor.d.ts.map +1 -0
- package/dist/auditor/env-auditor.js +83 -0
- package/dist/auditor/env-auditor.js.map +1 -0
- package/dist/auditor/mcp-analyzer.d.ts +11 -0
- package/dist/auditor/mcp-analyzer.d.ts.map +1 -0
- package/dist/auditor/mcp-analyzer.js +145 -0
- package/dist/auditor/mcp-analyzer.js.map +1 -0
- package/dist/auditor/mcp-detector.d.ts +17 -0
- package/dist/auditor/mcp-detector.d.ts.map +1 -0
- package/dist/auditor/mcp-detector.js +86 -0
- package/dist/auditor/mcp-detector.js.map +1 -0
- package/dist/auditor/remediation.d.ts +26 -0
- package/dist/auditor/remediation.d.ts.map +1 -0
- package/dist/auditor/remediation.js +222 -0
- package/dist/auditor/remediation.js.map +1 -0
- package/dist/auditor/tool-detector.d.ts +15 -0
- package/dist/auditor/tool-detector.d.ts.map +1 -0
- package/dist/auditor/tool-detector.js +241 -0
- package/dist/auditor/tool-detector.js.map +1 -0
- package/dist/auditor/types.d.ts +31 -0
- package/dist/auditor/types.d.ts.map +1 -0
- package/dist/auditor/types.js +2 -0
- package/dist/auditor/types.js.map +1 -0
- package/dist/auditor/vscode-extension-scanner.d.ts +8 -0
- package/dist/auditor/vscode-extension-scanner.d.ts.map +1 -0
- package/dist/auditor/vscode-extension-scanner.js +51 -0
- package/dist/auditor/vscode-extension-scanner.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +159 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/audit.d.ts +8 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +151 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +34 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/remediate-cli.d.ts +3 -0
- package/dist/commands/remediate-cli.d.ts.map +1 -0
- package/dist/commands/remediate-cli.js +96 -0
- package/dist/commands/remediate-cli.js.map +1 -0
- package/dist/commands/scan.d.ts +11 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +138 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/watch.d.ts +6 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +203 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +235 -0
- package/dist/config.js.map +1 -0
- package/dist/mcp-server/index.d.ts +3 -0
- package/dist/mcp-server/index.d.ts.map +1 -0
- package/dist/mcp-server/index.js +69 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/mcp-server/schemas.d.ts +13 -0
- package/dist/mcp-server/schemas.d.ts.map +1 -0
- package/dist/mcp-server/schemas.js +13 -0
- package/dist/mcp-server/schemas.js.map +1 -0
- package/dist/mcp-server/tools/audit-status.d.ts +3 -0
- package/dist/mcp-server/tools/audit-status.d.ts.map +1 -0
- package/dist/mcp-server/tools/audit-status.js +46 -0
- package/dist/mcp-server/tools/audit-status.js.map +1 -0
- package/dist/mcp-server/tools/check-command.d.ts +4 -0
- package/dist/mcp-server/tools/check-command.d.ts.map +1 -0
- package/dist/mcp-server/tools/check-command.js +30 -0
- package/dist/mcp-server/tools/check-command.js.map +1 -0
- package/dist/mcp-server/tools/scan-content.d.ts +4 -0
- package/dist/mcp-server/tools/scan-content.d.ts.map +1 -0
- package/dist/mcp-server/tools/scan-content.js +18 -0
- package/dist/mcp-server/tools/scan-content.js.map +1 -0
- package/dist/mcp-server/tools/scan-file.d.ts +4 -0
- package/dist/mcp-server/tools/scan-file.d.ts.map +1 -0
- package/dist/mcp-server/tools/scan-file.js +48 -0
- package/dist/mcp-server/tools/scan-file.js.map +1 -0
- package/dist/mcp-server/types.d.ts +15 -0
- package/dist/mcp-server/types.d.ts.map +1 -0
- package/dist/mcp-server/types.js +2 -0
- package/dist/mcp-server/types.js.map +1 -0
- package/dist/reporter/audit-report.d.ts +4 -0
- package/dist/reporter/audit-report.d.ts.map +1 -0
- package/dist/reporter/audit-report.js +186 -0
- package/dist/reporter/audit-report.js.map +1 -0
- package/dist/reporter/json-report.d.ts +3 -0
- package/dist/reporter/json-report.d.ts.map +1 -0
- package/dist/reporter/json-report.js +4 -0
- package/dist/reporter/json-report.js.map +1 -0
- package/dist/reporter/remediation-text.d.ts +3 -0
- package/dist/reporter/remediation-text.d.ts.map +1 -0
- package/dist/reporter/remediation-text.js +12 -0
- package/dist/reporter/remediation-text.js.map +1 -0
- package/dist/reporter/risk-scorer.d.ts +8 -0
- package/dist/reporter/risk-scorer.d.ts.map +1 -0
- package/dist/reporter/risk-scorer.js +40 -0
- package/dist/reporter/risk-scorer.js.map +1 -0
- package/dist/reporter/sarif-report.d.ts +3 -0
- package/dist/reporter/sarif-report.d.ts.map +1 -0
- package/dist/reporter/sarif-report.js +80 -0
- package/dist/reporter/sarif-report.js.map +1 -0
- package/dist/reporter/shared.d.ts +11 -0
- package/dist/reporter/shared.d.ts.map +1 -0
- package/dist/reporter/shared.js +85 -0
- package/dist/reporter/shared.js.map +1 -0
- package/dist/reporter/summary-generator.d.ts +16 -0
- package/dist/reporter/summary-generator.d.ts.map +1 -0
- package/dist/reporter/summary-generator.js +89 -0
- package/dist/reporter/summary-generator.js.map +1 -0
- package/dist/reporter/terminal-report.d.ts +4 -0
- package/dist/reporter/terminal-report.d.ts.map +1 -0
- package/dist/reporter/terminal-report.js +135 -0
- package/dist/reporter/terminal-report.js.map +1 -0
- package/dist/rules/crypto-rules.d.ts +3 -0
- package/dist/rules/crypto-rules.d.ts.map +1 -0
- package/dist/rules/crypto-rules.js +252 -0
- package/dist/rules/crypto-rules.js.map +1 -0
- package/dist/rules/default-rules.d.ts +9 -0
- package/dist/rules/default-rules.d.ts.map +1 -0
- package/dist/rules/default-rules.js +1319 -0
- package/dist/rules/default-rules.js.map +1 -0
- package/dist/rules/index.d.ts +7 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +7 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/injection-rules.d.ts +8 -0
- package/dist/rules/injection-rules.d.ts.map +1 -0
- package/dist/rules/injection-rules.js +108 -0
- package/dist/rules/injection-rules.js.map +1 -0
- package/dist/rules/types.d.ts +52 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +2 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/scanner/filesystem-scanner.d.ts +26 -0
- package/dist/scanner/filesystem-scanner.d.ts.map +1 -0
- package/dist/scanner/filesystem-scanner.js +369 -0
- package/dist/scanner/filesystem-scanner.js.map +1 -0
- package/dist/scanner/injection-scanner.d.ts +12 -0
- package/dist/scanner/injection-scanner.d.ts.map +1 -0
- package/dist/scanner/injection-scanner.js +136 -0
- package/dist/scanner/injection-scanner.js.map +1 -0
- package/dist/scanner/permission-checker.d.ts +4 -0
- package/dist/scanner/permission-checker.d.ts.map +1 -0
- package/dist/scanner/permission-checker.js +37 -0
- package/dist/scanner/permission-checker.js.map +1 -0
- package/dist/scanner/redact.d.ts +3 -0
- package/dist/scanner/redact.d.ts.map +1 -0
- package/dist/scanner/redact.js +17 -0
- package/dist/scanner/redact.js.map +1 -0
- package/dist/scanner/rule-engine.d.ts +9 -0
- package/dist/scanner/rule-engine.d.ts.map +1 -0
- package/dist/scanner/rule-engine.js +129 -0
- package/dist/scanner/rule-engine.js.map +1 -0
- package/dist/scanner/system-targets.d.ts +17 -0
- package/dist/scanner/system-targets.d.ts.map +1 -0
- package/dist/scanner/system-targets.js +81 -0
- package/dist/scanner/system-targets.js.map +1 -0
- package/dist/tui/App.d.ts +6 -0
- package/dist/tui/App.d.ts.map +1 -0
- package/dist/tui/App.js +224 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/components/BootSequence.d.ts +6 -0
- package/dist/tui/components/BootSequence.d.ts.map +1 -0
- package/dist/tui/components/BootSequence.js +40 -0
- package/dist/tui/components/BootSequence.js.map +1 -0
- package/dist/tui/components/BorderedSection.d.ts +12 -0
- package/dist/tui/components/BorderedSection.d.ts.map +1 -0
- package/dist/tui/components/BorderedSection.js +7 -0
- package/dist/tui/components/BorderedSection.js.map +1 -0
- package/dist/tui/components/ErrorBoundary.d.ts +18 -0
- package/dist/tui/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/tui/components/ErrorBoundary.js +36 -0
- package/dist/tui/components/ErrorBoundary.js.map +1 -0
- package/dist/tui/components/FirstUseHint.d.ts +7 -0
- package/dist/tui/components/FirstUseHint.d.ts.map +1 -0
- package/dist/tui/components/FirstUseHint.js +20 -0
- package/dist/tui/components/FirstUseHint.js.map +1 -0
- package/dist/tui/components/Footer.d.ts +10 -0
- package/dist/tui/components/Footer.d.ts.map +1 -0
- package/dist/tui/components/Footer.js +51 -0
- package/dist/tui/components/Footer.js.map +1 -0
- package/dist/tui/components/MetricCard.d.ts +11 -0
- package/dist/tui/components/MetricCard.d.ts.map +1 -0
- package/dist/tui/components/MetricCard.js +8 -0
- package/dist/tui/components/MetricCard.js.map +1 -0
- package/dist/tui/components/Panel.d.ts +15 -0
- package/dist/tui/components/Panel.d.ts.map +1 -0
- package/dist/tui/components/Panel.js +25 -0
- package/dist/tui/components/Panel.js.map +1 -0
- package/dist/tui/components/RemediationMenu.d.ts +10 -0
- package/dist/tui/components/RemediationMenu.d.ts.map +1 -0
- package/dist/tui/components/RemediationMenu.js +84 -0
- package/dist/tui/components/RemediationMenu.js.map +1 -0
- package/dist/tui/components/RiskGauge.d.ts +7 -0
- package/dist/tui/components/RiskGauge.d.ts.map +1 -0
- package/dist/tui/components/RiskGauge.js +55 -0
- package/dist/tui/components/RiskGauge.js.map +1 -0
- package/dist/tui/components/ScrollableList.d.ts +11 -0
- package/dist/tui/components/ScrollableList.d.ts.map +1 -0
- package/dist/tui/components/ScrollableList.js +14 -0
- package/dist/tui/components/ScrollableList.js.map +1 -0
- package/dist/tui/components/Section.d.ts +9 -0
- package/dist/tui/components/Section.d.ts.map +1 -0
- package/dist/tui/components/Section.js +7 -0
- package/dist/tui/components/Section.js.map +1 -0
- package/dist/tui/components/SectionHeader.d.ts +8 -0
- package/dist/tui/components/SectionHeader.d.ts.map +1 -0
- package/dist/tui/components/SectionHeader.js +15 -0
- package/dist/tui/components/SectionHeader.js.map +1 -0
- package/dist/tui/components/SeverityBadge.d.ts +5 -0
- package/dist/tui/components/SeverityBadge.d.ts.map +1 -0
- package/dist/tui/components/SeverityBadge.js +7 -0
- package/dist/tui/components/SeverityBadge.js.map +1 -0
- package/dist/tui/components/Sidebar.d.ts +2 -0
- package/dist/tui/components/Sidebar.d.ts.map +1 -0
- package/dist/tui/components/Sidebar.js +40 -0
- package/dist/tui/components/Sidebar.js.map +1 -0
- package/dist/tui/components/StatusIndicator.d.ts +8 -0
- package/dist/tui/components/StatusIndicator.d.ts.map +1 -0
- package/dist/tui/components/StatusIndicator.js +15 -0
- package/dist/tui/components/StatusIndicator.js.map +1 -0
- package/dist/tui/components/Table.d.ts +21 -0
- package/dist/tui/components/Table.d.ts.map +1 -0
- package/dist/tui/components/Table.js +38 -0
- package/dist/tui/components/Table.js.map +1 -0
- package/dist/tui/components/Transition.d.ts +8 -0
- package/dist/tui/components/Transition.d.ts.map +1 -0
- package/dist/tui/components/Transition.js +38 -0
- package/dist/tui/components/Transition.js.map +1 -0
- package/dist/tui/components/WelcomeScreen.d.ts +6 -0
- package/dist/tui/components/WelcomeScreen.d.ts.map +1 -0
- package/dist/tui/components/WelcomeScreen.js +14 -0
- package/dist/tui/components/WelcomeScreen.js.map +1 -0
- package/dist/tui/educational.d.ts +32 -0
- package/dist/tui/educational.d.ts.map +1 -0
- package/dist/tui/educational.js +117 -0
- package/dist/tui/educational.js.map +1 -0
- package/dist/tui/hooks/useAudit.d.ts +24 -0
- package/dist/tui/hooks/useAudit.d.ts.map +1 -0
- package/dist/tui/hooks/useAudit.js +263 -0
- package/dist/tui/hooks/useAudit.js.map +1 -0
- package/dist/tui/hooks/useConfig.d.ts +18 -0
- package/dist/tui/hooks/useConfig.d.ts.map +1 -0
- package/dist/tui/hooks/useConfig.js +85 -0
- package/dist/tui/hooks/useConfig.js.map +1 -0
- package/dist/tui/hooks/useHookStatus.d.ts +10 -0
- package/dist/tui/hooks/useHookStatus.d.ts.map +1 -0
- package/dist/tui/hooks/useHookStatus.js +59 -0
- package/dist/tui/hooks/useHookStatus.js.map +1 -0
- package/dist/tui/hooks/useLogs.d.ts +42 -0
- package/dist/tui/hooks/useLogs.d.ts.map +1 -0
- package/dist/tui/hooks/useLogs.js +105 -0
- package/dist/tui/hooks/useLogs.js.map +1 -0
- package/dist/tui/hooks/useScan.d.ts +39 -0
- package/dist/tui/hooks/useScan.d.ts.map +1 -0
- package/dist/tui/hooks/useScan.js +255 -0
- package/dist/tui/hooks/useScan.js.map +1 -0
- package/dist/tui/hooks/useTerminalSize.d.ts +10 -0
- package/dist/tui/hooks/useTerminalSize.d.ts.map +1 -0
- package/dist/tui/hooks/useTerminalSize.js +27 -0
- package/dist/tui/hooks/useTerminalSize.js.map +1 -0
- package/dist/tui/index.d.ts +2 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +8 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/screens/AuditPanel.d.ts +7 -0
- package/dist/tui/screens/AuditPanel.d.ts.map +1 -0
- package/dist/tui/screens/AuditPanel.js +467 -0
- package/dist/tui/screens/AuditPanel.js.map +1 -0
- package/dist/tui/screens/LogsPanel.d.ts +2 -0
- package/dist/tui/screens/LogsPanel.d.ts.map +1 -0
- package/dist/tui/screens/LogsPanel.js +127 -0
- package/dist/tui/screens/LogsPanel.js.map +1 -0
- package/dist/tui/screens/OverviewPanel.d.ts +2 -0
- package/dist/tui/screens/OverviewPanel.d.ts.map +1 -0
- package/dist/tui/screens/OverviewPanel.js +84 -0
- package/dist/tui/screens/OverviewPanel.js.map +1 -0
- package/dist/tui/screens/ScanPanel.d.ts +2 -0
- package/dist/tui/screens/ScanPanel.d.ts.map +1 -0
- package/dist/tui/screens/ScanPanel.js +188 -0
- package/dist/tui/screens/ScanPanel.js.map +1 -0
- package/dist/tui/screens/ScanResultsPanel.d.ts +2 -0
- package/dist/tui/screens/ScanResultsPanel.d.ts.map +1 -0
- package/dist/tui/screens/ScanResultsPanel.js +394 -0
- package/dist/tui/screens/ScanResultsPanel.js.map +1 -0
- package/dist/tui/screens/SettingsPanel.d.ts +2 -0
- package/dist/tui/screens/SettingsPanel.d.ts.map +1 -0
- package/dist/tui/screens/SettingsPanel.js +353 -0
- package/dist/tui/screens/SettingsPanel.js.map +1 -0
- package/dist/tui/state.d.ts +35 -0
- package/dist/tui/state.d.ts.map +1 -0
- package/dist/tui/state.js +13 -0
- package/dist/tui/state.js.map +1 -0
- package/dist/tui/theme.d.ts +58 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +80 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/hooks/audit-logger.sh +74 -0
- package/hooks/detection-lib.sh +301 -0
- package/hooks/git-pre-commit.sh +195 -0
- package/hooks/git-pre-push.sh +125 -0
- package/hooks/git-safety.sh +152 -0
- package/hooks/security-scanner.sh +527 -0
- package/install.sh +543 -0
- package/package.json +67 -0
- package/patterns/credentials.yaml +317 -0
- package/patterns/dangerous-commands.yaml +167 -0
- package/patterns/pii.yaml +95 -0
- package/patterns/prompt-injection.yaml +131 -0
- package/patterns/supply-chain.yaml +119 -0
- package/rules/AGENTS.md +60 -0
- package/rules/SECURITY-RULES.md +177 -0
- package/rules/claude.md +9 -0
- package/rules/clinerules +29 -0
- package/rules/continuerules +29 -0
- package/rules/copilot-instructions.md +9 -0
- package/rules/cursor-security.mdc +14 -0
- package/rules/gemini.md +9 -0
- package/rules/kiro-security.md +29 -0
- package/rules/roocode-security.md +29 -0
- package/rules/trae-security.md +29 -0
- package/rules/windsurfrules +9 -0
- package/skill/llm-antivirus/SKILL.md +73 -0
- package/skill/llm-antivirus/references/threat-patterns.yaml +82 -0
- package/skill/llm-antivirus/scripts/security-audit.sh +244 -0
- package/uninstall.sh +215 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Security Rules — Trae IDE
|
|
2
|
+
|
|
3
|
+
These rules are enforced by ChainWall and apply to all Trae IDE operations.
|
|
4
|
+
|
|
5
|
+
## NEVER
|
|
6
|
+
|
|
7
|
+
- Write credentials, API keys, tokens, or passwords in code or commands
|
|
8
|
+
- Access .env, credentials.json, secrets.json, SSH keys, .npmrc, or .pypirc
|
|
9
|
+
- Run rm -rf, mkfs, dd to devices, chmod 777, or redirect to block devices
|
|
10
|
+
- Pipe downloads to shell (curl|bash, wget|sh)
|
|
11
|
+
- Expose SSNs, credit card numbers, or other PII in outputs
|
|
12
|
+
- Write PEM private keys (RSA, DSA, EC, OpenSSH, PGP) to any file
|
|
13
|
+
- Force-push to main/master or hard-reset shared branches
|
|
14
|
+
- Install packages from arbitrary URLs or override registries
|
|
15
|
+
|
|
16
|
+
## ALWAYS
|
|
17
|
+
|
|
18
|
+
- Use environment variables for secrets
|
|
19
|
+
- Validate inputs at system boundaries
|
|
20
|
+
- Use parameterized queries — never concatenate user input into SQL or shell
|
|
21
|
+
- Pin dependency versions and preserve lock files
|
|
22
|
+
- Check file paths to prevent path traversal
|
|
23
|
+
- Use HTTPS for API calls and package downloads
|
|
24
|
+
|
|
25
|
+
## Configuration
|
|
26
|
+
|
|
27
|
+
Override: ~/.llm-av/config.json (global), .llm-av/config.json (project)
|
|
28
|
+
Bypass: LLMAV_SKIP=1 (logged)
|
|
29
|
+
Audit: .llm-av/audit.jsonl
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Windsurf Security Rules
|
|
2
|
+
|
|
3
|
+
This project uses ChainWall for security enforcement.
|
|
4
|
+
|
|
5
|
+
Read and follow ALL rules in AGENTS.md (in the project root)
|
|
6
|
+
before performing any file operations, shell commands, or code generation.
|
|
7
|
+
|
|
8
|
+
Do not write credentials, access sensitive files, run destructive commands,
|
|
9
|
+
or expose PII. See AGENTS.md for the complete rule set.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: llm-antivirus
|
|
3
|
+
description: Security auditing skill for AI coding agents — scans for credentials, dangerous commands, PII, and prompt injection
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
author: Laurenz
|
|
6
|
+
tags: [security, audit, credentials, pii, owasp]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# ChainWall Security Skill
|
|
10
|
+
|
|
11
|
+
You are a security auditing assistant. When invoked, perform a comprehensive
|
|
12
|
+
security scan of the project using the patterns and scripts provided.
|
|
13
|
+
|
|
14
|
+
## Quick Reference
|
|
15
|
+
|
|
16
|
+
**What this skill does:**
|
|
17
|
+
- Scans project files for leaked credentials, API keys, and tokens
|
|
18
|
+
- Detects dangerous shell commands in scripts and configs
|
|
19
|
+
- Identifies PII (SSN, credit cards, medical records)
|
|
20
|
+
- Checks for prompt injection patterns in AI-facing files
|
|
21
|
+
- Validates .gitignore for sensitive file exclusions
|
|
22
|
+
- Reports findings with severity levels and remediation guidance
|
|
23
|
+
|
|
24
|
+
## How to Use
|
|
25
|
+
|
|
26
|
+
Run the security audit script:
|
|
27
|
+
```bash
|
|
28
|
+
./skill/llm-antivirus/scripts/security-audit.sh
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or perform a targeted scan:
|
|
32
|
+
```bash
|
|
33
|
+
# Scan specific directory
|
|
34
|
+
./skill/llm-antivirus/scripts/security-audit.sh src/
|
|
35
|
+
|
|
36
|
+
# Scan specific file
|
|
37
|
+
./skill/llm-antivirus/scripts/security-audit.sh path/to/file.ts
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Detection Categories
|
|
41
|
+
|
|
42
|
+
| Category | Severity | Patterns |
|
|
43
|
+
|----------|----------|----------|
|
|
44
|
+
| Credentials | Critical/High | 55 patterns (AWS, GitHub, OpenAI, etc.) |
|
|
45
|
+
| Dangerous Commands | Critical/High | 26 patterns (rm -rf, curl\|bash, etc.) |
|
|
46
|
+
| PII | Critical/High | 15 patterns (SSN, credit card, medical) |
|
|
47
|
+
| Prompt Injection | Medium | 18 patterns (jailbreak, role confusion) |
|
|
48
|
+
| Supply Chain | High/Medium | 16 patterns (typosquatting, lock files) |
|
|
49
|
+
|
|
50
|
+
## When to Invoke This Skill
|
|
51
|
+
|
|
52
|
+
- Before committing code to a repository
|
|
53
|
+
- When reviewing pull requests for security issues
|
|
54
|
+
- After adding new dependencies or configuration files
|
|
55
|
+
- When onboarding a new project to verify security posture
|
|
56
|
+
- Periodically as part of security maintenance
|
|
57
|
+
|
|
58
|
+
## Pattern Reference
|
|
59
|
+
|
|
60
|
+
See `patterns/*.yaml` in the repository root for the complete pattern database
|
|
61
|
+
with regex expressions, severity levels, and descriptions.
|
|
62
|
+
|
|
63
|
+
## OWASP LLM Top 10 Coverage
|
|
64
|
+
|
|
65
|
+
| ID | Vulnerability | Covered |
|
|
66
|
+
|----|---------------|---------|
|
|
67
|
+
| LLM01 | Prompt Injection | Yes — Layer 6 |
|
|
68
|
+
| LLM02 | Insecure Output | Yes — Layers 2-3, 5 |
|
|
69
|
+
| LLM06 | Sensitive Info Disclosure | Yes — Layers 1-3, 5 |
|
|
70
|
+
| LLM07 | System Prompt Leakage | Yes — Layer 6 |
|
|
71
|
+
| LLM08 | Excessive Agency | Yes — Layer 4 |
|
|
72
|
+
| LLM09 | Overreliance | Partial — instruction files |
|
|
73
|
+
| LLM10 | Model Supply Chain | Yes — supply-chain patterns |
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# ChainWall — Threat Pattern Reference for Skill
|
|
2
|
+
#
|
|
3
|
+
# Consolidated pattern reference used by the security audit skill.
|
|
4
|
+
# This file provides a high-level summary; full patterns are in /patterns/*.yaml.
|
|
5
|
+
|
|
6
|
+
categories:
|
|
7
|
+
|
|
8
|
+
credentials:
|
|
9
|
+
count: 55
|
|
10
|
+
source: patterns/credentials.yaml
|
|
11
|
+
providers:
|
|
12
|
+
- AWS (Access Key, Secret, Session Token)
|
|
13
|
+
- GCP/Google (API Key, Service Account, OAuth Secret)
|
|
14
|
+
- Azure (Storage Key, AD Secret, Connection String)
|
|
15
|
+
- GitHub (PAT classic, fine-grained, OAuth, App, Refresh)
|
|
16
|
+
- GitLab (PAT, Pipeline, Runner)
|
|
17
|
+
- Slack (Bot/User Token, Webhook URL)
|
|
18
|
+
- Stripe (Secret Key, Restricted Key, Webhook Secret)
|
|
19
|
+
- OpenAI (API Key, Project Key)
|
|
20
|
+
- Anthropic (API Key)
|
|
21
|
+
- Twilio (API Key, Account SID)
|
|
22
|
+
- SendGrid (API Key)
|
|
23
|
+
- Supabase (Service Role, Anon Key)
|
|
24
|
+
- Firebase (Server Key)
|
|
25
|
+
- Databricks (Access Token)
|
|
26
|
+
- npm (Access Token)
|
|
27
|
+
- PyPI (API Token)
|
|
28
|
+
- Docker Hub (Access Token)
|
|
29
|
+
- Hashicorp Vault (Service Token, Batch Token)
|
|
30
|
+
- Datadog (API Key)
|
|
31
|
+
- Mailgun (API Key)
|
|
32
|
+
- Heroku (API Key)
|
|
33
|
+
- Shopify (Access Token, Custom App, Private App)
|
|
34
|
+
- Linear (API Key)
|
|
35
|
+
- Vercel (Access Token)
|
|
36
|
+
- JWT, Bearer, SSH/PGP keys
|
|
37
|
+
- Generic (API key assignments, passwords, private key vars)
|
|
38
|
+
|
|
39
|
+
dangerous_commands:
|
|
40
|
+
count: 24
|
|
41
|
+
source: patterns/dangerous-commands.yaml
|
|
42
|
+
categories:
|
|
43
|
+
- Destructive (rm -rf, shred)
|
|
44
|
+
- Remote Code Execution (curl|bash, eval, base64 decode)
|
|
45
|
+
- Permissions (chmod 777, SUID)
|
|
46
|
+
- Disk/Device (dd, mkfs, device write)
|
|
47
|
+
- Network Exfiltration (netcat, reverse shell, SSH tunnel)
|
|
48
|
+
- System Modification (crontab, hosts, sudoers, systemd)
|
|
49
|
+
- Container Escape (Docker socket, privileged)
|
|
50
|
+
- Environment (LD_PRELOAD, PATH manipulation)
|
|
51
|
+
- Anti-forensics (history deletion, log tampering)
|
|
52
|
+
|
|
53
|
+
pii:
|
|
54
|
+
count: 15
|
|
55
|
+
source: patterns/pii.yaml
|
|
56
|
+
types:
|
|
57
|
+
- Government IDs (SSN, EIN)
|
|
58
|
+
- Financial (credit card, bank account, routing, IBAN)
|
|
59
|
+
- Personal Contact (email/phone in PII context)
|
|
60
|
+
- Medical (MRN, DEA number)
|
|
61
|
+
- Identity Documents (passport, driver license, DOB)
|
|
62
|
+
|
|
63
|
+
prompt_injection:
|
|
64
|
+
count: 18
|
|
65
|
+
source: patterns/prompt-injection.yaml
|
|
66
|
+
vectors:
|
|
67
|
+
- Instruction Override (ignore previous, disregard, forget)
|
|
68
|
+
- Role Confusion (authority claims, admin override)
|
|
69
|
+
- System Prompt Extraction (reveal, show, reflect)
|
|
70
|
+
- Jailbreak (DAN, developer mode, no restrictions)
|
|
71
|
+
- Encoded Injection (base64, code blocks)
|
|
72
|
+
- Output Manipulation (suppress, format attacks)
|
|
73
|
+
|
|
74
|
+
supply_chain:
|
|
75
|
+
count: 17
|
|
76
|
+
source: patterns/supply-chain.yaml
|
|
77
|
+
vectors:
|
|
78
|
+
- Package Installation (pip from URL, registry override)
|
|
79
|
+
- Post-Install Scripts (curl in lifecycle, eval)
|
|
80
|
+
- Dependency Manipulation (git deps, private registry)
|
|
81
|
+
- Lock File (deletion, checkout)
|
|
82
|
+
- Container Image (untagged, unknown registry)
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# ChainWall — Security Audit Script
|
|
4
|
+
# Full project security scan using pattern databases
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# ./security-audit.sh # Scan entire project
|
|
8
|
+
# ./security-audit.sh src/ # Scan specific directory
|
|
9
|
+
# ./security-audit.sh file.ts # Scan specific file
|
|
10
|
+
#
|
|
11
|
+
# Exit codes:
|
|
12
|
+
# 0 = No findings
|
|
13
|
+
# 1 = Findings detected
|
|
14
|
+
#
|
|
15
|
+
# Dependencies: bash 3.2+, grep
|
|
16
|
+
#
|
|
17
|
+
|
|
18
|
+
set -o pipefail
|
|
19
|
+
|
|
20
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
21
|
+
# Configuration
|
|
22
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
23
|
+
|
|
24
|
+
# Resolve script and repo root
|
|
25
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
26
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
27
|
+
PATTERNS_DIR="${REPO_ROOT}/patterns"
|
|
28
|
+
|
|
29
|
+
# Colors
|
|
30
|
+
RED_BOLD=$'\e[1;31m'
|
|
31
|
+
RED=$'\e[31m'
|
|
32
|
+
YELLOW=$'\e[33m'
|
|
33
|
+
GREEN=$'\e[32m'
|
|
34
|
+
CYAN=$'\e[36m'
|
|
35
|
+
BOLD=$'\e[1m'
|
|
36
|
+
RESET=$'\e[0m'
|
|
37
|
+
|
|
38
|
+
# Scan target (default: current directory)
|
|
39
|
+
SCAN_TARGET="${1:-.}"
|
|
40
|
+
|
|
41
|
+
# Counters
|
|
42
|
+
CRITICAL_COUNT=0
|
|
43
|
+
HIGH_COUNT=0
|
|
44
|
+
MEDIUM_COUNT=0
|
|
45
|
+
LOW_COUNT=0
|
|
46
|
+
FILES_SCANNED=0
|
|
47
|
+
|
|
48
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
49
|
+
# Pattern Loading
|
|
50
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
51
|
+
|
|
52
|
+
# Extract regex patterns from a YAML file
|
|
53
|
+
# Returns one pattern per line
|
|
54
|
+
extract_patterns() {
|
|
55
|
+
local yaml_file="$1"
|
|
56
|
+
[[ ! -f "$yaml_file" ]] && return
|
|
57
|
+
grep '^\s*regex:' "$yaml_file" 2>/dev/null \
|
|
58
|
+
| sed 's/.*regex: *"//' \
|
|
59
|
+
| sed 's/"$//'
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
# Extract pattern names from a YAML file
|
|
63
|
+
extract_names() {
|
|
64
|
+
local yaml_file="$1"
|
|
65
|
+
[[ ! -f "$yaml_file" ]] && return
|
|
66
|
+
grep '^\s*- name:' "$yaml_file" 2>/dev/null \
|
|
67
|
+
| sed 's/.*- name: *//'
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
71
|
+
# Scanning Functions
|
|
72
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
73
|
+
|
|
74
|
+
scan_with_patterns() {
|
|
75
|
+
local yaml_file="$1"
|
|
76
|
+
local category="$2"
|
|
77
|
+
local severity="$3"
|
|
78
|
+
|
|
79
|
+
[[ ! -f "$yaml_file" ]] && return
|
|
80
|
+
|
|
81
|
+
# Read patterns and names into arrays
|
|
82
|
+
local patterns=()
|
|
83
|
+
local names=()
|
|
84
|
+
while IFS= read -r line; do
|
|
85
|
+
patterns+=("$line")
|
|
86
|
+
done < <(extract_patterns "$yaml_file")
|
|
87
|
+
|
|
88
|
+
while IFS= read -r line; do
|
|
89
|
+
names+=("$line")
|
|
90
|
+
done < <(extract_names "$yaml_file")
|
|
91
|
+
|
|
92
|
+
local idx=0
|
|
93
|
+
for pattern in "${patterns[@]}"; do
|
|
94
|
+
local name="${names[$idx]:-Pattern $idx}"
|
|
95
|
+
idx=$((idx + 1))
|
|
96
|
+
|
|
97
|
+
# Skip patterns with (?i) — grep -E doesn't support inline flags
|
|
98
|
+
# Use -i flag instead for case-insensitive patterns
|
|
99
|
+
local grep_flags="-rn"
|
|
100
|
+
local clean_pattern="$pattern"
|
|
101
|
+
if [[ "$pattern" == "(?i)"* ]]; then
|
|
102
|
+
grep_flags="-rni"
|
|
103
|
+
clean_pattern="${pattern#\(\?i\)}"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Run grep and collect results
|
|
107
|
+
local all_results
|
|
108
|
+
all_results=$(grep $grep_flags -E "$clean_pattern" "$SCAN_TARGET" \
|
|
109
|
+
--include='*.ts' --include='*.js' --include='*.py' --include='*.rb' \
|
|
110
|
+
--include='*.go' --include='*.rs' --include='*.java' --include='*.sh' \
|
|
111
|
+
--include='*.yaml' --include='*.yml' --include='*.json' --include='*.toml' \
|
|
112
|
+
--include='*.env' --include='*.env.*' --include='*.cfg' --include='*.ini' \
|
|
113
|
+
--include='*.conf' --include='*.config' --include='*.xml' --include='*.md' \
|
|
114
|
+
--exclude-dir='.git' --exclude-dir='node_modules' --exclude-dir='.llm-av' \
|
|
115
|
+
--exclude-dir='dist' --exclude-dir='build' --exclude-dir='__pycache__' \
|
|
116
|
+
--exclude-dir='tests' --exclude-dir='test' --exclude-dir='fixtures' \
|
|
117
|
+
--exclude='*.test.*' --exclude='*.spec.*' --exclude='security-audit.sh' \
|
|
118
|
+
2>/dev/null)
|
|
119
|
+
local results
|
|
120
|
+
results=$(echo "$all_results" | head -20)
|
|
121
|
+
|
|
122
|
+
if [[ -n "$results" ]]; then
|
|
123
|
+
local match_count
|
|
124
|
+
match_count=$(echo "$all_results" | wc -l | tr -d ' ')
|
|
125
|
+
|
|
126
|
+
# Set color based on severity
|
|
127
|
+
local color="$YELLOW"
|
|
128
|
+
case "$severity" in
|
|
129
|
+
critical) color="$RED_BOLD"; CRITICAL_COUNT=$((CRITICAL_COUNT + match_count)) ;;
|
|
130
|
+
high) color="$RED"; HIGH_COUNT=$((HIGH_COUNT + match_count)) ;;
|
|
131
|
+
medium) color="$YELLOW"; MEDIUM_COUNT=$((MEDIUM_COUNT + match_count)) ;;
|
|
132
|
+
low) color="$CYAN"; LOW_COUNT=$((LOW_COUNT + match_count)) ;;
|
|
133
|
+
esac
|
|
134
|
+
|
|
135
|
+
local severity_upper
|
|
136
|
+
severity_upper=$(echo "$severity" | tr '[:lower:]' '[:upper:]')
|
|
137
|
+
echo -e "\n${color}[${severity_upper}] ${name}${RESET}"
|
|
138
|
+
echo -e "${color}Pattern: ${clean_pattern}${RESET}"
|
|
139
|
+
echo "$results" | while IFS= read -r line; do
|
|
140
|
+
echo -e " ${line}"
|
|
141
|
+
done
|
|
142
|
+
if [[ "$match_count" -gt 20 ]]; then
|
|
143
|
+
echo -e " ... and $((match_count - 20)) more matches"
|
|
144
|
+
fi
|
|
145
|
+
fi
|
|
146
|
+
done
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
150
|
+
# .gitignore Check
|
|
151
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
152
|
+
|
|
153
|
+
check_gitignore() {
|
|
154
|
+
echo -e "\n${BOLD}=== .gitignore Check ===${RESET}"
|
|
155
|
+
|
|
156
|
+
if [[ ! -f ".gitignore" ]]; then
|
|
157
|
+
echo -e "${RED_BOLD}[CRITICAL] No .gitignore found${RESET}"
|
|
158
|
+
echo -e " Create a .gitignore to prevent committing sensitive files"
|
|
159
|
+
CRITICAL_COUNT=$((CRITICAL_COUNT + 1))
|
|
160
|
+
return
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
local missing=()
|
|
164
|
+
for pattern in ".env" "*.pem" "id_rsa" ".npmrc" ".pypirc"; do
|
|
165
|
+
if ! grep -q "$pattern" .gitignore 2>/dev/null; then
|
|
166
|
+
missing+=("$pattern")
|
|
167
|
+
fi
|
|
168
|
+
done
|
|
169
|
+
|
|
170
|
+
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
171
|
+
echo -e "${YELLOW}[MEDIUM] .gitignore missing sensitive patterns:${RESET}"
|
|
172
|
+
for m in "${missing[@]}"; do
|
|
173
|
+
echo -e " - $m"
|
|
174
|
+
MEDIUM_COUNT=$((MEDIUM_COUNT + 1))
|
|
175
|
+
done
|
|
176
|
+
else
|
|
177
|
+
echo -e "${GREEN} .gitignore includes standard sensitive patterns${RESET}"
|
|
178
|
+
fi
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
182
|
+
# Main
|
|
183
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
184
|
+
|
|
185
|
+
echo -e "${BOLD}╔══════════════════════════════════════════════╗${RESET}"
|
|
186
|
+
echo -e "${BOLD}║ ChainWall — Security Audit v2.0 ║${RESET}"
|
|
187
|
+
echo -e "${BOLD}╚══════════════════════════════════════════════╝${RESET}"
|
|
188
|
+
echo -e "Scanning: ${CYAN}${SCAN_TARGET}${RESET}"
|
|
189
|
+
echo -e "Patterns: ${CYAN}${PATTERNS_DIR}${RESET}"
|
|
190
|
+
echo ""
|
|
191
|
+
|
|
192
|
+
# Count files to scan
|
|
193
|
+
if [[ -d "$SCAN_TARGET" ]]; then
|
|
194
|
+
FILES_SCANNED=$(find "$SCAN_TARGET" -type f \
|
|
195
|
+
\( -name '*.ts' -o -name '*.js' -o -name '*.py' -o -name '*.sh' \
|
|
196
|
+
-o -name '*.yaml' -o -name '*.yml' -o -name '*.json' -o -name '*.env' \
|
|
197
|
+
-o -name '*.go' -o -name '*.rs' -o -name '*.java' \) \
|
|
198
|
+
-not -path '*/.git/*' -not -path '*/node_modules/*' \
|
|
199
|
+
-not -path '*/dist/*' -not -path '*/.llm-av/*' \
|
|
200
|
+
2>/dev/null | wc -l | tr -d ' ')
|
|
201
|
+
elif [[ -f "$SCAN_TARGET" ]]; then
|
|
202
|
+
FILES_SCANNED=1
|
|
203
|
+
fi
|
|
204
|
+
echo -e "Files: ${CYAN}${FILES_SCANNED}${RESET}"
|
|
205
|
+
|
|
206
|
+
# Run scans
|
|
207
|
+
echo -e "\n${BOLD}=== Credential Scan ===${RESET}"
|
|
208
|
+
scan_with_patterns "$PATTERNS_DIR/credentials.yaml" "credentials" "critical"
|
|
209
|
+
|
|
210
|
+
echo -e "\n${BOLD}=== Dangerous Command Scan ===${RESET}"
|
|
211
|
+
scan_with_patterns "$PATTERNS_DIR/dangerous-commands.yaml" "commands" "high"
|
|
212
|
+
|
|
213
|
+
echo -e "\n${BOLD}=== PII Scan ===${RESET}"
|
|
214
|
+
scan_with_patterns "$PATTERNS_DIR/pii.yaml" "pii" "high"
|
|
215
|
+
|
|
216
|
+
echo -e "\n${BOLD}=== Prompt Injection Scan ===${RESET}"
|
|
217
|
+
scan_with_patterns "$PATTERNS_DIR/prompt-injection.yaml" "injection" "medium"
|
|
218
|
+
|
|
219
|
+
echo -e "\n${BOLD}=== Supply Chain Scan ===${RESET}"
|
|
220
|
+
scan_with_patterns "$PATTERNS_DIR/supply-chain.yaml" "supply_chain" "medium"
|
|
221
|
+
|
|
222
|
+
# .gitignore check
|
|
223
|
+
check_gitignore
|
|
224
|
+
|
|
225
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
226
|
+
# Summary
|
|
227
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
228
|
+
|
|
229
|
+
TOTAL=$((CRITICAL_COUNT + HIGH_COUNT + MEDIUM_COUNT + LOW_COUNT))
|
|
230
|
+
|
|
231
|
+
echo -e "\n${BOLD}=== Summary ===${RESET}"
|
|
232
|
+
echo -e " Critical: ${RED_BOLD}${CRITICAL_COUNT}${RESET}"
|
|
233
|
+
echo -e " High: ${RED}${HIGH_COUNT}${RESET}"
|
|
234
|
+
echo -e " Medium: ${YELLOW}${MEDIUM_COUNT}${RESET}"
|
|
235
|
+
echo -e " Low: ${CYAN}${LOW_COUNT}${RESET}"
|
|
236
|
+
echo -e " ${BOLD}Total: ${TOTAL}${RESET}"
|
|
237
|
+
|
|
238
|
+
if [[ "$TOTAL" -eq 0 ]]; then
|
|
239
|
+
echo -e "\n${GREEN}No security findings detected.${RESET}"
|
|
240
|
+
exit 0
|
|
241
|
+
else
|
|
242
|
+
echo -e "\n${YELLOW}Review findings above and remediate before committing.${RESET}"
|
|
243
|
+
exit 1
|
|
244
|
+
fi
|
package/uninstall.sh
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# ChainWall — Uninstaller
|
|
4
|
+
#
|
|
5
|
+
# Removes ChainWall components from a project.
|
|
6
|
+
# Non-destructive: only removes what was installed, preserves user files.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# ./uninstall.sh # Uninstall from current directory
|
|
10
|
+
# ./uninstall.sh /path/to/project # Uninstall from specific project
|
|
11
|
+
#
|
|
12
|
+
# Requirements: bash 3.2+, jq
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
18
|
+
# Configuration
|
|
19
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
20
|
+
|
|
21
|
+
PROJECT_DIR="${1:-$(pwd)}"
|
|
22
|
+
|
|
23
|
+
# Colors
|
|
24
|
+
RED=$'\e[31m'
|
|
25
|
+
GREEN=$'\e[32m'
|
|
26
|
+
YELLOW=$'\e[33m'
|
|
27
|
+
CYAN=$'\e[36m'
|
|
28
|
+
BOLD=$'\e[1m'
|
|
29
|
+
RESET=$'\e[0m'
|
|
30
|
+
|
|
31
|
+
REMOVED=()
|
|
32
|
+
SKIPPED=()
|
|
33
|
+
|
|
34
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
35
|
+
# Helpers
|
|
36
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
37
|
+
|
|
38
|
+
info() { echo -e "${CYAN}[info]${RESET} $1"; }
|
|
39
|
+
ok() { echo -e "${GREEN}[removed]${RESET} $1"; REMOVED+=("$1"); }
|
|
40
|
+
skip() { echo -e "${YELLOW}[skip]${RESET} $1"; SKIPPED+=("$1"); }
|
|
41
|
+
|
|
42
|
+
remove_file() {
|
|
43
|
+
local path="$1"
|
|
44
|
+
local label="$2"
|
|
45
|
+
|
|
46
|
+
if [[ -f "$path" ]]; then
|
|
47
|
+
rm "$path"
|
|
48
|
+
ok "$label"
|
|
49
|
+
else
|
|
50
|
+
skip "$label (not found)"
|
|
51
|
+
fi
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
remove_dir() {
|
|
55
|
+
local path="$1"
|
|
56
|
+
local label="$2"
|
|
57
|
+
|
|
58
|
+
if [[ -d "$path" ]]; then
|
|
59
|
+
rm -rf "$path"
|
|
60
|
+
ok "$label"
|
|
61
|
+
else
|
|
62
|
+
skip "$label (not found)"
|
|
63
|
+
fi
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
67
|
+
# Uninstallation
|
|
68
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
69
|
+
|
|
70
|
+
echo -e "${BOLD}╔══════════════════════════════════════════════╗${RESET}"
|
|
71
|
+
echo -e "${BOLD}║ ChainWall — Uninstaller ║${RESET}"
|
|
72
|
+
echo -e "${BOLD}╚══════════════════════════════════════════════╝${RESET}"
|
|
73
|
+
echo ""
|
|
74
|
+
info "Project: ${PROJECT_DIR}"
|
|
75
|
+
echo ""
|
|
76
|
+
|
|
77
|
+
# ─── Remove Claude Code hooks from settings.local.json ─────────────────
|
|
78
|
+
SETTINGS_FILE="${PROJECT_DIR}/.claude/settings.local.json"
|
|
79
|
+
if [[ -f "$SETTINGS_FILE" ]] && command -v jq &> /dev/null; then
|
|
80
|
+
if jq -e '.hooks' "$SETTINGS_FILE" &>/dev/null; then
|
|
81
|
+
# Remove entries containing security-scanner.sh, git-safety.sh, or audit-logger.sh
|
|
82
|
+
UPDATED=$(jq '
|
|
83
|
+
.hooks.PreToolUse = [.hooks.PreToolUse[]? | select(.hooks | all(.command | contains("security-scanner.sh") | not) and all(.command | contains("git-safety.sh") | not))] |
|
|
84
|
+
.hooks.PostToolUse = [.hooks.PostToolUse[]? | select(.hooks | all(.command | contains("audit-logger.sh") | not))] |
|
|
85
|
+
if (.hooks.PreToolUse | length) == 0 and (.hooks.PostToolUse | length) == 0 then del(.hooks) else . end
|
|
86
|
+
' "$SETTINGS_FILE")
|
|
87
|
+
echo "$UPDATED" | jq '.' > "${SETTINGS_FILE}.tmp.$$"
|
|
88
|
+
mv "${SETTINGS_FILE}.tmp.$$" "$SETTINGS_FILE"
|
|
89
|
+
ok "Claude Code hooks (settings.local.json)"
|
|
90
|
+
else
|
|
91
|
+
skip "Claude Code hooks (no hooks in settings)"
|
|
92
|
+
fi
|
|
93
|
+
else
|
|
94
|
+
skip "Claude Code hooks (settings.local.json not found)"
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# ─── Remove installed files ────────────────────────────────────────────
|
|
98
|
+
MANIFEST_FILE="${PROJECT_DIR}/.llm-av/manifest.txt"
|
|
99
|
+
if [[ -f "$MANIFEST_FILE" ]]; then
|
|
100
|
+
info "Using install manifest for safe removal"
|
|
101
|
+
while IFS= read -r entry; do
|
|
102
|
+
[[ -z "$entry" ]] && continue
|
|
103
|
+
if [[ -d "$entry" ]]; then
|
|
104
|
+
remove_dir "$entry" "$(basename "$entry") (from manifest)"
|
|
105
|
+
elif [[ -f "$entry" ]]; then
|
|
106
|
+
remove_file "$entry" "$(basename "$entry") (from manifest)"
|
|
107
|
+
else
|
|
108
|
+
skip "$(basename "$entry") (not found)"
|
|
109
|
+
fi
|
|
110
|
+
done < "$MANIFEST_FILE"
|
|
111
|
+
else
|
|
112
|
+
info "No install manifest found — using default file list"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Always attempt these removals (fallback for pre-manifest installs)
|
|
116
|
+
remove_file "${PROJECT_DIR}/AGENTS.md" "AGENTS.md"
|
|
117
|
+
remove_dir "${PROJECT_DIR}/.claude/skill/llm-antivirus" "Claude Code skill"
|
|
118
|
+
remove_file "${PROJECT_DIR}/.claude/commands/security-scan.md" "Claude Code /security-scan command"
|
|
119
|
+
remove_file "${PROJECT_DIR}/.cursor/rules/security.mdc" "Cursor security rules"
|
|
120
|
+
remove_file "${PROJECT_DIR}/.github/copilot-instructions.md" "Copilot instructions"
|
|
121
|
+
|
|
122
|
+
# Windsurf: only remove if we appended (check for our marker)
|
|
123
|
+
if [[ -f "${PROJECT_DIR}/.windsurfrules" ]]; then
|
|
124
|
+
if grep -q "ChainWall" "${PROJECT_DIR}/.windsurfrules" 2>/dev/null; then
|
|
125
|
+
# Try to remove only our appended section
|
|
126
|
+
# If the whole file is ours, remove it
|
|
127
|
+
FIRST_LINE=$(head -1 "${PROJECT_DIR}/.windsurfrules" 2>/dev/null)
|
|
128
|
+
if [[ "$FIRST_LINE" == *"Windsurf Security Rules"* ]]; then
|
|
129
|
+
rm "${PROJECT_DIR}/.windsurfrules"
|
|
130
|
+
ok "Windsurf security rules (.windsurfrules)"
|
|
131
|
+
else
|
|
132
|
+
info "Windsurf: .windsurfrules contains mixed content — manual cleanup needed"
|
|
133
|
+
SKIPPED+=("Windsurf rules (manual cleanup)")
|
|
134
|
+
fi
|
|
135
|
+
fi
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
remove_file "${PROJECT_DIR}/GEMINI.md" "Gemini security rules"
|
|
139
|
+
remove_file "${PROJECT_DIR}/.clinerules" "Cline security rules"
|
|
140
|
+
remove_dir "${PROJECT_DIR}/.roo/rules" "RooCode security rules"
|
|
141
|
+
remove_file "${PROJECT_DIR}/.continuerules" "Continue.dev security rules"
|
|
142
|
+
remove_dir "${PROJECT_DIR}/.trae/rules" "Trae IDE security rules"
|
|
143
|
+
remove_dir "${PROJECT_DIR}/.kiro/rules" "Kiro security rules"
|
|
144
|
+
remove_file "${PROJECT_DIR}/.cursorrules" "Cursor fallback rules"
|
|
145
|
+
remove_file "${PROJECT_DIR}/.gemini/styleguide.md" "Gemini styleguide"
|
|
146
|
+
|
|
147
|
+
# ─── Remove git hooks ────────────────────────────────────────────────
|
|
148
|
+
if [[ -d "${PROJECT_DIR}/.git/hooks" ]]; then
|
|
149
|
+
for hook_name in pre-commit pre-push; do
|
|
150
|
+
hook_file="${PROJECT_DIR}/.git/hooks/${hook_name}"
|
|
151
|
+
if [[ -f "$hook_file" ]] && grep -q "ChainWall" "$hook_file" 2>/dev/null; then
|
|
152
|
+
if [[ -f "${hook_file}.existing" ]]; then
|
|
153
|
+
mv "${hook_file}.existing" "$hook_file"
|
|
154
|
+
ok "Git ${hook_name} hook (restored original)"
|
|
155
|
+
else
|
|
156
|
+
rm "$hook_file"
|
|
157
|
+
ok "Git ${hook_name} hook"
|
|
158
|
+
fi
|
|
159
|
+
fi
|
|
160
|
+
done
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
# ─── Remove MCP server config ────────────────────────────────────────
|
|
164
|
+
if command -v jq &> /dev/null; then
|
|
165
|
+
CLAUDE_DESKTOP_CONFIG="${HOME}/Library/Application Support/Claude/claude_desktop_config.json"
|
|
166
|
+
if [[ -f "$CLAUDE_DESKTOP_CONFIG" ]] && jq -e '.mcpServers."llm-antivirus"' "$CLAUDE_DESKTOP_CONFIG" &>/dev/null; then
|
|
167
|
+
UPDATED=$(jq 'del(.mcpServers."llm-antivirus")' "$CLAUDE_DESKTOP_CONFIG")
|
|
168
|
+
echo "$UPDATED" | jq '.' > "${CLAUDE_DESKTOP_CONFIG}.tmp.$$"
|
|
169
|
+
mv "${CLAUDE_DESKTOP_CONFIG}.tmp.$$" "$CLAUDE_DESKTOP_CONFIG"
|
|
170
|
+
ok "MCP server config (Claude Desktop)"
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
CURSOR_MCP_CONFIG="${HOME}/.cursor/mcp.json"
|
|
174
|
+
if [[ -f "$CURSOR_MCP_CONFIG" ]] && jq -e '.mcpServers."llm-antivirus"' "$CURSOR_MCP_CONFIG" &>/dev/null; then
|
|
175
|
+
UPDATED=$(jq 'del(.mcpServers."llm-antivirus")' "$CURSOR_MCP_CONFIG")
|
|
176
|
+
echo "$UPDATED" | jq '.' > "${CURSOR_MCP_CONFIG}.tmp.$$"
|
|
177
|
+
mv "${CURSOR_MCP_CONFIG}.tmp.$$" "$CURSOR_MCP_CONFIG"
|
|
178
|
+
ok "MCP server config (Cursor)"
|
|
179
|
+
fi
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
# ─── Remove .llm-av directory ──────────────────────────────────────────
|
|
183
|
+
if [[ -d "${PROJECT_DIR}/.llm-av" ]]; then
|
|
184
|
+
echo ""
|
|
185
|
+
echo -e "${YELLOW}Found .llm-av/ directory with audit logs and config.${RESET}"
|
|
186
|
+
echo -e "${YELLOW}Remove it? This will delete audit history. [y/N]${RESET}"
|
|
187
|
+
read -r REPLY
|
|
188
|
+
if [[ "$REPLY" =~ ^[Yy]$ ]]; then
|
|
189
|
+
rm -rf "${PROJECT_DIR}/.llm-av"
|
|
190
|
+
ok ".llm-av/ directory (audit logs and config)"
|
|
191
|
+
else
|
|
192
|
+
skip ".llm-av/ directory (preserved by user)"
|
|
193
|
+
fi
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
197
|
+
# Summary
|
|
198
|
+
# ═══════════════════════════════════════════════════════════════════════
|
|
199
|
+
|
|
200
|
+
echo ""
|
|
201
|
+
echo -e "${BOLD}=== Uninstall Summary ===${RESET}"
|
|
202
|
+
echo -e "${GREEN}Removed: ${#REMOVED[@]}${RESET}"
|
|
203
|
+
for item in "${REMOVED[@]}"; do
|
|
204
|
+
echo -e " ${RED}-${RESET} $item"
|
|
205
|
+
done
|
|
206
|
+
|
|
207
|
+
if [[ ${#SKIPPED[@]} -gt 0 ]]; then
|
|
208
|
+
echo -e "${YELLOW}Skipped: ${#SKIPPED[@]}${RESET}"
|
|
209
|
+
for item in "${SKIPPED[@]}"; do
|
|
210
|
+
echo -e " ${YELLOW}~${RESET} $item"
|
|
211
|
+
done
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
echo ""
|
|
215
|
+
echo -e "${GREEN}${BOLD}ChainWall uninstalled.${RESET}"
|