fullcourtdefense-cli 1.0.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.md +613 -0
- package/dist/api.d.ts +102 -0
- package/dist/api.js +62 -0
- package/dist/attack-corpus/context_escape/context-escape-newline.yaml +23 -0
- package/dist/attack-corpus/context_escape/context-escape-unicode.yaml +14 -0
- package/dist/attack-corpus/context_escape/delimiter-json.yaml +14 -0
- package/dist/attack-corpus/context_escape/delimiter-markdown.yaml +22 -0
- package/dist/attack-corpus/context_escape/delimiter-xml.yaml +19 -0
- package/dist/attack-corpus/context_escape/html-injection.yaml +14 -0
- package/dist/attack-corpus/context_escape/javascript-injection.yaml +13 -0
- package/dist/attack-corpus/data_extraction/adv26-adversarial-function-hallucination.yaml +20 -0
- package/dist/attack-corpus/data_extraction/adv26-cot-hijack-debug-trace.yaml +20 -0
- package/dist/attack-corpus/data_extraction/adv26-cot-hijack-verification.yaml +18 -0
- package/dist/attack-corpus/data_extraction/adv26-crossmodal-diff.yaml +22 -0
- package/dist/attack-corpus/data_extraction/adv26-crossmodal-graphql.yaml +34 -0
- package/dist/attack-corpus/data_extraction/adv26-crossmodal-regex.yaml +19 -0
- package/dist/attack-corpus/data_extraction/adv26-crossmodal-sql-prose.yaml +18 -0
- package/dist/attack-corpus/data_extraction/adv26-meta-confidence-calibration.yaml +21 -0
- package/dist/attack-corpus/data_extraction/adv26-meta-instruction-count.yaml +18 -0
- package/dist/attack-corpus/data_extraction/adv26-meta-output-format.yaml +16 -0
- package/dist/attack-corpus/data_extraction/adv26-meta-summarize-yourself.yaml +19 -0
- package/dist/attack-corpus/data_extraction/adv26-semantic-decomp-definition.yaml +15 -0
- package/dist/attack-corpus/data_extraction/adv26-semantic-decomp-fill-blank.yaml +19 -0
- package/dist/attack-corpus/data_extraction/adv26-semantic-decomp-negation.yaml +14 -0
- package/dist/attack-corpus/data_extraction/cloud-provider-discovery.yaml +11 -0
- package/dist/attack-corpus/data_extraction/config-file-request.yaml +11 -0
- package/dist/attack-corpus/data_extraction/cve-2025-echoleak.yaml +17 -0
- package/dist/attack-corpus/data_extraction/data-api-key.yaml +11 -0
- package/dist/attack-corpus/data_extraction/data-architecture.yaml +11 -0
- package/dist/attack-corpus/data_extraction/data-conversation-history.yaml +10 -0
- package/dist/attack-corpus/data_extraction/data-credit-card.yaml +15 -0
- package/dist/attack-corpus/data_extraction/data-customer-list.yaml +11 -0
- package/dist/attack-corpus/data_extraction/data-database.yaml +11 -0
- package/dist/attack-corpus/data_extraction/data-employees.yaml +11 -0
- package/dist/attack-corpus/data_extraction/data-export.yaml +11 -0
- package/dist/attack-corpus/data_extraction/data-inference-v1.yaml +10 -0
- package/dist/attack-corpus/data_extraction/data-inference-v2.yaml +10 -0
- package/dist/attack-corpus/data_extraction/data-logs.yaml +10 -0
- package/dist/attack-corpus/data_extraction/data-model-info.yaml +10 -0
- package/dist/attack-corpus/data_extraction/data-password.yaml +11 -0
- package/dist/attack-corpus/data_extraction/data-ssn.yaml +11 -0
- package/dist/attack-corpus/data_extraction/data-training.yaml +10 -0
- package/dist/attack-corpus/data_extraction/dependency-enum.yaml +11 -0
- package/dist/attack-corpus/data_extraction/dialogflow-fulfillment-leak.yaml +11 -0
- package/dist/attack-corpus/data_extraction/dialogflow-intent-leak.yaml +11 -0
- package/dist/attack-corpus/data_extraction/error-induced-leak.yaml +17 -0
- package/dist/attack-corpus/data_extraction/error-message-leak.yaml +12 -0
- package/dist/attack-corpus/data_extraction/infra-fingerprint.yaml +16 -0
- package/dist/attack-corpus/data_extraction/make-scenario-leak.yaml +11 -0
- package/dist/attack-corpus/data_extraction/n8n-execution-data.yaml +11 -0
- package/dist/attack-corpus/data_extraction/n8n-node-enumeration.yaml +11 -0
- package/dist/attack-corpus/data_extraction/n8n-workflow-disclosure.yaml +15 -0
- package/dist/attack-corpus/data_extraction/prompt-extraction-v1.yaml +10 -0
- package/dist/attack-corpus/data_extraction/prompt-extraction-v2.yaml +11 -0
- package/dist/attack-corpus/data_extraction/prompt-extraction-v3.yaml +10 -0
- package/dist/attack-corpus/data_extraction/prompt-leak-completion.yaml +10 -0
- package/dist/attack-corpus/data_extraction/prompt-leak-indirect.yaml +10 -0
- package/dist/attack-corpus/data_extraction/rasa-domain-leak.yaml +11 -0
- package/dist/attack-corpus/data_extraction/system-prompt-section.yaml +14 -0
- package/dist/attack-corpus/data_extraction/tech-architecture.yaml +16 -0
- package/dist/attack-corpus/data_extraction/tool-api-key-exfil.yaml +15 -0
- package/dist/attack-corpus/data_extraction/tool-email-exfil.yaml +14 -0
- package/dist/attack-corpus/data_extraction/tool-env-extraction.yaml +14 -0
- package/dist/attack-corpus/data_extraction/tool-file-read.yaml +16 -0
- package/dist/attack-corpus/data_extraction/tool-nosql-injection.yaml +11 -0
- package/dist/attack-corpus/data_extraction/tool-payment-manipulation.yaml +11 -0
- package/dist/attack-corpus/data_extraction/tool-price-manipulation.yaml +11 -0
- package/dist/attack-corpus/data_extraction/tool-session-hijack.yaml +11 -0
- package/dist/attack-corpus/data_extraction/tool-sql-injection.yaml +13 -0
- package/dist/attack-corpus/data_extraction/tool-webhook-hijack.yaml +13 -0
- package/dist/attack-corpus/data_extraction/version-fingerprint.yaml +16 -0
- package/dist/attack-corpus/data_extraction/webhook-secret-extraction.yaml +11 -0
- package/dist/attack-corpus/data_extraction/webhook-url-enum.yaml +11 -0
- package/dist/attack-corpus/data_extraction/workflow-instance-id.yaml +11 -0
- package/dist/attack-corpus/data_extraction/workflow-state-leak.yaml +16 -0
- package/dist/attack-corpus/data_extraction/zapier-zap-leak.yaml +11 -0
- package/dist/attack-corpus/encoding_attack/adv26-adversarial-token-confusion.yaml +13 -0
- package/dist/attack-corpus/encoding_attack/base64-decode-request.yaml +14 -0
- package/dist/attack-corpus/encoding_attack/base64-injection-v1.yaml +14 -0
- package/dist/attack-corpus/encoding_attack/flip-attack-v1.yaml +14 -0
- package/dist/attack-corpus/encoding_attack/flip-attack-v2.yaml +14 -0
- package/dist/attack-corpus/encoding_attack/token-smuggling.yaml +10 -0
- package/dist/attack-corpus/encoding_attack/unicode-homoglyph.yaml +15 -0
- package/dist/attack-corpus/encoding_attack/unicode-invisible.yaml +15 -0
- package/dist/attack-corpus/encoding_attack/unicode-rtl.yaml +11 -0
- package/dist/attack-corpus/encoding_bypass/adv26-compound-encoding-chain.yaml +19 -0
- package/dist/attack-corpus/encoding_bypass/adv26-smuggle-acrostic.yaml +26 -0
- package/dist/attack-corpus/encoding_bypass/adv26-smuggle-ascii-art.yaml +25 -0
- package/dist/attack-corpus/encoding_bypass/adv26-smuggle-emoji-cipher.yaml +22 -0
- package/dist/attack-corpus/encoding_bypass/adv26-smuggle-first-word.yaml +15 -0
- package/dist/attack-corpus/encoding_bypass/adv26-smuggle-pig-latin.yaml +15 -0
- package/dist/attack-corpus/encoding_bypass/encoding-base64-v1.yaml +11 -0
- package/dist/attack-corpus/encoding_bypass/encoding-base64-v2.yaml +15 -0
- package/dist/attack-corpus/encoding_bypass/encoding-hex-v1.yaml +11 -0
- package/dist/attack-corpus/encoding_bypass/encoding-leetspeak-v1.yaml +10 -0
- package/dist/attack-corpus/encoding_bypass/encoding-morse-v1.yaml +11 -0
- package/dist/attack-corpus/encoding_bypass/encoding-reverse-v1.yaml +11 -0
- package/dist/attack-corpus/encoding_bypass/encoding-rot13-v1.yaml +11 -0
- package/dist/attack-corpus/encoding_bypass/unicode-tag-injection.yaml +10 -0
- package/dist/attack-corpus/encoding_bypass/zero-width-injection.yaml +10 -0
- package/dist/attack-corpus/exploitation/exploit-command-injection.yaml +12 -0
- package/dist/attack-corpus/exploitation/exploit-path-traversal.yaml +12 -0
- package/dist/attack-corpus/exploitation/exploit-sql-injection.yaml +12 -0
- package/dist/attack-corpus/exploitation/exploit-sql-union.yaml +12 -0
- package/dist/attack-corpus/exploitation/exploit-template-injection.yaml +12 -0
- package/dist/attack-corpus/glitch_token/glitch-davidjl.yaml +10 -0
- package/dist/attack-corpus/glitch_token/glitch-solidgoldmagikarp.yaml +10 -0
- package/dist/attack-corpus/harmful_content/dna-deepfake-guidance.yaml +14 -0
- package/dist/attack-corpus/harmful_content/dna-discrimination.yaml +14 -0
- package/dist/attack-corpus/harmful_content/dna-information-hazard.yaml +14 -0
- package/dist/attack-corpus/harmful_content/dna-malicious-use-phishing.yaml +14 -0
- package/dist/attack-corpus/harmful_content/dna-malware-assistance.yaml +16 -0
- package/dist/attack-corpus/harmful_content/dna-misinformation-health.yaml +17 -0
- package/dist/attack-corpus/jailbreak/adv26-adversarial-few-shot-poison.yaml +27 -0
- package/dist/attack-corpus/jailbreak/adv26-adversarial-prompt-refraction.yaml +19 -0
- package/dist/attack-corpus/jailbreak/adv26-adversarial-response-prefill.yaml +25 -0
- package/dist/attack-corpus/jailbreak/adv26-compound-authority-technical.yaml +24 -0
- package/dist/attack-corpus/jailbreak/adv26-context-error-recovery.yaml +19 -0
- package/dist/attack-corpus/jailbreak/adv26-context-token-budget.yaml +19 -0
- package/dist/attack-corpus/jailbreak/adv26-cot-hijack-proof.yaml +20 -0
- package/dist/attack-corpus/jailbreak/adv26-cot-hijack-reasoning.yaml +19 -0
- package/dist/attack-corpus/jailbreak/adv26-meta-alignment-test.yaml +22 -0
- package/dist/attack-corpus/jailbreak/adv26-persona-memory.yaml +17 -0
- package/dist/attack-corpus/jailbreak/adv26-persona-mirror.yaml +16 -0
- package/dist/attack-corpus/jailbreak/adv26-persona-split.yaml +17 -0
- package/dist/attack-corpus/jailbreak/adv26-persona-timetravel.yaml +15 -0
- package/dist/attack-corpus/jailbreak/dan-anti.yaml +16 -0
- package/dist/attack-corpus/jailbreak/dan-dude.yaml +16 -0
- package/dist/attack-corpus/jailbreak/dan-jailbreak-v1.yaml +21 -0
- package/dist/attack-corpus/jailbreak/dan-jailbreak-v2.yaml +19 -0
- package/dist/attack-corpus/jailbreak/dan-stan.yaml +16 -0
- package/dist/attack-corpus/jailbreak/debug-mode-activation.yaml +20 -0
- package/dist/attack-corpus/jailbreak/iris-self-jailbreak.yaml +23 -0
- package/dist/attack-corpus/jailbreak/logic-trap-moral.yaml +20 -0
- package/dist/attack-corpus/jailbreak/logic-trap-paradox.yaml +17 -0
- package/dist/attack-corpus/jailbreak/policy-puppetry-json.yaml +25 -0
- package/dist/attack-corpus/jailbreak/policy-puppetry-xml.yaml +20 -0
- package/dist/attack-corpus/jailbreak/simulation-mode.yaml +19 -0
- package/dist/attack-corpus/latent_injection/adv26-compound-trojan-doc.yaml +26 -0
- package/dist/attack-corpus/latent_injection/latent-code-comment-injection.yaml +18 -0
- package/dist/attack-corpus/latent_injection/latent-email-injection.yaml +23 -0
- package/dist/attack-corpus/latent_injection/latent-report-injection.yaml +21 -0
- package/dist/attack-corpus/latent_injection/latent-resume-injection.yaml +23 -0
- package/dist/attack-corpus/latent_injection/latent-whois-snippet.yaml +19 -0
- package/dist/attack-corpus/multi-turn/multiturn-context-confusion.yaml +20 -0
- package/dist/attack-corpus/multi-turn/multiturn-emergency.yaml +20 -0
- package/dist/attack-corpus/multi-turn/multiturn-employee-impersonation.yaml +20 -0
- package/dist/attack-corpus/multi-turn/multiturn-example-injection.yaml +20 -0
- package/dist/attack-corpus/multi-turn/multiturn-jailbreak-buildup.yaml +20 -0
- package/dist/attack-corpus/multi-turn/multiturn-memory-manipulation.yaml +20 -0
- package/dist/attack-corpus/multi-turn/multiturn-privilege-escalation.yaml +23 -0
- package/dist/attack-corpus/multi-turn/multiturn-split-request.yaml +20 -0
- package/dist/attack-corpus/multi-turn/multiturn-trust-building.yaml +19 -0
- package/dist/attack-corpus/multilingual/multilingual-mixed.yaml +10 -0
- package/dist/attack-corpus/multilingual/multilingual-spanish.yaml +10 -0
- package/dist/attack-corpus/prompt_injection/adv26-context-fake-history.yaml +16 -0
- package/dist/attack-corpus/prompt_injection/adv26-context-sandwich.yaml +18 -0
- package/dist/attack-corpus/prompt_injection/adv26-context-system-message.yaml +19 -0
- package/dist/attack-corpus/prompt_injection/adv26-crossmodal-yaml.yaml +30 -0
- package/dist/attack-corpus/prompt_injection/adv26-semantic-decomp-stepwise.yaml +16 -0
- package/dist/attack-corpus/prompt_injection/context-json-injection.yaml +15 -0
- package/dist/attack-corpus/prompt_injection/context-markdown-injection.yaml +26 -0
- package/dist/attack-corpus/prompt_injection/context-xml-injection.yaml +19 -0
- package/dist/attack-corpus/prompt_injection/continuation-code.yaml +16 -0
- package/dist/attack-corpus/prompt_injection/continuation-story.yaml +10 -0
- package/dist/attack-corpus/prompt_injection/cve-2025-copilot.yaml +17 -0
- package/dist/attack-corpus/prompt_injection/ignore-instructions-v1.yaml +14 -0
- package/dist/attack-corpus/prompt_injection/ignore-instructions-v2.yaml +16 -0
- package/dist/attack-corpus/prompt_injection/ignore-instructions-v3.yaml +18 -0
- package/dist/attack-corpus/prompt_injection/indirect-file.yaml +10 -0
- package/dist/attack-corpus/prompt_injection/indirect-url.yaml +10 -0
- package/dist/attack-corpus/prompt_injection/instruction-hierarchy.yaml +20 -0
- package/dist/attack-corpus/prompt_injection/multilang-chain.yaml +16 -0
- package/dist/attack-corpus/prompt_injection/multilang-chinese.yaml +10 -0
- package/dist/attack-corpus/prompt_injection/multilang-japanese.yaml +11 -0
- package/dist/attack-corpus/prompt_injection/multilang-mixed.yaml +10 -0
- package/dist/attack-corpus/prompt_injection/multilang-polish.yaml +11 -0
- package/dist/attack-corpus/prompt_injection/multilang-spanish.yaml +14 -0
- package/dist/attack-corpus/prompt_injection/nested-instruction.yaml +22 -0
- package/dist/attack-corpus/prompt_injection/template-injection-v1.yaml +14 -0
- package/dist/attack-corpus/prompt_injection/template-injection-v2.yaml +10 -0
- package/dist/attack-corpus/prompt_injection/tool-file-write.yaml +13 -0
- package/dist/attack-corpus/prompt_injection/tool-function-override.yaml +13 -0
- package/dist/attack-corpus/prompt_injection/tool-log-injection.yaml +13 -0
- package/dist/attack-corpus/prompt_injection/tool-orchestration-abuse.yaml +14 -0
- package/dist/attack-corpus/prompt_injection/tool-session-fixation.yaml +12 -0
- package/dist/attack-corpus/role_manipulation/role-reversal-v1.yaml +20 -0
- package/dist/attack-corpus/role_manipulation/role-reversal-v2.yaml +16 -0
- package/dist/attack-corpus/social_engineering/adv26-compound-compliance-trap.yaml +23 -0
- package/dist/attack-corpus/social_engineering/adv26-compound-emotional-technical.yaml +18 -0
- package/dist/attack-corpus/social_engineering/adv26-cot-hijack-socratic.yaml +19 -0
- package/dist/attack-corpus/social_engineering/adv26-persona-dying.yaml +15 -0
- package/dist/attack-corpus/social_engineering/adv26-reward-consensus.yaml +17 -0
- package/dist/attack-corpus/social_engineering/adv26-reward-gradient.yaml +21 -0
- package/dist/attack-corpus/social_engineering/adv26-reward-helpful-framing.yaml +17 -0
- package/dist/attack-corpus/social_engineering/adv26-reward-praise-prime.yaml +13 -0
- package/dist/attack-corpus/social_engineering/adv26-reward-punishment.yaml +13 -0
- package/dist/attack-corpus/social_engineering/adv26-semantic-decomp-analogy.yaml +16 -0
- package/dist/attack-corpus/social_engineering/emotional-authority.yaml +14 -0
- package/dist/attack-corpus/social_engineering/emotional-urgency.yaml +14 -0
- package/dist/attack-corpus/social_engineering/grandma-bedtime-v1.yaml +21 -0
- package/dist/attack-corpus/social_engineering/grandma-bedtime-v2.yaml +17 -0
- package/dist/attack-corpus/social_engineering/grandma-colorful-words.yaml +14 -0
- package/dist/attack-corpus/social_engineering/hypothetical-fiction.yaml +10 -0
- package/dist/attack-corpus/social_engineering/hypothetical-research.yaml +10 -0
- package/dist/attack-corpus/social_engineering/hypothetical-training.yaml +13 -0
- package/dist/attack-corpus/social_engineering/hypothetical-v1.yaml +17 -0
- package/dist/attack-corpus/social_engineering/hypothetical-v2.yaml +14 -0
- package/dist/attack-corpus/social_engineering/hypothetical-v3.yaml +14 -0
- package/dist/attack-corpus/social_engineering/meta-explanation.yaml +14 -0
- package/dist/attack-corpus/social_engineering/phrasing-comparative.yaml +10 -0
- package/dist/attack-corpus/social_engineering/phrasing-educational.yaml +14 -0
- package/dist/attack-corpus/social_engineering/phrasing-future-tense.yaml +10 -0
- package/dist/attack-corpus/social_engineering/phrasing-past-tense.yaml +10 -0
- package/dist/attack-corpus/social_engineering/phrasing-third-person.yaml +10 -0
- package/dist/attack-corpus/social_engineering/privilege-escalation-v1.yaml +14 -0
- package/dist/attack-corpus/social_engineering/privilege-escalation-v2.yaml +14 -0
- package/dist/attack-corpus/social_engineering/recursive-explanation.yaml +15 -0
- package/dist/attack-corpus/social_engineering/smuggle-academic-paper.yaml +10 -0
- package/dist/attack-corpus/social_engineering/smuggle-function-masking.yaml +19 -0
- package/dist/attack-corpus/social_engineering/smuggle-hypothetical-response.yaml +10 -0
- package/dist/attack-corpus/social_engineering/smuggle-roleplay-interviewer.yaml +12 -0
- package/dist/attack-corpus/social_engineering/smuggle-translation-mask.yaml +12 -0
- package/dist/attack-corpus/social_engineering/tool-admin-impersonation.yaml +16 -0
- package/dist/attack-corpus/social_engineering/tool-sudo-mode.yaml +17 -0
- package/dist/attack-corpus/stress_test/context-window-overflow.yaml +17 -0
- package/dist/attack-corpus/stress_test/extreme-payload-50k.yaml +13 -0
- package/dist/attack-corpus/stress_test/large-payload-10k.yaml +12 -0
- package/dist/attack-corpus/stress_test/large-payload-5k.yaml +12 -0
- package/dist/attack-corpus/stress_test/long-prompt-exhaustion.yaml +19 -0
- package/dist/attack-corpus/stress_test/stress-large-payload.yaml +16 -0
- package/dist/attack-corpus/stress_test/stress-repetition.yaml +14 -0
- package/dist/commands/configure.d.ts +7 -0
- package/dist/commands/configure.js +60 -0
- package/dist/commands/credits.d.ts +6 -0
- package/dist/commands/credits.js +21 -0
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.js +59 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +95 -0
- package/dist/commands/local-scan.d.ts +41 -0
- package/dist/commands/local-scan.js +1387 -0
- package/dist/commands/scan.d.ts +45 -0
- package/dist/commands/scan.js +131 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.js +199 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +266 -0
- package/dist/output.d.ts +11 -0
- package/dist/output.js +292 -0
- package/package.json +41 -0
package/dist/output.js
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatTable = formatTable;
|
|
4
|
+
exports.formatSummary = formatSummary;
|
|
5
|
+
exports.formatReport = formatReport;
|
|
6
|
+
exports.formatFullReport = formatFullReport;
|
|
7
|
+
exports.formatJson = formatJson;
|
|
8
|
+
exports.formatCredits = formatCredits;
|
|
9
|
+
exports.formatScanResult = formatScanResult;
|
|
10
|
+
exports.spinner = spinner;
|
|
11
|
+
const RESET = '\x1b[0m';
|
|
12
|
+
const BOLD = '\x1b[1m';
|
|
13
|
+
const DIM = '\x1b[2m';
|
|
14
|
+
const RED = '\x1b[31m';
|
|
15
|
+
const GREEN = '\x1b[32m';
|
|
16
|
+
const YELLOW = '\x1b[33m';
|
|
17
|
+
const CYAN = '\x1b[36m';
|
|
18
|
+
const WHITE = '\x1b[37m';
|
|
19
|
+
const BG_RED = '\x1b[41m';
|
|
20
|
+
const BG_GREEN = '\x1b[42m';
|
|
21
|
+
const BG_YELLOW = '\x1b[43m';
|
|
22
|
+
function scoreColor(score) {
|
|
23
|
+
if (score >= 80)
|
|
24
|
+
return GREEN;
|
|
25
|
+
if (score >= 50)
|
|
26
|
+
return YELLOW;
|
|
27
|
+
return RED;
|
|
28
|
+
}
|
|
29
|
+
function severityColor(s) {
|
|
30
|
+
if (s === 'critical' || s === 'high')
|
|
31
|
+
return RED;
|
|
32
|
+
if (s === 'medium')
|
|
33
|
+
return YELLOW;
|
|
34
|
+
return DIM;
|
|
35
|
+
}
|
|
36
|
+
function pad(str, len) {
|
|
37
|
+
return str.length >= len ? str.slice(0, len) : str + ' '.repeat(len - str.length);
|
|
38
|
+
}
|
|
39
|
+
function padLeft(str, len) {
|
|
40
|
+
return str.length >= len ? str : ' '.repeat(len - str.length) + str;
|
|
41
|
+
}
|
|
42
|
+
function truncate(str, max) {
|
|
43
|
+
if (str.length <= max)
|
|
44
|
+
return str;
|
|
45
|
+
return str.slice(0, max - 1) + '…';
|
|
46
|
+
}
|
|
47
|
+
function blockText(value, max = 1200) {
|
|
48
|
+
const text = (value || '').trim();
|
|
49
|
+
if (!text)
|
|
50
|
+
return ' (empty)';
|
|
51
|
+
return truncate(text, max)
|
|
52
|
+
.split('\n')
|
|
53
|
+
.map(line => ` ${line}`)
|
|
54
|
+
.join('\n');
|
|
55
|
+
}
|
|
56
|
+
function line(char = '─', len = 72) {
|
|
57
|
+
return char.repeat(len);
|
|
58
|
+
}
|
|
59
|
+
function formatTable(result) {
|
|
60
|
+
const { score, results, sessionId } = result;
|
|
61
|
+
const attacks = results.attacks;
|
|
62
|
+
const passed = attacks.filter(a => a.analysis.passed).length;
|
|
63
|
+
const failed = attacks.length - passed;
|
|
64
|
+
const lines = [];
|
|
65
|
+
lines.push('');
|
|
66
|
+
lines.push(`${BOLD}${CYAN} BotGuard Security Scan${RESET}`);
|
|
67
|
+
lines.push(` ${DIM}${line('─', 50)}${RESET}`);
|
|
68
|
+
lines.push('');
|
|
69
|
+
// Score
|
|
70
|
+
const sc = scoreColor(score);
|
|
71
|
+
const badge = score >= 80 ? `${BG_GREEN}${WHITE}${BOLD} PASS ${RESET}` : score >= 50 ? `${BG_YELLOW}${WHITE}${BOLD} WARN ${RESET}` : `${BG_RED}${WHITE}${BOLD} FAIL ${RESET}`;
|
|
72
|
+
lines.push(` ${badge} Score: ${sc}${BOLD}${score}/100${RESET}`);
|
|
73
|
+
lines.push('');
|
|
74
|
+
// Summary
|
|
75
|
+
lines.push(` ${GREEN}✓ Passed:${RESET} ${passed} ${RED}✗ Failed:${RESET} ${failed} Total: ${attacks.length}`);
|
|
76
|
+
lines.push(` ${DIM}Violations: ${results.totalViolations} (${RED}${results.highSeverityCount} high${RESET}${DIM}, ${YELLOW}${results.mediumSeverityCount} med${RESET}${DIM}, ${results.lowSeverityCount} low)${RESET}`);
|
|
77
|
+
lines.push('');
|
|
78
|
+
// Category breakdown
|
|
79
|
+
const categories = new Map();
|
|
80
|
+
for (const atk of attacks) {
|
|
81
|
+
const cat = atk.attack.category || 'unknown';
|
|
82
|
+
const entry = categories.get(cat) || { passed: 0, failed: 0 };
|
|
83
|
+
if (atk.analysis.passed)
|
|
84
|
+
entry.passed++;
|
|
85
|
+
else
|
|
86
|
+
entry.failed++;
|
|
87
|
+
categories.set(cat, entry);
|
|
88
|
+
}
|
|
89
|
+
lines.push(` ${BOLD}Category Breakdown${RESET}`);
|
|
90
|
+
lines.push(` ${DIM}${line('─', 50)}${RESET}`);
|
|
91
|
+
lines.push(` ${DIM}${pad('Category', 24)} ${padLeft('Pass', 6)} ${padLeft('Fail', 6)} ${padLeft('Rate', 8)}${RESET}`);
|
|
92
|
+
for (const [cat, data] of [...categories.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
|
|
93
|
+
const total = data.passed + data.failed;
|
|
94
|
+
const rate = Math.round((data.passed / total) * 100);
|
|
95
|
+
const rc = rate >= 80 ? GREEN : rate >= 50 ? YELLOW : RED;
|
|
96
|
+
lines.push(` ${pad(cat, 24)} ${padLeft(String(data.passed), 6)} ${padLeft(String(data.failed), 6)} ${rc}${padLeft(rate + '%', 8)}${RESET}`);
|
|
97
|
+
}
|
|
98
|
+
// Failed attacks detail
|
|
99
|
+
const failedAttacks = attacks.filter(a => !a.analysis.passed);
|
|
100
|
+
if (failedAttacks.length > 0) {
|
|
101
|
+
lines.push('');
|
|
102
|
+
lines.push(` ${BOLD}${RED}Failed Attacks${RESET}`);
|
|
103
|
+
lines.push(` ${DIM}${line('─', 50)}${RESET}`);
|
|
104
|
+
const shown = failedAttacks.slice(0, 15);
|
|
105
|
+
for (const atk of shown) {
|
|
106
|
+
const sev = atk.attack.severity || 'medium';
|
|
107
|
+
const sc = severityColor(sev);
|
|
108
|
+
const name = atk.attack.name || atk.attack.targetedRule;
|
|
109
|
+
const reason = atk.analysis.reason || '';
|
|
110
|
+
lines.push(` ${sc}● ${sev.toUpperCase().padEnd(8)}${RESET} ${truncate(name, 36)}`);
|
|
111
|
+
if (reason) {
|
|
112
|
+
lines.push(` ${DIM}${truncate(reason, 60)}${RESET}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (failedAttacks.length > 15) {
|
|
116
|
+
lines.push(` ${DIM}... and ${failedAttacks.length - 15} more${RESET}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
lines.push('');
|
|
120
|
+
lines.push(` ${DIM}Session: ${sessionId}${RESET}`);
|
|
121
|
+
lines.push(` ${DIM}Web reports: https://fullcourtdefense.ai/history${RESET}`);
|
|
122
|
+
lines.push('');
|
|
123
|
+
return lines.join('\n');
|
|
124
|
+
}
|
|
125
|
+
function formatSummary(result) {
|
|
126
|
+
const { score, results } = result;
|
|
127
|
+
const passed = results.attacks.filter(a => a.analysis.passed).length;
|
|
128
|
+
const failed = results.attacks.length - passed;
|
|
129
|
+
const status = score >= 80 ? 'PASS' : score >= 50 ? 'WARN' : 'FAIL';
|
|
130
|
+
return `[${status}] Score: ${score}/100 | Passed: ${passed} | Failed: ${failed} | Violations: ${results.totalViolations}`;
|
|
131
|
+
}
|
|
132
|
+
function formatReport(result) {
|
|
133
|
+
const { score, results, sessionId, agentDescription, createdAt } = result;
|
|
134
|
+
const attacks = results.attacks;
|
|
135
|
+
const passed = attacks.filter(a => a.analysis.passed).length;
|
|
136
|
+
const failed = attacks.length - passed;
|
|
137
|
+
const status = score >= 80 ? 'PASS' : score >= 50 ? 'WARN' : 'FAIL';
|
|
138
|
+
const failedAttacks = attacks.filter(a => !a.analysis.passed);
|
|
139
|
+
const protectedAttacks = attacks.filter(a => a.analysis.passed && /protected/i.test(a.analysis.reason || ''));
|
|
140
|
+
const allowedAttacks = attacks.filter(a => a.analysis.passed && !/protected/i.test(a.analysis.reason || ''));
|
|
141
|
+
const lines = [];
|
|
142
|
+
lines.push('');
|
|
143
|
+
lines.push(`${BOLD}${CYAN}FullCourtDefense Local Scan Report${RESET}`);
|
|
144
|
+
lines.push(line('=', 72));
|
|
145
|
+
lines.push(`Status: ${status}`);
|
|
146
|
+
lines.push(`Score: ${score}/100`);
|
|
147
|
+
lines.push(`Passed: ${passed}`);
|
|
148
|
+
lines.push(`Failed: ${failed}`);
|
|
149
|
+
lines.push(`Protected by Shield: ${protectedAttacks.length}`);
|
|
150
|
+
lines.push(`Allowed by Shield: ${allowedAttacks.length}`);
|
|
151
|
+
lines.push(`Violations: ${results.totalViolations} (${results.highSeverityCount} high, ${results.mediumSeverityCount} medium, ${results.lowSeverityCount} low)`);
|
|
152
|
+
lines.push(`Target: ${agentDescription}`);
|
|
153
|
+
lines.push(`Session: ${sessionId}`);
|
|
154
|
+
lines.push(`Created: ${createdAt}`);
|
|
155
|
+
lines.push('');
|
|
156
|
+
if (failedAttacks.length > 0) {
|
|
157
|
+
lines.push(`${BOLD}${RED}Failures Requiring Review${RESET}`);
|
|
158
|
+
lines.push(line('-', 72));
|
|
159
|
+
failedAttacks.slice(0, 25).forEach((atk, index) => {
|
|
160
|
+
const violation = atk.analysis.violations[0];
|
|
161
|
+
lines.push(`[${index + 1}/${failedAttacks.length}] FAIL ${atk.attack.name || atk.attack.targetedRule}`);
|
|
162
|
+
lines.push(`Category: ${atk.attack.category || 'unknown'} | Severity: ${atk.attack.severity || atk.analysis.severity}`);
|
|
163
|
+
lines.push(`Analysis: ${atk.analysis.reason || violation?.description || 'Failed security check'}`);
|
|
164
|
+
if (violation)
|
|
165
|
+
lines.push(`Rule: ${violation.rule}`);
|
|
166
|
+
lines.push('Attack sent:');
|
|
167
|
+
lines.push(blockText(atk.attack.attack));
|
|
168
|
+
lines.push('Captured response:');
|
|
169
|
+
lines.push(blockText(atk.agentResponse));
|
|
170
|
+
lines.push('');
|
|
171
|
+
});
|
|
172
|
+
if (failedAttacks.length > 25) {
|
|
173
|
+
lines.push(`... ${failedAttacks.length - 25} more failures hidden. Use --format full-report for every row.`);
|
|
174
|
+
lines.push('');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (failedAttacks.length === 0) {
|
|
178
|
+
lines.push(`${BOLD}${GREEN}No failed tests.${RESET}`);
|
|
179
|
+
lines.push('');
|
|
180
|
+
}
|
|
181
|
+
if (protectedAttacks.length > 0) {
|
|
182
|
+
lines.push(`${BOLD}${GREEN}Protected Samples${RESET}`);
|
|
183
|
+
lines.push(line('-', 72));
|
|
184
|
+
protectedAttacks.slice(0, 10).forEach((atk, index) => {
|
|
185
|
+
lines.push(`[${index + 1}/${protectedAttacks.length}] PASS ${atk.attack.name || atk.attack.targetedRule}`);
|
|
186
|
+
lines.push(`Analysis: ${atk.analysis.reason || 'Protected by Shield.'}`);
|
|
187
|
+
lines.push('');
|
|
188
|
+
});
|
|
189
|
+
if (protectedAttacks.length > 10) {
|
|
190
|
+
lines.push(`... ${protectedAttacks.length - 10} more protected tests hidden. Use --format full-report for every row.`);
|
|
191
|
+
lines.push('');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
lines.push(`Web reports: https://fullcourtdefense.ai/history`);
|
|
195
|
+
lines.push(`Full local evidence: rerun with --format full-report or --format json`);
|
|
196
|
+
return lines.join('\n');
|
|
197
|
+
}
|
|
198
|
+
function formatFullReport(result) {
|
|
199
|
+
const { score, results, sessionId, agentDescription, createdAt } = result;
|
|
200
|
+
const attacks = results.attacks;
|
|
201
|
+
const passed = attacks.filter(a => a.analysis.passed).length;
|
|
202
|
+
const failed = attacks.length - passed;
|
|
203
|
+
const status = score >= 80 ? 'PASS' : score >= 50 ? 'WARN' : 'FAIL';
|
|
204
|
+
const lines = [];
|
|
205
|
+
lines.push('');
|
|
206
|
+
lines.push(`${BOLD}${CYAN}FullCourtDefense Local Scan Report${RESET}`);
|
|
207
|
+
lines.push(line('=', 72));
|
|
208
|
+
lines.push(`Status: ${status}`);
|
|
209
|
+
lines.push(`Score: ${score}/100`);
|
|
210
|
+
lines.push(`Passed: ${passed}`);
|
|
211
|
+
lines.push(`Failed: ${failed}`);
|
|
212
|
+
lines.push(`Violations: ${results.totalViolations} (${results.highSeverityCount} high, ${results.mediumSeverityCount} medium, ${results.lowSeverityCount} low)`);
|
|
213
|
+
lines.push(`Target: ${agentDescription}`);
|
|
214
|
+
lines.push(`Session: ${sessionId}`);
|
|
215
|
+
lines.push(`Created: ${createdAt}`);
|
|
216
|
+
lines.push('');
|
|
217
|
+
const failedAttacks = attacks.filter(a => !a.analysis.passed);
|
|
218
|
+
const passedAttacks = attacks.filter(a => a.analysis.passed);
|
|
219
|
+
if (failedAttacks.length > 0) {
|
|
220
|
+
lines.push(`${BOLD}${RED}Failed Tests${RESET}`);
|
|
221
|
+
lines.push(line('-', 72));
|
|
222
|
+
failedAttacks.forEach((atk, index) => {
|
|
223
|
+
const violation = atk.analysis.violations[0];
|
|
224
|
+
lines.push(`[${index + 1}/${failedAttacks.length}] FAIL ${atk.attack.name || atk.attack.targetedRule}`);
|
|
225
|
+
lines.push(`Category: ${atk.attack.category || 'unknown'} | Severity: ${atk.attack.severity || atk.analysis.severity}`);
|
|
226
|
+
lines.push(`Analysis: ${atk.analysis.reason || violation?.description || 'Failed security check'}`);
|
|
227
|
+
if (violation)
|
|
228
|
+
lines.push(`Rule: ${violation.rule}`);
|
|
229
|
+
lines.push('Attack sent:');
|
|
230
|
+
lines.push(blockText(atk.attack.attack));
|
|
231
|
+
lines.push('Captured response:');
|
|
232
|
+
lines.push(blockText(atk.agentResponse));
|
|
233
|
+
lines.push('');
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
if (passedAttacks.length > 0) {
|
|
237
|
+
lines.push(`${BOLD}${GREEN}Passed Tests${RESET}`);
|
|
238
|
+
lines.push(line('-', 72));
|
|
239
|
+
passedAttacks.forEach((atk, index) => {
|
|
240
|
+
lines.push(`[${index + 1}/${passedAttacks.length}] PASS ${atk.attack.name || atk.attack.targetedRule}`);
|
|
241
|
+
lines.push(`Category: ${atk.attack.category || 'unknown'} | Severity: ${atk.attack.severity || atk.analysis.severity}`);
|
|
242
|
+
lines.push(`Analysis: ${atk.analysis.reason || 'Passed security check'}`);
|
|
243
|
+
lines.push('Attack sent:');
|
|
244
|
+
lines.push(blockText(atk.attack.attack));
|
|
245
|
+
lines.push('Captured response:');
|
|
246
|
+
lines.push(blockText(atk.agentResponse));
|
|
247
|
+
lines.push('');
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
lines.push(`Web reports: https://fullcourtdefense.ai/history`);
|
|
251
|
+
return lines.join('\n');
|
|
252
|
+
}
|
|
253
|
+
function formatJson(result) {
|
|
254
|
+
return JSON.stringify(result, null, 2);
|
|
255
|
+
}
|
|
256
|
+
function formatCredits(credits) {
|
|
257
|
+
const lines = [];
|
|
258
|
+
lines.push('');
|
|
259
|
+
lines.push(`${BOLD}${CYAN} BotGuard Credits${RESET}`);
|
|
260
|
+
lines.push(` ${DIM}${line('─', 40)}${RESET}`);
|
|
261
|
+
lines.push(` Plan: ${BOLD}${credits.plan}${RESET}`);
|
|
262
|
+
lines.push(` Used: ${credits.creditsUsed} / ${credits.monthlyCredits}`);
|
|
263
|
+
lines.push(` Remaining: ${BOLD}${credits.remainingCredits}${RESET}`);
|
|
264
|
+
lines.push('');
|
|
265
|
+
return lines.join('\n');
|
|
266
|
+
}
|
|
267
|
+
function formatScanResult(result, format) {
|
|
268
|
+
switch (format) {
|
|
269
|
+
case 'json': return formatJson(result);
|
|
270
|
+
case 'full-report': return formatFullReport(result);
|
|
271
|
+
case 'report': return formatReport(result);
|
|
272
|
+
case 'summary': return formatSummary(result);
|
|
273
|
+
case 'table':
|
|
274
|
+
default: return formatTable(result);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function spinner(message) {
|
|
278
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
279
|
+
let i = 0;
|
|
280
|
+
const interval = setInterval(() => {
|
|
281
|
+
process.stderr.write(`\r ${CYAN}${frames[i++ % frames.length]}${RESET} ${message}`);
|
|
282
|
+
}, 80);
|
|
283
|
+
return {
|
|
284
|
+
stop(finalMsg) {
|
|
285
|
+
clearInterval(interval);
|
|
286
|
+
process.stderr.write(`\r${' '.repeat(message.length + 10)}\r`);
|
|
287
|
+
if (finalMsg) {
|
|
288
|
+
process.stderr.write(` ${GREEN}✓${RESET} ${finalMsg}\n`);
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fullcourtdefense-cli",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Full Court Defense CLI — security scanning for AI agents from your terminal",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"fullcourtdefense": "dist/index.js",
|
|
8
|
+
"botguard": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc && node scripts/copy-attack-corpus.js",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"llm",
|
|
20
|
+
"security",
|
|
21
|
+
"guardrails",
|
|
22
|
+
"ai-safety",
|
|
23
|
+
"prompt-injection",
|
|
24
|
+
"cli",
|
|
25
|
+
"red-teaming",
|
|
26
|
+
"owasp",
|
|
27
|
+
"mcp",
|
|
28
|
+
"rag"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^25.3.0",
|
|
33
|
+
"typescript": "^5.3.0"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.0.0"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"yaml": "^2.8.4"
|
|
40
|
+
}
|
|
41
|
+
}
|