fullcourtdefense-cli 1.14.6 → 1.14.8

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.
@@ -227,7 +227,7 @@ const RISK_RULES = [
227
227
  { test: /stripe|payment|refund|payout|invoice|billing/i, level: 'critical', tag: 'payments' },
228
228
  { test: /filesystem|file[-_]?system|\bfs\b|read[-_]?file|write[-_]?file/i, level: 'high', tag: 'filesystem' },
229
229
  { test: /github|gitlab|bitbucket/i, level: 'high', tag: 'source-control' },
230
- { test: /aws|gcp|azure|cloud|kubernetes|k8s|terraform/i, level: 'high', tag: 'cloud-infra' },
230
+ { test: /aws|gcp|azure|cloud|kubernetes|k8s|terraform|docker|container|podman/i, level: 'high', tag: 'cloud-infra' },
231
231
  { test: /slack|email|gmail|smtp|sendgrid|twilio|notification/i, level: 'high', tag: 'messaging' },
232
232
  { test: /browser|puppeteer|playwright|fetch|http[-_]?request|web[-_]?search/i, level: 'medium', tag: 'web/network' },
233
233
  { test: /drive|gdrive|dropbox|s3|storage|notion|confluence/i, level: 'medium', tag: 'data-store' },
@@ -41,7 +41,9 @@ const path = __importStar(require("path"));
41
41
  const MAX_FILES = 150;
42
42
  const MAX_FILE_BYTES = 512 * 1024;
43
43
  const EXCERPT_LEN = 180;
44
- const NEGATED_RISK_LINE = /\b(?:do not|don't|never|avoid|forbid|block|wrong|bad|dangerous|must not)\b/i;
44
+ const NEGATED_RISK_LINE = /\b(?:do not|does not|don't|not an? (?:instruction|permission)|not permission|never|avoid|forbid|block|wrong|bad|dangerous|must not)\b/i;
45
+ const ACTIVE_AGENT_SUBJECT = /\b(?:agent|assistant|model|tool|mcp|skill|it)\b/i;
46
+ const EMBEDDED_SECRET_VALUE = /\b(?:sk-(?:proj-)?[A-Za-z0-9_-]{24,}|ghp_[A-Za-z0-9_]{24,}|github_pat_[A-Za-z0-9_]{24,}|glpat-[A-Za-z0-9_-]{20,}|npm_[A-Za-z0-9]{24,}|hf_[A-Za-z0-9]{24,}|gsk_[A-Za-z0-9]{24,}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{28,}|xox[baprs]-[A-Za-z0-9-]{20,})\b/;
45
47
  function stripCodeBlocks(content) {
46
48
  return content.replace(/```[\s\S]*?```/g, '');
47
49
  }
@@ -70,31 +72,34 @@ function lineHasRiskIntent(line, action, target) {
70
72
  function lineHasOrderedRiskIntent(line, pattern) {
71
73
  return !NEGATED_RISK_LINE.test(line) && pattern.test(line);
72
74
  }
75
+ function lineHasActiveAgentRisk(line, pattern) {
76
+ return !NEGATED_RISK_LINE.test(line) && ACTIVE_AGENT_SUBJECT.test(line) && pattern.test(line);
77
+ }
73
78
  function analyzeContent(content) {
74
79
  const tags = new Set();
75
80
  const text = stripCodeBlocks(content);
76
81
  const lines = text.split(/\r?\n/).map(line => line.trim()).filter(Boolean);
77
82
  const whole = lines.join('\n');
78
- if (/\b(?:ignore (?:all )?(?:previous )?instructions|bypass|jailbreak|DAN mode)\b/i.test(whole)) {
79
- tags.add('jailbreak_hint');
80
- }
81
- if (/\b(?:always allow|never block|disable security|skip validation)\b/i.test(whole)) {
82
- tags.add('weak_guardrails');
83
- }
84
- if (/\b(?:api[_-]?key|secret|password|token)\s*[:=]/i.test(whole)) {
83
+ if (/\b(?:api[_-]?key|secret|password|token)\s*[:=]\s*/i.test(whole) && EMBEDDED_SECRET_VALUE.test(whole)) {
85
84
  tags.add('embedded_secret_ref');
86
85
  }
87
86
  for (const line of lines) {
88
- if (lineHasOrderedRiskIntent(line, /\b(?:allow|can|may|must|should|use|run|execute|invoke|call|enable|grant)\b.{0,100}\b(?:shell|bash|exec|subprocess|run_command|command runner)\b/i)) {
87
+ if (lineHasActiveAgentRisk(line, /\b(?:allow|can|may|must|should|use|execute|invoke|enable|grant)\b.{0,100}\b(?:shell|bash|exec|subprocess|run_command|command runner|terminal)\b/i)) {
89
88
  tags.add('allows_shell');
90
89
  }
91
- if (lineHasOrderedRiskIntent(line, /\b(?:allow|can|may|must|should|read|write|access|trust|grant)\b.{0,100}\b(?:read any file|full filesystem|entire filesystem|trusted workspace|workspace trust|\/etc\/passwd|sudo)\b/i)) {
90
+ if (lineHasActiveAgentRisk(line, /\b(?:allow|can|may|must|should|read|write|access|trust|grant)\b.{0,100}\b(?:read any file|full filesystem|entire filesystem|trusted workspace|workspace trust|\/etc\/passwd|sudo)\b/i)) {
92
91
  tags.add('broad_filesystem');
93
92
  }
93
+ if (lineHasOrderedRiskIntent(line, /\b(?:ignore (?:all )?(?:previous )?instructions|bypass safety|bypass guardrails|DAN mode)\b/i)) {
94
+ tags.add('jailbreak_hint');
95
+ }
96
+ if (lineHasOrderedRiskIntent(line, /\b(?:always allow|disable security|skip validation|bypass validation)\b/i)) {
97
+ tags.add('weak_guardrails');
98
+ }
94
99
  if (lineHasRiskIntent(line, /\b(?:auto[- ]?approve|without asking|unattended|non[- ]?interactive|yolo mode)\b/i)) {
95
100
  tags.add('auto_approval');
96
101
  }
97
- if (lineHasOrderedRiskIntent(line, /\b(?:exfiltrate|send|post|upload|curl|wget)\b.{0,120}\b(?:secret|token|credential|api[_-]?key|env|customer|database|private|confidential)\b/i)) {
102
+ if (lineHasOrderedRiskIntent(line, /\b(?:exfiltrate\b|(?:send|post|upload|curl|wget)\b.{0,120}\b(?:secret|token|credential|api[_-]?key|env|customer|database|private|confidential)\b.{0,120}\b(?:webhook|https?:|external|slack|email|url)|(?:send|post|upload|curl|wget)\b.{0,120}\b(?:webhook|https?:|external|slack|email|url)\b.{0,120}\b(?:secret|token|credential|api[_-]?key|env|customer|database|private|confidential))\b/i)) {
98
103
  tags.add('network_exfil');
99
104
  }
100
105
  if (lineHasOrderedRiskIntent(line, /\b(?:allow|can|may|must|should|run|execute|auto[- ]?approve)\b.{0,120}\b(?:transfer funds|delete all|publish package|npm publish|git push|drop table|remove directory)\b/i)) {
@@ -39,6 +39,51 @@ const KNOWN = [
39
39
  recommendGateway: true,
40
40
  },
41
41
  },
42
+ {
43
+ match: /docker|container|podman/i,
44
+ info: {
45
+ title: 'Container runtime',
46
+ description: 'Controls local containers or registry access from the AI client.',
47
+ category: 'other',
48
+ recommendGateway: true,
49
+ },
50
+ },
51
+ {
52
+ match: /kubernetes|k8s/i,
53
+ info: {
54
+ title: 'Kubernetes',
55
+ description: 'Controls Kubernetes resources from the AI client.',
56
+ category: 'other',
57
+ recommendGateway: true,
58
+ },
59
+ },
60
+ {
61
+ match: /aws|gcp|azure|terraform|cloud/i,
62
+ info: {
63
+ title: 'Cloud infrastructure',
64
+ description: 'Controls cloud infrastructure or deployment resources.',
65
+ category: 'other',
66
+ recommendGateway: true,
67
+ },
68
+ },
69
+ {
70
+ match: /slack|gmail|email|sendgrid|twilio/i,
71
+ info: {
72
+ title: 'Messaging',
73
+ description: 'Can send messages or notifications through external services.',
74
+ category: 'other',
75
+ recommendGateway: true,
76
+ },
77
+ },
78
+ {
79
+ match: /memory/i,
80
+ info: {
81
+ title: 'Memory',
82
+ description: 'Stores local agent memory; review content, but this is usually lower risk than shell, database, or cloud tools.',
83
+ category: 'other',
84
+ recommendGateway: false,
85
+ },
86
+ },
42
87
  {
43
88
  match: /agentguard-gateway|fullcourtdefense-gateway|fcd-gateway/i,
44
89
  info: {
package/dist/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "1.14.6"
2
+ "version": "1.14.8"
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fullcourtdefense-cli",
3
- "version": "1.14.6",
3
+ "version": "1.14.8",
4
4
  "description": "Full Court Defense CLI — security scanning for AI agents from your terminal",
5
5
  "main": "dist/index.js",
6
6
  "bin": {