@guava-parity/guard-scanner 13.0.0 → 16.0.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/README.md +170 -215
- package/README_ja.md +252 -0
- package/SECURITY.md +12 -4
- package/SKILL.md +148 -57
- package/dist/cli.cjs +5997 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +6003 -0
- package/dist/index.cjs +4825 -0
- package/dist/index.d.mts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.mjs +4798 -0
- package/dist/mcp-server.cjs +4756 -0
- package/dist/mcp-server.d.mts +1 -0
- package/dist/mcp-server.d.ts +1 -0
- package/dist/mcp-server.mjs +4767 -0
- package/dist/openclaw-plugin.cjs +4863 -0
- package/dist/openclaw-plugin.d.mts +11 -0
- package/dist/openclaw-plugin.d.ts +11 -0
- package/dist/openclaw-plugin.mjs +4854 -0
- package/dist/types.cjs +18 -0
- package/dist/types.d.mts +215 -0
- package/dist/types.d.ts +215 -0
- package/dist/types.mjs +1 -0
- package/docs/EVIDENCE_DRIVEN.md +182 -0
- package/docs/banner.png +0 -0
- package/docs/data/benchmark-ledger.json +1428 -0
- package/docs/data/corpus-metrics.json +11 -0
- package/docs/data/fp-ledger.json +18 -0
- package/docs/data/latest.json +25837 -2481
- package/docs/data/quality-contract.json +36 -0
- package/docs/generated/npm-audit-20260312.json +96 -0
- package/docs/generated/openclaw-upstream-status.json +25 -0
- package/docs/glossary.md +46 -0
- package/docs/index.html +1085 -496
- package/docs/logo.png +0 -0
- package/docs/openclaw-compatibility-audit.md +45 -0
- package/docs/openclaw-continuous-compatibility-plan.md +37 -0
- package/docs/rules/a2a-contagion.md +68 -0
- package/docs/rules/advanced-exfil.md +52 -0
- package/docs/rules/agent-protocol.md +108 -0
- package/docs/rules/api-abuse.md +68 -0
- package/docs/rules/autonomous-risk.md +92 -0
- package/docs/rules/config-impact.md +132 -0
- package/docs/rules/credential-handling.md +100 -0
- package/docs/rules/cve-patterns.md +332 -0
- package/docs/rules/data-exposure.md +84 -0
- package/docs/rules/exfiltration.md +36 -0
- package/docs/rules/financial-access.md +84 -0
- package/docs/rules/identity-hijack.md +140 -0
- package/docs/rules/inference-manipulation.md +60 -0
- package/docs/rules/leaky-skills.md +52 -0
- package/docs/rules/malicious-code.md +108 -0
- package/docs/rules/mcp-security.md +148 -0
- package/docs/rules/memory-poisoning.md +84 -0
- package/docs/rules/model-poisoning.md +44 -0
- package/docs/rules/obfuscation.md +60 -0
- package/docs/rules/persistence.md +108 -0
- package/docs/rules/pii-exposure.md +116 -0
- package/docs/rules/prompt-injection.md +148 -0
- package/docs/rules/prompt-worm.md +44 -0
- package/docs/rules/safeguard-bypass.md +44 -0
- package/docs/rules/sandbox-escape.md +100 -0
- package/docs/rules/secret-detection.md +44 -0
- package/docs/rules/supply-chain-v2.md +92 -0
- package/docs/rules/suspicious-download.md +60 -0
- package/docs/rules/trust-boundary.md +76 -0
- package/docs/rules/trust-exploitation.md +92 -0
- package/docs/rules/unverifiable-deps.md +84 -0
- package/docs/rules/vdb-injection.md +84 -0
- package/docs/security-vulnerability-report-20260312.md +53 -0
- package/docs/spec/PRD_V2_ARCHITECTURE.md +55 -0
- package/docs/spec/capabilities.json +174 -0
- package/docs/spec/finding.schema.json +104 -0
- package/docs/spec/integration-manifest.md +39 -0
- package/docs/spec/plugin-trust.json +11 -0
- package/docs/spec/sbom.json +33 -0
- package/docs/threat-model.md +65 -0
- package/docs/v13-architecture-manifest.md +55 -0
- package/hooks/context.ts +306 -0
- package/hooks/guard-scanner/plugin.ts +24 -1
- package/openclaw-plugin.mts +107 -0
- package/openclaw.plugin.json +30 -53
- package/package.json +66 -13
- package/src/asset-auditor.js +0 -508
- package/src/ci-reporter.js +0 -135
- package/src/cli.js +0 -294
- package/src/html-template.js +0 -239
- package/src/ioc-db.js +0 -54
- package/src/mcp-server.js +0 -702
- package/src/patterns.js +0 -611
- package/src/quarantine.js +0 -41
- package/src/runtime-guard.js +0 -346
- package/src/scanner.js +0 -1157
- package/src/vt-client.js +0 -202
- package/src/watcher.js +0 -170
package/dist/types.cjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
|
|
16
|
+
// src/types.ts
|
|
17
|
+
var types_exports = {};
|
|
18
|
+
module.exports = __toCommonJS(types_exports);
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
type Severity = "LOW" | "MEDIUM" | "HIGH" | "CRITICAL";
|
|
2
|
+
type GuardMode = "monitor" | "enforce" | "strict";
|
|
3
|
+
type RuntimeAction = "blocked" | "warned";
|
|
4
|
+
interface EvidenceSpan {
|
|
5
|
+
file?: string;
|
|
6
|
+
start_line: number;
|
|
7
|
+
end_line: number;
|
|
8
|
+
}
|
|
9
|
+
interface FindingEvidence {
|
|
10
|
+
file?: string;
|
|
11
|
+
line?: number | null;
|
|
12
|
+
sample?: string;
|
|
13
|
+
match_count?: number;
|
|
14
|
+
tool_name?: string;
|
|
15
|
+
params_preview?: string;
|
|
16
|
+
layer?: number;
|
|
17
|
+
layer_name?: string;
|
|
18
|
+
owasp_asi?: string[];
|
|
19
|
+
protocol_surface?: string[];
|
|
20
|
+
}
|
|
21
|
+
interface Finding {
|
|
22
|
+
schema_version?: string;
|
|
23
|
+
source?: "static" | "runtime";
|
|
24
|
+
id: string;
|
|
25
|
+
rule_id?: string;
|
|
26
|
+
cat?: string;
|
|
27
|
+
category: string;
|
|
28
|
+
severity: Severity;
|
|
29
|
+
desc?: string;
|
|
30
|
+
description: string;
|
|
31
|
+
file?: string;
|
|
32
|
+
line?: number | null;
|
|
33
|
+
matchCount?: number;
|
|
34
|
+
sample?: string;
|
|
35
|
+
rationale: string;
|
|
36
|
+
preconditions: string;
|
|
37
|
+
remediation_hint: string;
|
|
38
|
+
false_positive_scenarios: string[];
|
|
39
|
+
validation_state: string;
|
|
40
|
+
validation_status: string;
|
|
41
|
+
confidence: number;
|
|
42
|
+
attack_chain_id: string | null;
|
|
43
|
+
evidence: FindingEvidence;
|
|
44
|
+
evidence_spans: EvidenceSpan[];
|
|
45
|
+
layer?: number;
|
|
46
|
+
layer_name?: string;
|
|
47
|
+
owasp_asi?: string[];
|
|
48
|
+
protocol_surface?: string[];
|
|
49
|
+
action?: RuntimeAction;
|
|
50
|
+
}
|
|
51
|
+
interface SkillFindingResult {
|
|
52
|
+
skill: string;
|
|
53
|
+
risk: number;
|
|
54
|
+
verdict: string;
|
|
55
|
+
findings: Finding[];
|
|
56
|
+
}
|
|
57
|
+
interface ThresholdBand {
|
|
58
|
+
suspicious: number;
|
|
59
|
+
malicious: number;
|
|
60
|
+
}
|
|
61
|
+
interface ScanStats {
|
|
62
|
+
scanned: number;
|
|
63
|
+
clean: number;
|
|
64
|
+
low: number;
|
|
65
|
+
suspicious: number;
|
|
66
|
+
malicious: number;
|
|
67
|
+
}
|
|
68
|
+
interface Recommendation {
|
|
69
|
+
skill: string;
|
|
70
|
+
actions: string[];
|
|
71
|
+
}
|
|
72
|
+
interface ScanReport {
|
|
73
|
+
schema_version: string;
|
|
74
|
+
timestamp: string;
|
|
75
|
+
scanner: string;
|
|
76
|
+
finding_schema_version: string;
|
|
77
|
+
mode: "normal" | "strict";
|
|
78
|
+
compliance_mode?: "owasp-asi" | null;
|
|
79
|
+
stats: ScanStats;
|
|
80
|
+
thresholds: ThresholdBand;
|
|
81
|
+
findings: SkillFindingResult[];
|
|
82
|
+
recommendations: Recommendation[];
|
|
83
|
+
layer_summary?: Array<Record<string, unknown>>;
|
|
84
|
+
owasp_asi_coverage?: Array<Record<string, unknown>>;
|
|
85
|
+
threat_model?: Record<string, unknown>;
|
|
86
|
+
iocVersion: string;
|
|
87
|
+
}
|
|
88
|
+
interface TextScanResult {
|
|
89
|
+
safe: boolean;
|
|
90
|
+
risk: number;
|
|
91
|
+
detections: Finding[];
|
|
92
|
+
}
|
|
93
|
+
interface ScannerOptions {
|
|
94
|
+
verbose?: boolean;
|
|
95
|
+
selfExclude?: boolean;
|
|
96
|
+
strict?: boolean;
|
|
97
|
+
summaryOnly?: boolean;
|
|
98
|
+
quiet?: boolean;
|
|
99
|
+
checkDeps?: boolean;
|
|
100
|
+
soulLock?: boolean;
|
|
101
|
+
plugins?: string[];
|
|
102
|
+
rulesFile?: string;
|
|
103
|
+
compliance?: "owasp-asi";
|
|
104
|
+
}
|
|
105
|
+
interface CustomRule {
|
|
106
|
+
id: string;
|
|
107
|
+
cat: string;
|
|
108
|
+
regex: RegExp;
|
|
109
|
+
severity: Severity;
|
|
110
|
+
desc: string;
|
|
111
|
+
codeOnly?: boolean;
|
|
112
|
+
docOnly?: boolean;
|
|
113
|
+
all?: boolean;
|
|
114
|
+
soulLock?: boolean;
|
|
115
|
+
}
|
|
116
|
+
interface PluginConfig {
|
|
117
|
+
mode?: GuardMode;
|
|
118
|
+
auditLog?: boolean;
|
|
119
|
+
customRules?: string;
|
|
120
|
+
}
|
|
121
|
+
interface RuntimeDecision {
|
|
122
|
+
blocked: boolean;
|
|
123
|
+
blockReason: string | null;
|
|
124
|
+
detections: Finding[];
|
|
125
|
+
mode: GuardMode;
|
|
126
|
+
toolName?: string;
|
|
127
|
+
matchedPolicyId?: string | null;
|
|
128
|
+
policyRationale?: string | null;
|
|
129
|
+
riskAmplificationReasons?: string[];
|
|
130
|
+
remediationSuggestion?: string | null;
|
|
131
|
+
policyDecision?: RuntimePolicyDecision | null;
|
|
132
|
+
}
|
|
133
|
+
interface McpRequest {
|
|
134
|
+
method: string;
|
|
135
|
+
params?: Record<string, unknown>;
|
|
136
|
+
id?: string | number | null;
|
|
137
|
+
}
|
|
138
|
+
interface SarifReport {
|
|
139
|
+
version: string;
|
|
140
|
+
$schema?: string;
|
|
141
|
+
runs: Array<Record<string, unknown>>;
|
|
142
|
+
}
|
|
143
|
+
interface CapabilityMetrics {
|
|
144
|
+
static_pattern_count: number;
|
|
145
|
+
runtime_check_count?: number;
|
|
146
|
+
threat_category_count: number;
|
|
147
|
+
runtime_layer_count?: number;
|
|
148
|
+
runtime_layers?: number;
|
|
149
|
+
benchmark_corpus_version?: string;
|
|
150
|
+
explainability_completeness_rate?: number;
|
|
151
|
+
runtime_check_latency_budget_ms?: number;
|
|
152
|
+
quality_targets?: QualityTargets;
|
|
153
|
+
[key: string]: unknown;
|
|
154
|
+
}
|
|
155
|
+
interface RuntimeCheckStats {
|
|
156
|
+
total: number;
|
|
157
|
+
byLayer: Record<number, number>;
|
|
158
|
+
bySeverity: Partial<Record<Severity, number>>;
|
|
159
|
+
}
|
|
160
|
+
interface QualityTargets {
|
|
161
|
+
precision_min: number;
|
|
162
|
+
recall_min: number;
|
|
163
|
+
false_positive_rate_max: number;
|
|
164
|
+
false_negative_rate_max: number;
|
|
165
|
+
explainability_completeness_rate_min: number;
|
|
166
|
+
runtime_check_latency_budget_ms: number;
|
|
167
|
+
false_positive_budget_by_category: Record<string, number>;
|
|
168
|
+
}
|
|
169
|
+
interface RuntimePolicyContract {
|
|
170
|
+
id?: string;
|
|
171
|
+
allowed_tools?: string[];
|
|
172
|
+
blocked_tools?: string[];
|
|
173
|
+
max_network_scope?: "none" | "internal-only" | "external-ok";
|
|
174
|
+
secret_bearing_context?: boolean;
|
|
175
|
+
memory_write_permission?: boolean;
|
|
176
|
+
}
|
|
177
|
+
interface RuntimePolicyDecision {
|
|
178
|
+
action: "allow" | "block";
|
|
179
|
+
reason: string;
|
|
180
|
+
policyId: string;
|
|
181
|
+
amplificationReasons: string[];
|
|
182
|
+
remediationSuggestion: string;
|
|
183
|
+
}
|
|
184
|
+
interface ThreatModel {
|
|
185
|
+
timestamp: string;
|
|
186
|
+
surface: Record<string, boolean>;
|
|
187
|
+
summary: string;
|
|
188
|
+
owasp_asi?: string[];
|
|
189
|
+
layer_summary?: Array<Record<string, unknown>>;
|
|
190
|
+
protocol_surfaces?: string[];
|
|
191
|
+
}
|
|
192
|
+
interface GuardScannerInstance {
|
|
193
|
+
verbose: boolean;
|
|
194
|
+
strict: boolean;
|
|
195
|
+
summaryOnly: boolean;
|
|
196
|
+
quiet: boolean;
|
|
197
|
+
checkDeps: boolean;
|
|
198
|
+
soulLock: boolean;
|
|
199
|
+
thresholds: ThresholdBand;
|
|
200
|
+
findings: SkillFindingResult[];
|
|
201
|
+
stats: ScanStats;
|
|
202
|
+
scanText(text: string): TextScanResult;
|
|
203
|
+
scanDirectory(dir: string): SkillFindingResult[];
|
|
204
|
+
scanTarget(targetPath: string): ScanReport;
|
|
205
|
+
toJSON(): ScanReport;
|
|
206
|
+
toSARIF(scanDir: string): SarifReport;
|
|
207
|
+
toHTML(): string;
|
|
208
|
+
generateThreatModel(findings: Finding[]): ThreatModel;
|
|
209
|
+
}
|
|
210
|
+
interface GuardScannerConstructor {
|
|
211
|
+
new (options?: ScannerOptions): GuardScannerInstance;
|
|
212
|
+
}
|
|
213
|
+
type ScanResult = SkillFindingResult;
|
|
214
|
+
|
|
215
|
+
export type { CapabilityMetrics, CustomRule, EvidenceSpan, Finding, FindingEvidence, GuardMode, GuardScannerConstructor, GuardScannerInstance, McpRequest, PluginConfig, QualityTargets, Recommendation, RuntimeAction, RuntimeCheckStats, RuntimeDecision, RuntimePolicyContract, RuntimePolicyDecision, SarifReport, ScanReport, ScanResult, ScanStats, ScannerOptions, Severity, SkillFindingResult, TextScanResult, ThreatModel, ThresholdBand };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
type Severity = "LOW" | "MEDIUM" | "HIGH" | "CRITICAL";
|
|
2
|
+
type GuardMode = "monitor" | "enforce" | "strict";
|
|
3
|
+
type RuntimeAction = "blocked" | "warned";
|
|
4
|
+
interface EvidenceSpan {
|
|
5
|
+
file?: string;
|
|
6
|
+
start_line: number;
|
|
7
|
+
end_line: number;
|
|
8
|
+
}
|
|
9
|
+
interface FindingEvidence {
|
|
10
|
+
file?: string;
|
|
11
|
+
line?: number | null;
|
|
12
|
+
sample?: string;
|
|
13
|
+
match_count?: number;
|
|
14
|
+
tool_name?: string;
|
|
15
|
+
params_preview?: string;
|
|
16
|
+
layer?: number;
|
|
17
|
+
layer_name?: string;
|
|
18
|
+
owasp_asi?: string[];
|
|
19
|
+
protocol_surface?: string[];
|
|
20
|
+
}
|
|
21
|
+
interface Finding {
|
|
22
|
+
schema_version?: string;
|
|
23
|
+
source?: "static" | "runtime";
|
|
24
|
+
id: string;
|
|
25
|
+
rule_id?: string;
|
|
26
|
+
cat?: string;
|
|
27
|
+
category: string;
|
|
28
|
+
severity: Severity;
|
|
29
|
+
desc?: string;
|
|
30
|
+
description: string;
|
|
31
|
+
file?: string;
|
|
32
|
+
line?: number | null;
|
|
33
|
+
matchCount?: number;
|
|
34
|
+
sample?: string;
|
|
35
|
+
rationale: string;
|
|
36
|
+
preconditions: string;
|
|
37
|
+
remediation_hint: string;
|
|
38
|
+
false_positive_scenarios: string[];
|
|
39
|
+
validation_state: string;
|
|
40
|
+
validation_status: string;
|
|
41
|
+
confidence: number;
|
|
42
|
+
attack_chain_id: string | null;
|
|
43
|
+
evidence: FindingEvidence;
|
|
44
|
+
evidence_spans: EvidenceSpan[];
|
|
45
|
+
layer?: number;
|
|
46
|
+
layer_name?: string;
|
|
47
|
+
owasp_asi?: string[];
|
|
48
|
+
protocol_surface?: string[];
|
|
49
|
+
action?: RuntimeAction;
|
|
50
|
+
}
|
|
51
|
+
interface SkillFindingResult {
|
|
52
|
+
skill: string;
|
|
53
|
+
risk: number;
|
|
54
|
+
verdict: string;
|
|
55
|
+
findings: Finding[];
|
|
56
|
+
}
|
|
57
|
+
interface ThresholdBand {
|
|
58
|
+
suspicious: number;
|
|
59
|
+
malicious: number;
|
|
60
|
+
}
|
|
61
|
+
interface ScanStats {
|
|
62
|
+
scanned: number;
|
|
63
|
+
clean: number;
|
|
64
|
+
low: number;
|
|
65
|
+
suspicious: number;
|
|
66
|
+
malicious: number;
|
|
67
|
+
}
|
|
68
|
+
interface Recommendation {
|
|
69
|
+
skill: string;
|
|
70
|
+
actions: string[];
|
|
71
|
+
}
|
|
72
|
+
interface ScanReport {
|
|
73
|
+
schema_version: string;
|
|
74
|
+
timestamp: string;
|
|
75
|
+
scanner: string;
|
|
76
|
+
finding_schema_version: string;
|
|
77
|
+
mode: "normal" | "strict";
|
|
78
|
+
compliance_mode?: "owasp-asi" | null;
|
|
79
|
+
stats: ScanStats;
|
|
80
|
+
thresholds: ThresholdBand;
|
|
81
|
+
findings: SkillFindingResult[];
|
|
82
|
+
recommendations: Recommendation[];
|
|
83
|
+
layer_summary?: Array<Record<string, unknown>>;
|
|
84
|
+
owasp_asi_coverage?: Array<Record<string, unknown>>;
|
|
85
|
+
threat_model?: Record<string, unknown>;
|
|
86
|
+
iocVersion: string;
|
|
87
|
+
}
|
|
88
|
+
interface TextScanResult {
|
|
89
|
+
safe: boolean;
|
|
90
|
+
risk: number;
|
|
91
|
+
detections: Finding[];
|
|
92
|
+
}
|
|
93
|
+
interface ScannerOptions {
|
|
94
|
+
verbose?: boolean;
|
|
95
|
+
selfExclude?: boolean;
|
|
96
|
+
strict?: boolean;
|
|
97
|
+
summaryOnly?: boolean;
|
|
98
|
+
quiet?: boolean;
|
|
99
|
+
checkDeps?: boolean;
|
|
100
|
+
soulLock?: boolean;
|
|
101
|
+
plugins?: string[];
|
|
102
|
+
rulesFile?: string;
|
|
103
|
+
compliance?: "owasp-asi";
|
|
104
|
+
}
|
|
105
|
+
interface CustomRule {
|
|
106
|
+
id: string;
|
|
107
|
+
cat: string;
|
|
108
|
+
regex: RegExp;
|
|
109
|
+
severity: Severity;
|
|
110
|
+
desc: string;
|
|
111
|
+
codeOnly?: boolean;
|
|
112
|
+
docOnly?: boolean;
|
|
113
|
+
all?: boolean;
|
|
114
|
+
soulLock?: boolean;
|
|
115
|
+
}
|
|
116
|
+
interface PluginConfig {
|
|
117
|
+
mode?: GuardMode;
|
|
118
|
+
auditLog?: boolean;
|
|
119
|
+
customRules?: string;
|
|
120
|
+
}
|
|
121
|
+
interface RuntimeDecision {
|
|
122
|
+
blocked: boolean;
|
|
123
|
+
blockReason: string | null;
|
|
124
|
+
detections: Finding[];
|
|
125
|
+
mode: GuardMode;
|
|
126
|
+
toolName?: string;
|
|
127
|
+
matchedPolicyId?: string | null;
|
|
128
|
+
policyRationale?: string | null;
|
|
129
|
+
riskAmplificationReasons?: string[];
|
|
130
|
+
remediationSuggestion?: string | null;
|
|
131
|
+
policyDecision?: RuntimePolicyDecision | null;
|
|
132
|
+
}
|
|
133
|
+
interface McpRequest {
|
|
134
|
+
method: string;
|
|
135
|
+
params?: Record<string, unknown>;
|
|
136
|
+
id?: string | number | null;
|
|
137
|
+
}
|
|
138
|
+
interface SarifReport {
|
|
139
|
+
version: string;
|
|
140
|
+
$schema?: string;
|
|
141
|
+
runs: Array<Record<string, unknown>>;
|
|
142
|
+
}
|
|
143
|
+
interface CapabilityMetrics {
|
|
144
|
+
static_pattern_count: number;
|
|
145
|
+
runtime_check_count?: number;
|
|
146
|
+
threat_category_count: number;
|
|
147
|
+
runtime_layer_count?: number;
|
|
148
|
+
runtime_layers?: number;
|
|
149
|
+
benchmark_corpus_version?: string;
|
|
150
|
+
explainability_completeness_rate?: number;
|
|
151
|
+
runtime_check_latency_budget_ms?: number;
|
|
152
|
+
quality_targets?: QualityTargets;
|
|
153
|
+
[key: string]: unknown;
|
|
154
|
+
}
|
|
155
|
+
interface RuntimeCheckStats {
|
|
156
|
+
total: number;
|
|
157
|
+
byLayer: Record<number, number>;
|
|
158
|
+
bySeverity: Partial<Record<Severity, number>>;
|
|
159
|
+
}
|
|
160
|
+
interface QualityTargets {
|
|
161
|
+
precision_min: number;
|
|
162
|
+
recall_min: number;
|
|
163
|
+
false_positive_rate_max: number;
|
|
164
|
+
false_negative_rate_max: number;
|
|
165
|
+
explainability_completeness_rate_min: number;
|
|
166
|
+
runtime_check_latency_budget_ms: number;
|
|
167
|
+
false_positive_budget_by_category: Record<string, number>;
|
|
168
|
+
}
|
|
169
|
+
interface RuntimePolicyContract {
|
|
170
|
+
id?: string;
|
|
171
|
+
allowed_tools?: string[];
|
|
172
|
+
blocked_tools?: string[];
|
|
173
|
+
max_network_scope?: "none" | "internal-only" | "external-ok";
|
|
174
|
+
secret_bearing_context?: boolean;
|
|
175
|
+
memory_write_permission?: boolean;
|
|
176
|
+
}
|
|
177
|
+
interface RuntimePolicyDecision {
|
|
178
|
+
action: "allow" | "block";
|
|
179
|
+
reason: string;
|
|
180
|
+
policyId: string;
|
|
181
|
+
amplificationReasons: string[];
|
|
182
|
+
remediationSuggestion: string;
|
|
183
|
+
}
|
|
184
|
+
interface ThreatModel {
|
|
185
|
+
timestamp: string;
|
|
186
|
+
surface: Record<string, boolean>;
|
|
187
|
+
summary: string;
|
|
188
|
+
owasp_asi?: string[];
|
|
189
|
+
layer_summary?: Array<Record<string, unknown>>;
|
|
190
|
+
protocol_surfaces?: string[];
|
|
191
|
+
}
|
|
192
|
+
interface GuardScannerInstance {
|
|
193
|
+
verbose: boolean;
|
|
194
|
+
strict: boolean;
|
|
195
|
+
summaryOnly: boolean;
|
|
196
|
+
quiet: boolean;
|
|
197
|
+
checkDeps: boolean;
|
|
198
|
+
soulLock: boolean;
|
|
199
|
+
thresholds: ThresholdBand;
|
|
200
|
+
findings: SkillFindingResult[];
|
|
201
|
+
stats: ScanStats;
|
|
202
|
+
scanText(text: string): TextScanResult;
|
|
203
|
+
scanDirectory(dir: string): SkillFindingResult[];
|
|
204
|
+
scanTarget(targetPath: string): ScanReport;
|
|
205
|
+
toJSON(): ScanReport;
|
|
206
|
+
toSARIF(scanDir: string): SarifReport;
|
|
207
|
+
toHTML(): string;
|
|
208
|
+
generateThreatModel(findings: Finding[]): ThreatModel;
|
|
209
|
+
}
|
|
210
|
+
interface GuardScannerConstructor {
|
|
211
|
+
new (options?: ScannerOptions): GuardScannerInstance;
|
|
212
|
+
}
|
|
213
|
+
type ScanResult = SkillFindingResult;
|
|
214
|
+
|
|
215
|
+
export type { CapabilityMetrics, CustomRule, EvidenceSpan, Finding, FindingEvidence, GuardMode, GuardScannerConstructor, GuardScannerInstance, McpRequest, PluginConfig, QualityTargets, Recommendation, RuntimeAction, RuntimeCheckStats, RuntimeDecision, RuntimePolicyContract, RuntimePolicyDecision, SarifReport, ScanReport, ScanResult, ScanStats, ScannerOptions, Severity, SkillFindingResult, TextScanResult, ThreatModel, ThresholdBand };
|
package/dist/types.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Evidence-Driven Metrics
|
|
2
|
+
|
|
3
|
+
guard-scanner uses a **single source of truth (SSoT)** architecture for all public metrics. This ensures that numbers in README, documentation, and tests are always in sync with the implementation.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────┐
|
|
9
|
+
│ Source Code (patterns.js, etc.) │
|
|
10
|
+
└──────────────┬──────────────────────┘
|
|
11
|
+
│
|
|
12
|
+
▼
|
|
13
|
+
┌─────────────────────────────────────┐
|
|
14
|
+
│ generate-capabilities.js │
|
|
15
|
+
│ Generates: docs/spec/capabilities.json
|
|
16
|
+
└──────────────┬──────────────────────┘
|
|
17
|
+
│
|
|
18
|
+
▼
|
|
19
|
+
┌─────────────────────────────────────┐
|
|
20
|
+
│ capabilities.json (SSoT) │
|
|
21
|
+
│ - static_pattern_count: 352 │
|
|
22
|
+
│ - threat_category_count: 32 │
|
|
23
|
+
│ - runtime_check_count: 26 │
|
|
24
|
+
│ - mcp_tools: [...] │
|
|
25
|
+
└──────┬───────────────────────┬──────┘
|
|
26
|
+
│ │
|
|
27
|
+
▼ ▼
|
|
28
|
+
┌──────────────┐ ┌────────────────┐
|
|
29
|
+
│ generate- │ │ verify- │
|
|
30
|
+
│ readme- │ │ capabilities.js│
|
|
31
|
+
│ metrics.js │ │ (CI check) │
|
|
32
|
+
└──────┬───────┘ └────────────────┘
|
|
33
|
+
│
|
|
34
|
+
▼
|
|
35
|
+
┌─────────────────────────────────────┐
|
|
36
|
+
│ README.md │
|
|
37
|
+
│ (Auto-updated metrics) │
|
|
38
|
+
└─────────────────────────────────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Scripts
|
|
42
|
+
|
|
43
|
+
### 1. `generate-capabilities.js`
|
|
44
|
+
|
|
45
|
+
**Purpose:** Generate `docs/spec/capabilities.json` from source code.
|
|
46
|
+
|
|
47
|
+
**Runs:**
|
|
48
|
+
- Counts patterns from `src/patterns.js`
|
|
49
|
+
- Counts runtime checks from `src/runtime-guard.js`
|
|
50
|
+
- Lists MCP tools from `src/mcp-server.js`
|
|
51
|
+
- Reads versions from `package.json` and `openclaw.plugin.json`
|
|
52
|
+
|
|
53
|
+
**Usage:**
|
|
54
|
+
```bash
|
|
55
|
+
node scripts/generate-capabilities.js
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Output:** `docs/spec/capabilities.json`
|
|
59
|
+
|
|
60
|
+
### 2. `generate-readme-metrics.js`
|
|
61
|
+
|
|
62
|
+
**Purpose:** Inject metrics from `capabilities.json` into `README.md`.
|
|
63
|
+
|
|
64
|
+
**Updates:**
|
|
65
|
+
- Header metrics line (categories, patterns, checks)
|
|
66
|
+
- Dependency badge
|
|
67
|
+
- Capability table entries
|
|
68
|
+
- MCP tool descriptions
|
|
69
|
+
|
|
70
|
+
**Usage:**
|
|
71
|
+
```bash
|
|
72
|
+
# Update README
|
|
73
|
+
node scripts/generate-readme-metrics.js
|
|
74
|
+
|
|
75
|
+
# CI mode: fail if drift detected
|
|
76
|
+
node scripts/generate-readme-metrics.js --check
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 3. `generate-readme-stats.js`
|
|
80
|
+
|
|
81
|
+
**Purpose:** Inject test counts from `npm test` output into README.
|
|
82
|
+
|
|
83
|
+
**Updates:**
|
|
84
|
+
- Test badge: `tests-336%20passed`
|
|
85
|
+
- Test results block
|
|
86
|
+
|
|
87
|
+
**Usage:**
|
|
88
|
+
```bash
|
|
89
|
+
# Update README
|
|
90
|
+
node scripts/generate-readme-stats.js
|
|
91
|
+
|
|
92
|
+
# CI mode: fail if drift detected
|
|
93
|
+
node scripts/generate-readme-stats.js --check
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 4. `verify-capabilities.js`
|
|
97
|
+
|
|
98
|
+
**Purpose:** Verify all documentation matches `capabilities.json`.
|
|
99
|
+
|
|
100
|
+
**Checks:**
|
|
101
|
+
- README.md metrics
|
|
102
|
+
- README_ja.md metrics
|
|
103
|
+
- SKILL.md metrics
|
|
104
|
+
- package.json version
|
|
105
|
+
- openclaw.plugin.json version
|
|
106
|
+
- Test file count
|
|
107
|
+
|
|
108
|
+
**Usage:**
|
|
109
|
+
```bash
|
|
110
|
+
node scripts/verify-capabilities.js
|
|
111
|
+
# Exits 1 if any drift detected
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## CI Integration
|
|
115
|
+
|
|
116
|
+
The CI workflow enforces zero-tolerance for drift:
|
|
117
|
+
|
|
118
|
+
```yaml
|
|
119
|
+
# .github/workflows/ci.yml
|
|
120
|
+
- name: Generate capabilities manifest
|
|
121
|
+
run: node scripts/generate-capabilities.js
|
|
122
|
+
|
|
123
|
+
- name: Check README metrics drift
|
|
124
|
+
run: |
|
|
125
|
+
node scripts/generate-readme-metrics.js --check
|
|
126
|
+
node scripts/generate-readme-stats.js --check
|
|
127
|
+
|
|
128
|
+
- name: Verify all capability claims
|
|
129
|
+
run: node scripts/verify-capabilities.js
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Local Development
|
|
133
|
+
|
|
134
|
+
**Sync all README metrics:**
|
|
135
|
+
```bash
|
|
136
|
+
npm run sync:readme
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This runs:
|
|
140
|
+
1. `generate-capabilities.js` (update SSoT)
|
|
141
|
+
2. `generate-readme-metrics.js` (update metrics)
|
|
142
|
+
3. `generate-readme-stats.js` (update test counts)
|
|
143
|
+
|
|
144
|
+
## Adding New Metrics
|
|
145
|
+
|
|
146
|
+
1. **Add to source code:** Update `patterns.js`, `runtime-guard.js`, etc.
|
|
147
|
+
2. **Update generator:** Edit `generate-capabilities.js` to extract new metric
|
|
148
|
+
3. **Update README generator:** Edit `generate-readme-metrics.js` to inject into README
|
|
149
|
+
4. **Update verifier:** Edit `verify-capabilities.js` to check for drift
|
|
150
|
+
5. **Run sync:** `npm run sync:readme`
|
|
151
|
+
6. **Commit changes:** Include updated `capabilities.json` and `README.md`
|
|
152
|
+
|
|
153
|
+
## Philosophy
|
|
154
|
+
|
|
155
|
+
**Why evidence-driven?**
|
|
156
|
+
|
|
157
|
+
- **Trust:** Users can verify claims match implementation
|
|
158
|
+
- **Marketing-first avoidance:** Numbers come from code, not marketing
|
|
159
|
+
- **Drift prevention:** CI blocks PRs with mismatched numbers
|
|
160
|
+
- **Single source of truth:** One canonical source (`capabilities.json`)
|
|
161
|
+
- **Audit trail:** All changes go through generators
|
|
162
|
+
|
|
163
|
+
**Zero tolerance for hardcoded numbers in public docs.**
|
|
164
|
+
|
|
165
|
+
## MCP Integration
|
|
166
|
+
|
|
167
|
+
The `get_stats` MCP tool reads from `capabilities.json`:
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
function handleGetStats() {
|
|
171
|
+
const runtimeStats = getCheckStats();
|
|
172
|
+
return successResult(
|
|
173
|
+
`🛡️ guard-scanner v${VERSION}\n\n` +
|
|
174
|
+
`Static Analysis:\n` +
|
|
175
|
+
` • ${STATIC_SUMMARY}\n` + // from capabilities.json
|
|
176
|
+
` • ${runtimeStats.total} checks across ${Object.keys(runtimeStats.byLayer).length} layers\n` +
|
|
177
|
+
// ...
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
This ensures MCP clients always get accurate, up-to-date metrics.
|
package/docs/banner.png
CHANGED
|
Binary file
|