shellward 0.7.10 → 0.7.11

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 CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/shellward?color=cb0000&label=npm)](https://www.npmjs.com/package/shellward)
10
10
  [![license](https://img.shields.io/badge/license-Apache--2.0-blue)](./LICENSE)
11
- [![tests](https://img.shields.io/badge/tests-302%20passing-brightgreen)](#performance)
11
+ [![tests](https://img.shields.io/badge/tests-303%20passing-brightgreen)](#performance)
12
12
  [![deps](https://img.shields.io/badge/dependencies-0-brightgreen)](#performance)
13
13
 
14
14
  **🌐 官网: https://jnmetacode.github.io/shellward/**
@@ -121,17 +121,52 @@ export function runProjectComplianceAudit(config, root) {
121
121
  }
122
122
  // CLI 静态扫描:未部署运行时 → 能力/审计类不虚报"已启用",只如实评估项目证据
123
123
  const report = runComplianceAudit(config, env, { deployed: false });
124
+ // 「敏感个人信息识别」这条静态扫描确实做得到 —— 直接连到扫描结果,不再标"待核验"
125
+ const piiCount = scan.findings.filter(f => f.kind === 'pii').length;
126
+ const spi = report.results.find(r => r.control.id === 'pipl-spi-detect');
127
+ if (spi) {
128
+ if (piiCount > 0) {
129
+ spi.status = 'fail';
130
+ spi.detail_zh = `扫描在项目文件中发现 ${piiCount} 处个人信息暴露(见上方「项目实测风险」)— 需评估最小必要并脱敏`;
131
+ spi.detail_en = `Scan found ${piiCount} PII exposure(s) in files — assess minimization & de-identify`;
132
+ }
133
+ else {
134
+ spi.status = 'pass';
135
+ spi.detail_zh = '已扫描项目文件,未发现明文个人信息暴露(运行时 PII 处理建议仍接入 ShellWard)';
136
+ spi.detail_en = 'Scanned files; no plaintext PII exposure found';
137
+ }
138
+ }
139
+ // override 改了状态 → 重算计数与控制项得分
140
+ recount(report);
141
+ const baseScore = computeScore(report.results);
124
142
  // 发现驱动评分:项目实测风险按严重度扣分(封顶 40),使分数反映"你的真实风险"
125
143
  const penalty = computeProjectPenalty(scan);
126
- if (penalty > 0) {
127
- report.score = Math.max(0, report.score - penalty);
128
- report.grade = gradeOf(report.score);
144
+ report.score = Math.max(0, baseScore - penalty);
145
+ report.grade = gradeOf(report.score);
146
+ if (penalty > 0)
129
147
  report.projectPenalty = penalty;
130
- }
131
148
  report.staticScan = true;
132
149
  report.filesScanned = scan.filesScanned;
133
150
  return { report, scan };
134
151
  }
152
+ /** 重新统计 pass/warn/fail/manual 计数(控制项状态被覆盖后调用) */
153
+ function recount(report) {
154
+ let passed = 0, warned = 0, failed = 0, manual = 0;
155
+ for (const r of report.results) {
156
+ if (r.status === 'pass')
157
+ passed++;
158
+ else if (r.status === 'warn')
159
+ warned++;
160
+ else if (r.status === 'fail')
161
+ failed++;
162
+ else
163
+ manual++;
164
+ }
165
+ report.passed = passed;
166
+ report.warned = warned;
167
+ report.failed = failed;
168
+ report.manual = manual;
169
+ }
135
170
  const FINDING_PENALTY = { critical: 8, high: 4, medium: 1 };
136
171
  const MAX_PROJECT_PENALTY = 40;
137
172
  function computeProjectPenalty(scan) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shellward",
3
- "version": "0.7.10",
3
+ "version": "0.7.11",
4
4
  "mcpName": "io.github.jnMetaCode/shellward",
5
5
  "description": "AI agent security & MCP security middleware — prompt injection detection, AI firewall, runtime guardrails & data-loss prevention for LLM tool calls. 8-layer defense against data exfiltration & dangerous commands. Zero dependencies. SDK + OpenClaw plugin. Supports LangChain, AutoGPT, Claude Code, Cursor, OpenAI Agents, Hermes Agent.",
6
6
  "keywords": [
@@ -189,19 +189,48 @@ export function runProjectComplianceAudit(config: ShellWardConfig, root: string)
189
189
  // CLI 静态扫描:未部署运行时 → 能力/审计类不虚报"已启用",只如实评估项目证据
190
190
  const report = runComplianceAudit(config, env, { deployed: false })
191
191
 
192
+ // 「敏感个人信息识别」这条静态扫描确实做得到 —— 直接连到扫描结果,不再标"待核验"
193
+ const piiCount = scan.findings.filter(f => f.kind === 'pii').length
194
+ const spi = report.results.find(r => r.control.id === 'pipl-spi-detect')
195
+ if (spi) {
196
+ if (piiCount > 0) {
197
+ spi.status = 'fail'
198
+ spi.detail_zh = `扫描在项目文件中发现 ${piiCount} 处个人信息暴露(见上方「项目实测风险」)— 需评估最小必要并脱敏`
199
+ spi.detail_en = `Scan found ${piiCount} PII exposure(s) in files — assess minimization & de-identify`
200
+ } else {
201
+ spi.status = 'pass'
202
+ spi.detail_zh = '已扫描项目文件,未发现明文个人信息暴露(运行时 PII 处理建议仍接入 ShellWard)'
203
+ spi.detail_en = 'Scanned files; no plaintext PII exposure found'
204
+ }
205
+ }
206
+
207
+ // override 改了状态 → 重算计数与控制项得分
208
+ recount(report)
209
+ const baseScore = computeScore(report.results)
210
+
192
211
  // 发现驱动评分:项目实测风险按严重度扣分(封顶 40),使分数反映"你的真实风险"
193
212
  const penalty = computeProjectPenalty(scan)
194
- if (penalty > 0) {
195
- report.score = Math.max(0, report.score - penalty)
196
- report.grade = gradeOf(report.score)
197
- report.projectPenalty = penalty
198
- }
213
+ report.score = Math.max(0, baseScore - penalty)
214
+ report.grade = gradeOf(report.score)
215
+ if (penalty > 0) report.projectPenalty = penalty
199
216
  report.staticScan = true
200
217
  report.filesScanned = scan.filesScanned
201
218
 
202
219
  return { report, scan }
203
220
  }
204
221
 
222
+ /** 重新统计 pass/warn/fail/manual 计数(控制项状态被覆盖后调用) */
223
+ function recount(report: ComplianceReport): void {
224
+ let passed = 0, warned = 0, failed = 0, manual = 0
225
+ for (const r of report.results) {
226
+ if (r.status === 'pass') passed++
227
+ else if (r.status === 'warn') warned++
228
+ else if (r.status === 'fail') failed++
229
+ else manual++
230
+ }
231
+ report.passed = passed; report.warned = warned; report.failed = failed; report.manual = manual
232
+ }
233
+
205
234
  const FINDING_PENALTY = { critical: 8, high: 4, medium: 1 } as const
206
235
  const MAX_PROJECT_PENALTY = 40
207
236