Skip to content

Commit ee6aab3

Browse files
committed
feat(cli): 本地 web 视图 --open / --serve (v0.6.8)
- scan --open: 扫完在浏览器打开 HTML 报告(写临时目录) - scan --serve [port]: 本地 http 服务(仅 127.0.0.1)提供报告并自动打开浏览器 - 坚持数据不出本机:不做云端上传扫描,只本地查看 - 真实第三方狗粮:chalk(非AI) 0 误报、openai-quickstart-python 正确检出
1 parent 11a0a60 commit ee6aab3

4 files changed

Lines changed: 67 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/),
66
and this project adheres to [Semantic Versioning](https://semver.org/).
77

8+
## [0.6.8] - 2026-06-20
9+
10+
### Added — 本地 web 视图(方便看,数据不出本机)
11+
- **`npx shellward scan --open`**:扫描后把 HTML 合规报告写入临时目录并在默认浏览器打开
12+
- **`npx shellward scan --serve [port]`**:本地零依赖 HTTP 服务(默认 7777,仅监听 127.0.0.1)提供报告,自动打开浏览器
13+
- 坚持"数据不出本机"原则:**不做云端上传扫描**,只在本地起服务/打开文件查看
14+
- 真实第三方项目狗粮验证:非 AI 库(chalk)0 误报、Python AI 项目(openai-quickstart)正确检出依赖
15+
816
## [0.6.7] - 2026-06-20
917

1018
### Changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ npx shellward scan
3737
合规得分: 63/100 [C]
3838
```
3939

40+
想在浏览器里看?`npx shellward scan --open`(扫完直接打开报告)或 `--serve`(本地 http://localhost 提供报告)——**数据全程不出本机**
41+
4042
`--json` 供 CI · `--ci` 发现 critical 时让构建失败 · `--html report.html` 导出可打印成 PDF 的报告(备案/审计存档)· 也可作 [GitHub Action](#github-action-pr-compliance-gate) 接入 PR 门禁。
4143

4244
> 检测重点:**境外大模型端点与 SDK 依赖(数据出境——中国独有、英文工具没有的概念)**、硬编码密钥、文件中的中文 PII、`.env` 暴露。扫到境外模型(如 `openai` 依赖)时,**直接给出境内合规替代**(通义千问 / DeepSeek / Kimi / 智谱)及其 OpenAI 兼容 `base_url`——多数迁移只需改一个 `base_url`

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "shellward",
3-
"version": "0.6.7",
3+
"version": "0.6.8",
44
"mcpName": "io.github.jnMetaCode/shellward",
55
"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.",
66
"keywords": [

src/cli.ts

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
//
1010
// 设计目标:30 秒、零配置、出一张可截图的「你的项目」合规风险报告。
1111

12-
import { resolve } from 'path'
12+
import { resolve, join } from 'path'
1313
import { writeFileSync } from 'fs'
14+
import { tmpdir } from 'os'
15+
import { createServer } from 'http'
16+
import { spawn } from 'child_process'
1417
import { ShellWard } from './core/engine.js'
1518
import { runProjectComplianceAudit } from './compliance/audit.js'
1619
import { renderComplianceReport, renderProjectFindings } from './compliance/report.js'
@@ -48,6 +51,8 @@ function runScan(args: string[]) {
4851
const ci = args.includes('--ci')
4952
const outPath = flagValue(args, '--out')
5053
const htmlPath = flagValue(args, '--html')
54+
const open = args.includes('--open')
55+
const serve = args.includes('--serve')
5156
const dirArg = args.find(a => !a.startsWith('-'))
5257
const root = resolve(dirArg || process.cwd())
5358

@@ -62,6 +67,39 @@ function runScan(args: string[]) {
6267

6368
const { report, scan } = runProjectComplianceAudit(guard.config, root)
6469

70+
// ===== 本地 web 视图(方便看;数据全程不出本机)=====
71+
if (serve) {
72+
const html = renderHtmlReport(report, scan, locale, { root })
73+
const port = Number(flagValue(args, '--serve') || flagValue(args, '--port')) || 7777
74+
const server = createServer((_req, res) => {
75+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })
76+
res.end(html)
77+
})
78+
server.on('error', (e: any) => {
79+
console.error(zh ? `无法启动本地服务: ${e?.message}` : `Failed to start server: ${e?.message}`)
80+
process.exit(1)
81+
})
82+
server.listen(port, '127.0.0.1', () => {
83+
const url = `http://localhost:${port}`
84+
process.stdout.write(zh
85+
? `🌐 本地合规报告: ${url} (得分 ${report.score}/100 [${report.grade}],Ctrl+C 退出;数据不出本机)\n`
86+
: `🌐 Local compliance report: ${url} (score ${report.score}/100 [${report.grade}]; Ctrl+C to stop; nothing leaves your machine)\n`)
87+
openBrowser(url)
88+
})
89+
return
90+
}
91+
92+
if (open) {
93+
const html = renderHtmlReport(report, scan, locale, { root })
94+
const file = join(tmpdir(), `shellward-report-${report.score}-${report.grade}.html`)
95+
writeFileSync(file, html, 'utf-8')
96+
process.stdout.write(zh
97+
? `🌐 已在浏览器打开合规报告: ${file} (得分 ${report.score}/100 [${report.grade}];数据不出本机)\n`
98+
: `🌐 Opened compliance report in browser: ${file} (score ${report.score}/100 [${report.grade}])\n`)
99+
openBrowser(file)
100+
return
101+
}
102+
65103
if (json) {
66104
process.stdout.write(JSON.stringify({
67105
root,
@@ -117,6 +155,19 @@ function runScan(args: string[]) {
117155
}
118156
}
119157

158+
/** 跨平台在默认浏览器打开 URL 或本地文件(失败静默,不影响主流程) */
159+
function openBrowser(target: string): void {
160+
const cmd = process.platform === 'darwin' ? 'open'
161+
: process.platform === 'win32' ? 'cmd'
162+
: 'xdg-open'
163+
const cmdArgs = process.platform === 'win32' ? ['/c', 'start', '', target] : [target]
164+
try {
165+
const child = spawn(cmd, cmdArgs, { stdio: 'ignore', detached: true })
166+
child.on('error', () => {})
167+
child.unref()
168+
} catch { /* 打开失败不影响 */ }
169+
}
170+
120171
/** 取 `--flag value` 或 `--flag=value` 的值 */
121172
function flagValue(args: string[], flag: string): string | undefined {
122173
const i = args.indexOf(flag)
@@ -136,6 +187,8 @@ Usage:
136187
shellward scan --ci Exit non-zero if critical findings
137188
shellward scan --out f Export the full report to a Markdown file
138189
shellward scan --html f Export a self-contained HTML report (print to PDF)
190+
shellward scan --open Scan and open the report in your browser (local)
191+
shellward scan --serve Scan and serve the report at http://localhost (local)
139192
shellward mcp Start MCP server (stdio)
140193
shellward --help
141194
@@ -150,6 +203,8 @@ PII in files, .env permissions. Maps to CSL / PIPL / MLPS / cross-border / label
150203
shellward scan --ci 有 critical 发现时非零退出
151204
shellward scan --out 文件 导出完整报告为 Markdown(合规存档)
152205
shellward scan --html 文件 导出自包含 HTML 报告(浏览器可打印成 PDF)
206+
shellward scan --open 扫描并在浏览器打开报告(本地,方便看)
207+
shellward scan --serve 扫描并在 http://localhost 提供报告(本地服务)
153208
shellward mcp 启动 MCP 服务器(stdio)
154209
shellward --help
155210

0 commit comments

Comments
 (0)