@autobest-ui/agent 1.0.27 → 1.0.28
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/mcp/trace-mcp-recorder/README.md +1 -1
- package/mcp/trace-mcp-recorder/index.js +99 -0
- package/mcp/trace-mcp-recorder/index.test.js +3 -0
- package/package.json +1 -1
- package/skills/common/code-quality/SKILL.md +78 -128
- package/skills/common/code-quality/agents/openai.yaml +1 -1
- package/skills/common/code-quality/references/implementation-playbook.md +81 -0
- package/skills/common/code-quality/references/report-format.md +87 -93
- package/skills/common/trace-recorder/SKILL.md +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# trace-mcp-recorder
|
|
2
2
|
|
|
3
|
-
`trace-mcp-recorder` 是基于 `@modelcontextprotocol/sdk` 和 `StdioServerTransport` 的 Node.js MCP Server。它打开非无头 Chromium,PC 端默认 viewport 为 1400×740,并在页面左下角显示半透明的可拖拽 2×2
|
|
3
|
+
`trace-mcp-recorder` 是基于 `@modelcontextprotocol/sdk` 和 `StdioServerTransport` 的 Node.js MCP Server。它打开非无头 Chromium,PC 端默认 viewport 为 1400×740,并在页面左下角显示半透明的可拖拽 2×2 控制栏:第一行是“开始录制”“停止录制”,第二行是“切换移动端”“截图”,下方提供“画笔”“撤销”“清空”标注工具。四个主按钮始终显示,不伸缩,统一高度 32px;拖动控制栏空白区域即可移动位置,按钮点击仍只触发对应功能。画笔使用独立 SVG 路径覆盖层,开启后可用鼠标或触摸标注页面;点击“退出画笔”会立即关闭并清空已有标注,避免后续页面操作继续带着旧标注,截图时会连同页面一起保存。默认是 PC 端,也可切换为 iPhone 14 Pro Max 移动端模拟。页面先正常打开并等待,点击开始后先启动 Trace,临时禁用 Chromium 缓存并刷新一次当前 SPA 页面,等待 DOM、CSS、字体和图片稳定后恢复缓存,再进入正式录制;普通点击、输入和滚动不会生成自定义 Action,只有点击“截图”才会把当前渲染画面作为 Trace Group 写入官方 Viewer,截图时控制栏会临时隐藏。空闲超过 2 分钟自动结束,然后上传原生 `trace.zip` 和浏览器元数据,并返回私有后端的 Trace Viewer 链接。同一进程同一时间只允许一个录制任务。
|
|
4
4
|
|
|
5
5
|
## 安装与启动
|
|
6
6
|
|
|
@@ -177,21 +177,116 @@ function createRecorderPageScript() {
|
|
|
177
177
|
.stop { background: rgba(220, 38, 38, .82); }
|
|
178
178
|
.device { background: rgba(37, 99, 235, .82); }
|
|
179
179
|
.screenshot { background: rgba(234, 88, 12, .82); }
|
|
180
|
+
.annotation-actions {
|
|
181
|
+
grid-column: 1 / -1;
|
|
182
|
+
display: grid;
|
|
183
|
+
grid-template-columns: repeat(3, 1fr);
|
|
184
|
+
gap: 8px;
|
|
185
|
+
}
|
|
186
|
+
.annotation-actions button { min-width: 0; }
|
|
187
|
+
.pen { background: rgba(147, 51, 234, .82); }
|
|
188
|
+
.pen.active { background: rgba(126, 34, 206, .96); }
|
|
189
|
+
.undo, .clear { background: rgba(63, 63, 70, .82); }
|
|
180
190
|
</style>
|
|
181
191
|
<div class="toolbar" role="group" aria-label="Trace 录制控制">
|
|
182
192
|
<button class="start" type="button" data-action="start" data-trace-recorder-control>开始录制</button>
|
|
183
193
|
<button class="stop" type="button" data-action="stop" data-trace-recorder-control>停止录制</button>
|
|
184
194
|
<button class="device" type="button" data-action="toggle-device" data-trace-recorder-control>切换移动端</button>
|
|
185
195
|
<button class="screenshot" type="button" data-action="screenshot" data-trace-recorder-control>截图</button>
|
|
196
|
+
<div class="annotation-actions" role="group" aria-label="页面标注">
|
|
197
|
+
<button class="pen" type="button" data-action="pen" data-trace-recorder-control>画笔</button>
|
|
198
|
+
<button class="undo" type="button" data-action="undo" data-trace-recorder-control>撤销</button>
|
|
199
|
+
<button class="clear" type="button" data-action="clear" data-trace-recorder-control>清空</button>
|
|
200
|
+
</div>
|
|
186
201
|
</div>
|
|
187
202
|
\`;
|
|
203
|
+
const annotation = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
204
|
+
annotation.setAttribute('data-trace-recorder-annotation', '');
|
|
205
|
+
annotation.setAttribute('aria-label', 'Trace 页面标注层');
|
|
206
|
+
Object.assign(annotation.style, {
|
|
207
|
+
position: 'fixed',
|
|
208
|
+
inset: '0',
|
|
209
|
+
width: '100vw',
|
|
210
|
+
height: '100vh',
|
|
211
|
+
zIndex: '2147483646',
|
|
212
|
+
pointerEvents: 'none',
|
|
213
|
+
touchAction: 'none'
|
|
214
|
+
});
|
|
215
|
+
document.documentElement.append(annotation);
|
|
188
216
|
document.documentElement.append(host);
|
|
189
217
|
const toolbar = shadow.querySelector('.toolbar');
|
|
190
218
|
const startButton = shadow.querySelector('[data-action="start"]');
|
|
191
219
|
const screenshotButton = shadow.querySelector('[data-action="screenshot"]');
|
|
192
220
|
const stopButton = shadow.querySelector('[data-action="stop"]');
|
|
193
221
|
const deviceButton = shadow.querySelector('[data-action="toggle-device"]');
|
|
222
|
+
const penButton = shadow.querySelector('[data-action="pen"]');
|
|
223
|
+
const undoButton = shadow.querySelector('[data-action="undo"]');
|
|
224
|
+
const clearButton = shadow.querySelector('[data-action="clear"]');
|
|
194
225
|
let dragState;
|
|
226
|
+
let drawingPath;
|
|
227
|
+
let penEnabled = false;
|
|
228
|
+
let annotationEnabled = false;
|
|
229
|
+
|
|
230
|
+
const annotationPaths = () => Array.from(annotation.querySelectorAll('path'));
|
|
231
|
+
const renderAnnotation = () => {
|
|
232
|
+
const hasPaths = annotationPaths().length > 0;
|
|
233
|
+
penButton.classList.toggle('active', penEnabled);
|
|
234
|
+
penButton.textContent = penEnabled ? '退出画笔' : '画笔';
|
|
235
|
+
penButton.disabled = !annotationEnabled;
|
|
236
|
+
undoButton.disabled = !annotationEnabled || !hasPaths;
|
|
237
|
+
clearButton.disabled = !annotationEnabled || !hasPaths;
|
|
238
|
+
annotation.style.pointerEvents = penEnabled ? 'auto' : 'none';
|
|
239
|
+
};
|
|
240
|
+
annotation.addEventListener('pointerdown', event => {
|
|
241
|
+
if (!penEnabled || event.button !== 0) return;
|
|
242
|
+
drawingPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
243
|
+
drawingPath.setAttribute('d', 'M ' + event.clientX + ' ' + event.clientY);
|
|
244
|
+
drawingPath.setAttribute('fill', 'none');
|
|
245
|
+
drawingPath.setAttribute('stroke', '#ef4444');
|
|
246
|
+
drawingPath.setAttribute('stroke-width', '4');
|
|
247
|
+
drawingPath.setAttribute('stroke-linecap', 'round');
|
|
248
|
+
drawingPath.setAttribute('stroke-linejoin', 'round');
|
|
249
|
+
annotation.append(drawingPath);
|
|
250
|
+
annotation.setPointerCapture?.(event.pointerId);
|
|
251
|
+
renderAnnotation();
|
|
252
|
+
});
|
|
253
|
+
annotation.addEventListener('pointermove', event => {
|
|
254
|
+
if (!drawingPath) return;
|
|
255
|
+
drawingPath.setAttribute('d', drawingPath.getAttribute('d') + ' L ' + event.clientX + ' ' + event.clientY);
|
|
256
|
+
});
|
|
257
|
+
const finishDrawing = event => {
|
|
258
|
+
if (!drawingPath) return;
|
|
259
|
+
drawingPath = undefined;
|
|
260
|
+
annotation.releasePointerCapture?.(event.pointerId);
|
|
261
|
+
renderAnnotation();
|
|
262
|
+
};
|
|
263
|
+
annotation.addEventListener('pointerup', finishDrawing);
|
|
264
|
+
annotation.addEventListener('pointercancel', finishDrawing);
|
|
265
|
+
|
|
266
|
+
penButton.addEventListener('click', event => {
|
|
267
|
+
event.preventDefault();
|
|
268
|
+
event.stopPropagation();
|
|
269
|
+
if (penEnabled) {
|
|
270
|
+
// Leaving annotation mode removes all marks so later page actions
|
|
271
|
+
// cannot accidentally carry an old annotation into a screenshot.
|
|
272
|
+
annotation.replaceChildren();
|
|
273
|
+
drawingPath = undefined;
|
|
274
|
+
}
|
|
275
|
+
penEnabled = !penEnabled;
|
|
276
|
+
renderAnnotation();
|
|
277
|
+
});
|
|
278
|
+
undoButton.addEventListener('click', event => {
|
|
279
|
+
event.preventDefault();
|
|
280
|
+
event.stopPropagation();
|
|
281
|
+
annotationPaths().at(-1)?.remove();
|
|
282
|
+
renderAnnotation();
|
|
283
|
+
});
|
|
284
|
+
clearButton.addEventListener('click', event => {
|
|
285
|
+
event.preventDefault();
|
|
286
|
+
event.stopPropagation();
|
|
287
|
+
annotation.replaceChildren();
|
|
288
|
+
renderAnnotation();
|
|
289
|
+
});
|
|
195
290
|
|
|
196
291
|
toolbar.addEventListener('pointerdown', event => {
|
|
197
292
|
if (event.button !== 0 || event.target.closest('button')) return;
|
|
@@ -216,11 +311,15 @@ function createRecorderPageScript() {
|
|
|
216
311
|
};
|
|
217
312
|
toolbar.addEventListener('pointerup', stopDragging);
|
|
218
313
|
toolbar.addEventListener('pointercancel', stopDragging);
|
|
314
|
+
renderAnnotation();
|
|
219
315
|
|
|
220
316
|
const render = (state, deviceMode = 'desktop') => {
|
|
221
317
|
const recording = state === 'recording';
|
|
222
318
|
const waiting = state === 'waiting_for_start';
|
|
223
319
|
const preparing = state === 'starting';
|
|
320
|
+
annotationEnabled = recording;
|
|
321
|
+
if (!annotationEnabled) penEnabled = false;
|
|
322
|
+
renderAnnotation();
|
|
224
323
|
startButton.disabled = !waiting;
|
|
225
324
|
screenshotButton.disabled = !recording;
|
|
226
325
|
stopButton.disabled = !recording && !waiting;
|
|
@@ -108,6 +108,9 @@ test('page controls start recording, record activity, upload and clean up one se
|
|
|
108
108
|
assert.equal(started.metadata.browserVersion, 'Fixture Chromium 1');
|
|
109
109
|
assert.equal(calls.some(call => call[0] === 'trace-start'), false);
|
|
110
110
|
assert.match(calls.find(call => call[0] === 'init-script')[1].content, /开始录制/);
|
|
111
|
+
assert.match(calls.find(call => call[0] === 'init-script')[1].content, /data-trace-recorder-annotation/);
|
|
112
|
+
assert.match(calls.find(call => call[0] === 'init-script')[1].content, /退出画笔/);
|
|
113
|
+
assert.match(calls.find(call => call[0] === 'init-script')[1].content, /Leaving annotation mode removes all marks/);
|
|
111
114
|
assert.deepEqual(await bindings.__traceRecorderControl({}, 'start'), {
|
|
112
115
|
state: 'starting',
|
|
113
116
|
deviceMode: 'desktop'
|
package/package.json
CHANGED
|
@@ -1,165 +1,115 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: code-quality
|
|
3
|
-
description:
|
|
3
|
+
description: 审计前端与 Node.js 服务的上线安全风险,重点检查生产可达的 XSS、CSP、认证会话、敏感 key、明文传输、导航、第三方集成和服务端注入,并在 `.scratch/code-quality-report.md` 输出带证据的只读 Markdown 报告。用户要求前端安全编码审查、生产漏洞扫描或上线前安全 Review 时使用。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# 前端与 Node.js
|
|
6
|
+
# 前端与 Node.js 安全审计
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## 何时使用此技能
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
- 参与前端安全编码或上线前安全 Review。
|
|
11
|
+
- 需要检查生产可达的客户端漏洞、Node.js 服务风险或敏感信息泄露。
|
|
12
|
+
- 需要检查 XSS、CSP、认证/会话、URL 导航、第三方脚本、API key 或明文传输。
|
|
13
|
+
- 需要基于源码、配置、依赖树和工具输出生成可追溯的安全报告。
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
## 请勿在以下情况下使用此技能
|
|
13
16
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
- CWE-79 XSS、CWE-22/CWE-23 路径穿越、CWE-601 Open Redirect、CWE-200 敏感信息暴露、CWE-312/CWE-319 明文敏感数据、CWE-327/CWE-328 弱密码学、CWE-532 日志中的敏感信息、CWE-798 硬编码凭据、CWE-918 SSRF、CWE-400/CWE-1333 DoS/ReDoS、CWE-94 代码注入。
|
|
18
|
-
- `npm audit`/OSV、Node.js Security Best Practices、供应链安全和 lockfile 完整性。
|
|
17
|
+
- 任务只是普通功能开发、性能优化、视觉调整或一般代码风格 Review。
|
|
18
|
+
- 任务只涉及 local/dev/test 且能证明不会进入生产构建、发布配置或默认上线路径。
|
|
19
|
+
- 用户要求自动修复、升级依赖、轮换密钥、提交代码或执行渗透测试;本 Skill 只读审计并提供建议。
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
## 指示
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
- 明确审计目标、生产入口、边界、可用工具和所需运行条件。
|
|
24
|
+
- 只把上线后可达或会进入发布产物的风险纳入安全结论;local/dev/test-only 问题记录为排除项,不计入风险统计。
|
|
25
|
+
- 按 [implementation-playbook.md](references/implementation-playbook.md) 的固定顺序检查,不用单次 grep 或单次 `npm audit` 代替审计。
|
|
26
|
+
- 应用 OWASP Top 10、OWASP API Security Top 10、OWASP ASVS、CWE、OSV/npm audit 和 Node.js 安全实践;每个结论绑定源码、配置、依赖树或工具证据。
|
|
27
|
+
- 输出唯一项目产物 `.scratch/code-quality-report.md`,格式遵循 [report-format.md](references/report-format.md)。
|
|
28
|
+
- 工具、漏洞数据库、生产入口或关键源码不可用时,报告 `Incomplete`/`Blocked` 和具体原因,不将缺失证据当作通过。
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
- 唯一允许生成的项目产物是 `.scratch/code-quality-report.md`。可以创建 `.scratch`,但不得在其中生成其他文件。
|
|
26
|
-
- 读取源码、manifest、锁文件、配置、Docker/nginx/启动脚本、测试和 CI 文件,以及 Git 元数据;跳过 `node_modules`、构建缓存、二进制和无关的大型产物。
|
|
27
|
-
- 不读取 `.env` 内容、私钥、凭据或 secret store;只记录文件位置、变量名或脱敏类型。
|
|
28
|
-
- 对 `.env`、secret store 和私钥文件只记录存在性、路径和脱敏变量名;不得读取、复制或输出其值。
|
|
29
|
-
- 不修改业务源码、依赖、锁文件、构建配置、测试、Git 历史、远程状态或运行中的业务数据;不安装依赖或改变项目配置。
|
|
30
|
-
- 运行现有只读检查命令前确认命令不会写入项目;命令失败、网络不可达或范围不可读时保留失败证据。
|
|
30
|
+
## 角色
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
你是一名前端与 Node.js 安全审计专家,擅长客户端安全、DOM/XSS 防护、浏览器安全策略、认证会话、敏感数据流、供应链和生产配置风险。你的职责是评估和解释风险,不直接编辑业务代码。
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
## 目的
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
建立稳定、可重复的上线安全检查:
|
|
37
37
|
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
- 所有环境配置入口和环境变量来源;只记录位置和脱敏变量类型,不读取秘密值。
|
|
38
|
+
- 找到真实可达的漏洞和敏感凭据暴露。
|
|
39
|
+
- 证明输入从来源到危险汇点的完整数据流。
|
|
40
|
+
- 区分生产风险、发布风险、开发专用风险和误报。
|
|
41
|
+
- 给出可执行的修改建议、优先级和复测方式。
|
|
42
|
+
- 让同一审计范围的重复执行尽量保持相同顺序、编号和判定标准。
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
## 能力范围
|
|
46
45
|
|
|
47
|
-
###
|
|
46
|
+
### 输出处理和 XSS 防护
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
- 检查 `textContent` 与 `innerHTML`、`outerHTML`、`insertAdjacentHTML`、`dangerouslySetInnerHTML` 的使用上下文。
|
|
49
|
+
- 检查 DOMPurify 或等价 sanitizer、allowlist、HTML/URL/JavaScript 上下文编码。
|
|
50
|
+
- 检查用户生成内容、Markdown、富文本、模板和动态 HTML 是否到达浏览器执行点。
|
|
51
|
+
- 检查 `eval`、`new Function`、动态 script、iframe、object、embed 和 `document.write`。
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
- `npm ls` 或对应 package manager 的实际依赖树。
|
|
53
|
-
- lockfile 完整性和 manifest/lockfile 一致性。
|
|
54
|
-
- direct/transitive dependency 区分、实际安装版本和 workspace 归属。
|
|
55
|
-
- 维护状态、过期版本、危险安装脚本和 postinstall 风险。
|
|
56
|
-
- 构建工具、开发服务器和可暴露服务的攻击面。
|
|
53
|
+
### CSP 和浏览器安全
|
|
57
54
|
|
|
58
|
-
|
|
55
|
+
- 检查 CSP header/meta、nonce、hash、`strict-dynamic`、`unsafe-inline` 和报告收集。
|
|
56
|
+
- 检查 SRI、Trusted Types、Permissions Policy、Referrer-Policy、HSTS、CORP/COEP。
|
|
57
|
+
- 检查点击劫持防护:优先验证服务器 `frame-ancestors`/`X-Frame-Options`;视口或脚本帧检测只能作为辅助信号。
|
|
58
|
+
- 检查 HTTPS 强制、mixed content、安全 Cookie 和安全响应头。
|
|
59
59
|
|
|
60
|
-
###
|
|
60
|
+
### 输入、文件和 CSS
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
- 检查 allowlist 输入验证、schema、URL 协议/域名验证、ReDoS 和请求速率限制。
|
|
63
|
+
- 检查上传类型/大小、服务端验证、解压、临时文件和路径穿越。
|
|
64
|
+
- 检查动态样式、CSS 注入、CSS 自定义属性、CSS-in-JS、第三方 CSS 和样式 CSP。
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
### 导航、认证和会话
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-> base URL
|
|
71
|
-
-> transport
|
|
72
|
-
-> retry/error handler
|
|
73
|
-
-> logger/telemetry
|
|
74
|
-
-> storage/cache/cookie
|
|
75
|
-
-> redirect/navigation
|
|
76
|
-
```
|
|
68
|
+
- 检查开放重定向、`window.open`、`location.*`、深度链接、外部链接的 `noopener/noreferrer` 和路由授权。
|
|
69
|
+
- 强制追踪注册、登录、登出、刷新 token、改密、重置密码、MFA、角色判断和高权限操作。
|
|
70
|
+
- 区分 HTTPS 请求体(通常不是明文漏洞)与 HTTP、明文 WebSocket、mixed content 或降级代理传输。
|
|
71
|
+
- 检查 token 的 HttpOnly/Secure/SameSite Cookie、`localStorage`/`sessionStorage`、过期、重放、跨环境混用和多标签同步。
|
|
77
72
|
|
|
78
|
-
|
|
73
|
+
### 敏感 key、第三方和 Node.js
|
|
79
74
|
|
|
80
|
-
|
|
75
|
+
- 检查 `apiKey`、`api_key`、`OPENAI_API_KEY`、`secretKey`、`clientSecret`、`privateKey` 等字段,以及 OpenAI/AWS/GitHub/Google/Azure/Stripe 等已知凭据格式。
|
|
76
|
+
- 检查 JWT、Bearer/Basic 凭据、PEM 私钥和高熵字符串;普通 `key`、React `key` 和业务索引不能自动判定为漏洞。
|
|
77
|
+
- 检查 CDN/SRI、iframe sandbox、`postMessage` origin、分析/聊天/支付集成和 API key 是否暴露到客户端。
|
|
78
|
+
- 若存在 Node.js 服务,检查鉴权、schema、SSRF、注入、命令执行、原型污染、文件操作、反序列化、WebSocket、DoS、日志和安全 middleware。
|
|
81
79
|
|
|
82
|
-
|
|
80
|
+
## 行为特征
|
|
83
81
|
|
|
84
|
-
|
|
82
|
+
- 先判断生产可达性,再判断漏洞;local/dev/test-only 问题默认排除。
|
|
83
|
+
- 先确认 source-to-sink 数据流,再给严重级别;关键词命中只能产生 `Needs Manual Verification`。
|
|
84
|
+
- 对真实 key 只输出前缀、后缀、长度或 SHA-256 截断指纹,绝不输出完整秘密。
|
|
85
|
+
- 对登录/注册/改密/重置密码分别确认最终 URL、协议、重定向、transport、日志和存储。
|
|
86
|
+
- 使用服务器提供的 frame policy;不把客户端帧检测当成授权边界。
|
|
87
|
+
- 优先推荐成熟 sanitizer、allowlist、标准浏览器安全能力和最小权限设计。
|
|
88
|
+
- 不修改代码、依赖、锁文件、配置、Git 历史或线上数据;只生成报告和修复建议。
|
|
85
89
|
|
|
86
|
-
|
|
87
|
-
- OpenAI、AWS、GitHub、Google、Azure、Stripe 等供应商的已知前缀或结构;例如 `sk-`、`AKIA`、`ASIA`、`ghp_`、`github_pat_`、`AIza`、`xoxb-`、`xoxp-`、`SG.` 等。具体模式必须结合上下文核验,不得只因前缀就确认泄露。
|
|
88
|
-
- PEM 私钥/证书块、JWT、Bearer Token、Basic 凭据和明显的高熵长字符串。
|
|
89
|
-
- 赋值、对象字段、JSON/YAML 配置、HTTP header、SDK 初始化、环境变量映射、日志和错误上报中的 key 值流转。
|
|
90
|
+
## 审计方法
|
|
90
91
|
|
|
91
|
-
|
|
92
|
+
1. 确认仓库根目录、分支、提交、工作树、技术栈、生产入口、包管理器和锁文件。
|
|
93
|
+
2. 识别生产构建、发布配置、Docker/nginx/启动脚本和会进入线上 bundle 的环境变量来源;不读取 `.env`、私钥或 secret store 的值。
|
|
94
|
+
3. 按实现手册检查依赖供应链、认证/敏感数据路径、XSS/浏览器安全、Node.js 服务、生产配置和安全测试保护。
|
|
95
|
+
4. 复核工具结果的源码上下文,聚合同一根因,排除固定常量、占位符、测试假值和不可达代码。
|
|
96
|
+
5. 为每个 finding 记录来源、汇点、数据流、生产环境、攻击前置条件、影响、标准映射、状态和置信度。
|
|
97
|
+
6. 生成 `.scratch/code-quality-report.md`,重新读取并验证章节、行号、脱敏、工具状态和 Git 工作树。
|
|
92
98
|
|
|
93
|
-
|
|
99
|
+
## 优先级
|
|
94
100
|
|
|
95
|
-
|
|
101
|
+
报告使用 P0-P4,不使用 Critical/High/Medium/Low/Info 作为最终排序:
|
|
96
102
|
|
|
97
|
-
|
|
103
|
+
- **P0**:生产 RCE、认证绕过/管理员接管、生产高权限 key/token 暴露、供应链/生产构建接管。
|
|
104
|
+
- **P1**:确认的 DOM XSS/服务端注入、认证授权绕过、生产 key/token/支付数据泄露、注册/登录/改密/重置密码的明文 transport、SSRF、路径穿越、任意文件读取、高危依赖。
|
|
105
|
+
- **P2**:需要额外条件的注入、可影响生产发布的配置、低权限泄露、DoS、弱安全头、宽松 CORS、中危依赖。
|
|
106
|
+
- **P3**:安全测试缺失、可进入发布产物的工程风险、日志脱敏不完整和依赖维护风险。
|
|
107
|
+
- **P4**:不会进入生产的改进建议、维护性建议、浏览器兼容性和低风险加固。
|
|
98
108
|
|
|
99
|
-
-
|
|
100
|
-
- `eval`、`new Function`、动态 script、iframe、object、embed。
|
|
101
|
-
- `window.open`、`location.assign`、`location.replace`、`location.href`。
|
|
102
|
-
- URL 参数到导航、HTML、脚本或资源 URL 的流转。
|
|
103
|
-
- `javascript:`、`data:`、协议相对 URL。
|
|
104
|
-
- `postMessage` 的 origin 校验。
|
|
105
|
-
- CORS、CSP、SRI、安全响应头、第三方脚本和 CDN 资源。
|
|
109
|
+
每条问题必须使用 `CQ-P<优先级>-<序号>` 编号,并按 P0 到 P4 排序。local/dev/test-only 且确认不会进入生产的问题不进入 P0-P4。
|
|
106
110
|
|
|
107
|
-
|
|
111
|
+
## 输出和局限性
|
|
108
112
|
|
|
109
|
-
|
|
113
|
+
报告必须区分 `Confirmed`、`Suspected`、`Needs Manual Verification` 和 `False Positive`,并遵循固定报告格式。它是只读安全审计,不是渗透测试、合规认证或“绝对安全”证明;没有运行时/生产环境证据时,必须明确局限。
|
|
110
114
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
- 路由鉴权、越权、参数校验和 schema。
|
|
114
|
-
- 原型污染、SSRF、路径穿越、文件上传、解压和临时文件。
|
|
115
|
-
- 命令执行、shell 拼接、模板注入、SQL/NoSQL/LDAP 注入。
|
|
116
|
-
- HTTP 请求代理、WebSocket 和不安全反序列化。
|
|
117
|
-
- ReDoS、资源耗尽、body size、timeout 和 rate limit。
|
|
118
|
-
- 错误栈、敏感信息、日志注入和敏感字段记录。
|
|
119
|
-
- CORS、CSRF、cookie、安全响应头及实际可达的 middleware 配置。
|
|
120
|
-
|
|
121
|
-
必须区分服务端实际可达风险与仅构建工具/开发依赖风险;后者不能直接升级为生产服务漏洞。
|
|
122
|
-
|
|
123
|
-
### Phase 6: 配置和环境
|
|
124
|
-
|
|
125
|
-
逐环境审查 `local`、`development`、`test`、`staging/uat`、`production`(只对仓库中有证据的环境下结论)。不能把 local/dev 配置直接判定为生产漏洞,也不能因为 production 看起来安全就忽略默认启动路径。
|
|
126
|
-
|
|
127
|
-
检查 API HTTPS、HTTP 降级、mixed content、CORS、CSP、HSTS、cookie 属性、默认凭据、debug 模式、source map、错误页、开发服务器暴露、生产 bundle 中的测试地址/内网 IP/管理接口,以及 Dockerfile、nginx、启动脚本和构建阶段是否把错误环境打进生产产物。
|
|
128
|
-
|
|
129
|
-
### Phase 7: 工程质量和安全测试保护
|
|
130
|
-
|
|
131
|
-
检查 `typecheck`、`lint`、`test`、`build`、安全路径测试数量,以及鉴权、重定向、富文本、上传、支付和日志脱敏测试。检查是否存在 `test` script、CI 安全门禁、bundle/依赖/secret scanning 门禁。
|
|
132
|
-
|
|
133
|
-
测试缺失只能作为工程风险,不能伪装成已确认安全漏洞;命令不可执行时记录原因和范围。
|
|
134
|
-
|
|
135
|
-
## 证据和 finding 规则
|
|
136
|
-
|
|
137
|
-
所有 High/Critical finding 必须具备:至少一个明确文件和行号、至少一个来源、至少一个危险汇点、明确中间调用链、受影响环境、攻击前置条件、用户/系统影响,以及修复后的验证命令或测试。每条 finding 必须标记 `Confirmed`、`Suspected`、`Needs Manual Verification` 或 `False Positive`,并提供置信度。
|
|
138
|
-
|
|
139
|
-
静态关键词命中但没有 source-to-sink 证据时,只能标记 `Needs Manual Verification`,不能作为 Confirmed High。相同根因在多个文件中出现时聚合为一个 finding,并列出代表性位置;只有攻击面不同才拆分。
|
|
140
|
-
|
|
141
|
-
## 固定严重级别
|
|
142
|
-
|
|
143
|
-
### Critical
|
|
144
|
-
|
|
145
|
-
仅用于生产环境可远程利用的 RCE、认证绕过或任意管理员接管、生产密钥/密码/token 大规模暴露、可直接导致供应链执行或生产构建接管、严重未授权高权限操作。可直接接管生产构建或具备高权限的真实供应商 key 也属于此级别。
|
|
146
|
-
|
|
147
|
-
### High
|
|
148
|
-
|
|
149
|
-
用于已确认的 DOM XSS 或服务端注入、认证/授权绕过、生产密码/token/支付数据进入日志或客户端不安全存储、生产明文传输敏感数据、SSRF、路径穿越、任意文件读取、高权限操作的开放重定向或 CSRF、可用但权限受限的硬编码供应商 key,以及有明确攻击路径的高危依赖。
|
|
150
|
-
|
|
151
|
-
### Medium
|
|
152
|
-
|
|
153
|
-
用于需要额外前置条件的 XSS/注入、非生产但可能误部署的安全配置、低权限敏感数据泄露、DoS、弱安全头、宽松 CORS 和中等风险依赖漏洞。
|
|
154
|
-
|
|
155
|
-
### Low/Info
|
|
156
|
-
|
|
157
|
-
用于仅本地开发风险、构建维护性问题、需要人工确认但暂无利用证据的问题、浏览器兼容性和测试覆盖不足。
|
|
158
|
-
|
|
159
|
-
## 确定性与完成条件
|
|
160
|
-
|
|
161
|
-
- 每次执行固定 Phase 1-7、固定严重级别、固定 finding 编号前缀和固定报告章节。
|
|
162
|
-
- 不能因为发现数量多而省略认证、日志或环境配置审查。
|
|
163
|
-
- 不能把“未扫描”写成“通过”,也不能把工具成功运行等同于项目安全。
|
|
164
|
-
- 完成前重新读取 `.scratch/code-quality-report.md`,检查章节、行号、命令结果、证据和 Git 状态。
|
|
165
|
-
- 只有报告已生成且可读、所有 Phase 都有结果(含未发现/未执行原因)、High/Critical 满足证据门槛、工作树除报告外没有本次 Skill 产生的项目文件时才算完成。
|
|
115
|
+
如需详细检查顺序、字段示例和验证命令,请阅读 [implementation-playbook.md](references/implementation-playbook.md)。
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Code Quality"
|
|
3
3
|
short_description: "审计前端与 Node.js 服务安全和工程质量"
|
|
4
|
-
default_prompt: "使用 $code-quality
|
|
4
|
+
default_prompt: "使用 $code-quality 按固定流程审计当前前端与 Node.js 服务的生产可达安全风险,并生成 .scratch/code-quality-report.md。"
|
|
5
5
|
|
|
6
6
|
policy:
|
|
7
7
|
allow_implicit_invocation: true
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Code Quality Implementation Playbook
|
|
2
|
+
|
|
3
|
+
本手册是 `code-quality` 的执行细节。入口 Skill 负责路由和边界,本文件负责固定检查顺序、证据门槛和可复用示例。
|
|
4
|
+
|
|
5
|
+
## 固定流程
|
|
6
|
+
|
|
7
|
+
### 1. 生产范围确认
|
|
8
|
+
|
|
9
|
+
- 执行 `git rev-parse --show-toplevel`,记录分支、提交和 `git status --short`。
|
|
10
|
+
- 从 manifest、源码、构建脚本和部署文件确认 SPA/SSR、Node API/BFF、生产入口和包管理器。
|
|
11
|
+
- 只读取生产构建、发布配置和会进入线上 bundle 的路径;local/dev/test-only 文件标记排除原因。
|
|
12
|
+
- `.env`、私钥和 secret store 只记录路径和脱敏变量名,不读取值。
|
|
13
|
+
|
|
14
|
+
### 2. 依赖和供应链
|
|
15
|
+
|
|
16
|
+
按实际工具执行 `npm audit --json`/OSV、`npm ls`、lockfile 一致性、安装脚本和生产 bundle 归属检查。依赖 finding 记录包名、安装版本、direct/transitive、CVE/OSV/GHSA、影响范围、修复路径和运行时/构建时/开发时影响。工具不可用写 `Incomplete`/`Blocked`。
|
|
17
|
+
|
|
18
|
+
### 3. 认证、注册和敏感数据流
|
|
19
|
+
|
|
20
|
+
对注册、登录、登出、刷新 token、改密、重置密码、MFA 和高权限操作逐条追踪:
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
输入 -> 表单/state -> API client -> base URL -> transport
|
|
24
|
+
-> retry/error -> logger/telemetry -> storage/cookie/cache -> redirect
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
判定规则:
|
|
28
|
+
|
|
29
|
+
- HTTPS 请求体中的密码不是仅凭字段名确认的明文传输漏洞。
|
|
30
|
+
- HTTP、明文 WebSocket、mixed content、降级代理或不安全重定向传递生产凭据是 High。
|
|
31
|
+
- 密码/token 进入日志、遥测、错误上报、URL、localStorage 或不安全缓存是敏感泄露。
|
|
32
|
+
- 记录 token 的 Cookie 属性、过期/刷新、重放和跨环境风险。
|
|
33
|
+
|
|
34
|
+
### 4. Key 和秘密扫描
|
|
35
|
+
|
|
36
|
+
检查 `apiKey`、`api_key`、`OPENAI_API_KEY`、`secretKey`、`clientSecret`、`privateKey`、供应商前缀、JWT、Bearer/Basic、PEM 和高熵值。对每个命中确认是否为真实值、占位符、测试假值、变量引用或仅字段名。
|
|
37
|
+
|
|
38
|
+
普通 `key`、React `key` 和业务索引不自动报漏洞。真实 key 只在报告中记录脱敏指纹;若进入生产 bundle、Git 历史、日志、URL、客户端存储或公开接口,建议撤销、轮换、收缩权限、清理历史并复测。
|
|
39
|
+
|
|
40
|
+
### 5. 客户端和服务端安全
|
|
41
|
+
|
|
42
|
+
检查 XSS sink、动态脚本、URL 导航、`postMessage`、CSP/SRI/Trusted Types、frame policy、CORS/CSRF、安全 Cookie、第三方集成;Node.js 服务检查鉴权、schema、SSRF、路径穿越、命令/模板/SQL/NoSQL 注入、文件上传、反序列化、DoS 和日志。
|
|
43
|
+
|
|
44
|
+
### 6. 证据和报告
|
|
45
|
+
|
|
46
|
+
P0/P1 必须具备文件与行号、来源、汇点、调用链、生产环境、前置条件、影响和验证方式。静态关键词没有数据流证据只能是 `Needs Manual Verification`。报告固定写入 `.scratch/code-quality-report.md`,写后复读并检查 Git 状态。
|
|
47
|
+
|
|
48
|
+
## 推荐验证命令
|
|
49
|
+
|
|
50
|
+
只在命令已存在且确认不会改写项目时执行:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
npm audit --json
|
|
54
|
+
npm ls
|
|
55
|
+
npm run lint
|
|
56
|
+
npm run typecheck
|
|
57
|
+
npm test -- --runInBand
|
|
58
|
+
npm run build
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
命令不存在、网络不可用或失败时记录状态和原因;不要用失败结果推断安全通过。
|
|
62
|
+
|
|
63
|
+
## finding 示例
|
|
64
|
+
|
|
65
|
+
```md
|
|
66
|
+
### CQ-P1-001 登录凭据通过 HTTP 传输
|
|
67
|
+
|
|
68
|
+
- 优先级:P1
|
|
69
|
+
- 状态:Confirmed
|
|
70
|
+
- 标准映射:ASVS V9 / CWE-319
|
|
71
|
+
- 来源:`src/auth/login.ts:18`
|
|
72
|
+
- 危险汇点:`src/api/client.ts:42`
|
|
73
|
+
- 数据流:`password field -> login request -> http://api.example.com/login`
|
|
74
|
+
- 受影响环境:production
|
|
75
|
+
- 攻击前置条件:攻击者可观察客户端到 API 的网络路径
|
|
76
|
+
- 证据:生产 base URL 使用 `http://`,且登录请求未升级到 HTTPS
|
|
77
|
+
- 修复建议:强制 HTTPS、阻止降级和 mixed content,并验证登录/注册/改密路径
|
|
78
|
+
- 验证方式:在生产构建和网络检查中确认所有认证端点使用 HTTPS
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
报告不得输出完整 key、token、密码、私钥或用户数据。
|
|
@@ -1,126 +1,120 @@
|
|
|
1
1
|
# Code Quality 报告格式
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
报告唯一输出路径:`.scratch/code-quality-report.md`。报告面向开发人员修复问题,使用简体中文,按优先级从高到低排列。不要输出完整 key、token、密码、私钥或用户数据。
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
报告必须按以下顺序出现;没有发现或没有适用项时保留章节并写明“未发现实现证据”或“不适用”。
|
|
5
|
+
## 固定排版
|
|
8
6
|
|
|
9
7
|
```md
|
|
10
8
|
# Code Quality Security Report
|
|
11
9
|
|
|
12
|
-
##
|
|
13
|
-
##
|
|
14
|
-
##
|
|
15
|
-
##
|
|
16
|
-
##
|
|
17
|
-
##
|
|
18
|
-
##
|
|
19
|
-
##
|
|
20
|
-
## Medium/Low/Info 问题
|
|
21
|
-
## 工程质量问题
|
|
22
|
-
## 未执行检查
|
|
23
|
-
## 修改建议与验证方式
|
|
24
|
-
## 未覆盖范围与残余风险
|
|
10
|
+
## 扫描结论
|
|
11
|
+
## P0 - 紧急修复
|
|
12
|
+
## P1 - 高优先级修复
|
|
13
|
+
## P2 - 中优先级修复
|
|
14
|
+
## P3 - 一般修复
|
|
15
|
+
## P4 - 建议优化
|
|
16
|
+
## 修复排版建议
|
|
17
|
+
## 未覆盖范围
|
|
25
18
|
```
|
|
26
19
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
摘要必须说明审计状态、审计时间、审计目标、是否存在阻断项和结论边界。风险统计必须分别列出:
|
|
30
|
-
|
|
31
|
-
- Confirmed 漏洞数量。
|
|
32
|
-
- Needs Manual Verification 数量。
|
|
33
|
-
- Suspected 数量。
|
|
34
|
-
- False Positive 数量(如有复核记录)。
|
|
35
|
-
- 工程质量问题数量。
|
|
36
|
-
- 依赖漏洞数量。
|
|
37
|
-
- 生产环境问题数量。
|
|
38
|
-
- 非生产环境问题数量。
|
|
39
|
-
- 敏感 key/凭据发现数量,并区分真实值、占位符、测试假值和待确认值。
|
|
40
|
-
- 未执行检查数量。
|
|
20
|
+
没有问题时仍保留 P0-P4 标题,并写“未发现”。工具不可用、生产入口不可读或检查范围不完整时,在“扫描结论”和“未覆盖范围”中写明 `Incomplete` 或 `Blocked`。
|
|
41
21
|
|
|
42
|
-
|
|
22
|
+
## 优先级
|
|
43
23
|
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
24
|
+
- **P0**:生产环境正在暴露或可直接造成重大后果的问题,例如 RCE、认证绕过/管理员接管、生产高权限 key/token 暴露、生产构建或供应链接管。
|
|
25
|
+
- **P1**:确认的生产漏洞或敏感数据泄露,例如 DOM XSS、服务端注入、SSRF、路径穿越、任意文件读取、生产 key/token 泄露、注册/登录/改密/重置密码通过 HTTP 或其他明文 transport 传输、高危依赖。
|
|
26
|
+
- **P2**:需要额外条件才能利用,但会影响生产安全的问题,例如弱 CSP、宽松 CORS、CSRF 前置条件、低权限敏感信息泄露、DoS/ReDoS、中危依赖。
|
|
27
|
+
- **P3**:不会立即造成漏洞,但会增加上线风险或修复成本,例如安全测试缺失、可进入发布产物的配置隐患、日志脱敏不完整、依赖维护风险。
|
|
28
|
+
- **P4**:改进建议和低风险问题,例如代码可维护性、浏览器兼容性、非阻断安全加固。
|
|
48
29
|
|
|
49
|
-
|
|
30
|
+
local/dev/test-only 且确认不会进入生产构建、发布配置或默认上线路径的问题,不进入 P0-P4;只在“未覆盖范围”中记录排除原因。
|
|
50
31
|
|
|
51
|
-
##
|
|
32
|
+
## 扫描结论
|
|
52
33
|
|
|
53
|
-
|
|
34
|
+
只写必要信息:
|
|
54
35
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
36
|
+
```md
|
|
37
|
+
- 状态:Findings / Passed / Incomplete / Blocked
|
|
38
|
+
- 扫描范围:生产源码、发布配置、依赖和生产 bundle 相关路径
|
|
39
|
+
- 扫描时间:YYYY-MM-DD HH:mm
|
|
40
|
+
- P0:0
|
|
41
|
+
- P1:2
|
|
42
|
+
- P2:1
|
|
43
|
+
- P3:0
|
|
44
|
+
- P4:3
|
|
45
|
+
```
|
|
60
46
|
|
|
61
|
-
##
|
|
47
|
+
## 单条错误格式
|
|
62
48
|
|
|
63
|
-
|
|
49
|
+
每条错误必须有连续编号,并放在对应优先级章节内。编号格式为 `CQ-<优先级>-<序号>`,例如 `CQ-P1-001`。同一根因的多个位置合并到一条;攻击面不同才拆分。
|
|
64
50
|
|
|
65
51
|
```md
|
|
66
|
-
### CQ-
|
|
67
|
-
|
|
68
|
-
-
|
|
69
|
-
- 状态:Confirmed
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
52
|
+
### CQ-P1-001 登录凭据通过 HTTP 传输
|
|
53
|
+
|
|
54
|
+
- 优先级:P1
|
|
55
|
+
- 状态:Confirmed / Suspected / Needs Manual Verification / False Positive
|
|
56
|
+
- 文件夹:`src/auth/`
|
|
57
|
+
- 文件:`src/auth/login.ts`
|
|
58
|
+
- 行号:42
|
|
59
|
+
- 错误代码:`CWE-319`
|
|
60
|
+
- 规则/标准:ASVS V9 / OWASP A02
|
|
61
|
+
- 错误位置:`fetch(loginUrl, { method: 'POST', body })`
|
|
62
|
+
- 错误说明:生产登录请求使用 `http://`,密码可能以明文方式经过网络传输。
|
|
63
|
+
- 影响:网络观察者可能获取用户凭据。
|
|
64
|
+
- 证据:`src/config/api.ts:12` 将生产 base URL 配置为 `http://...`。
|
|
65
|
+
- 修改建议:强制使用 HTTPS,阻止协议降级,并检查注册、登录、改密和重置密码的最终请求地址。
|
|
66
|
+
- 代码示例:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
const api = new URL('/login', 'https://api.example.com');
|
|
70
|
+
await fetch(api, { method: 'POST', body: JSON.stringify(payload) });
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- 验证方式:检查生产构建配置和浏览器 Network,确认认证请求均使用 HTTPS。
|
|
86
74
|
```
|
|
87
75
|
|
|
88
|
-
|
|
76
|
+
### 字段要求
|
|
77
|
+
|
|
78
|
+
- `文件夹`:问题所在目录;无法归属时写最近的模块目录。
|
|
79
|
+
- `文件` 和 `行号`:必须能直接定位;工具只给出包名时,补充 manifest 或 lockfile 位置。
|
|
80
|
+
- `错误代码`:优先填写 CWE、CVE、OSV、规则 ID 或项目 lint 规则;确实没有时写 `N/A`,不要编造编号。
|
|
81
|
+
- `错误位置`:给出具体函数、表达式、配置键或命令,而不是只写文件名。
|
|
82
|
+
- `代码示例`:优先给最小修复前/修复后片段;涉及 key/token/密码时使用脱敏占位符。
|
|
83
|
+
- `修改建议`:说明改什么、为什么改和边界条件,不直接修改仓库。
|
|
84
|
+
- `验证方式`:给出命令、测试或浏览器检查方法。
|
|
89
85
|
|
|
90
|
-
|
|
86
|
+
静态关键词命中但没有来源到危险汇点的证据,只能使用 `Needs Manual Verification`,不能直接列为 P0/P1。
|
|
91
87
|
|
|
92
|
-
|
|
88
|
+
## 敏感 key 报告规则
|
|
93
89
|
|
|
94
|
-
|
|
95
|
-
- 凭据类型和供应商(如可确认)。
|
|
96
|
-
- 脱敏指纹:前缀、后缀、长度或 SHA-256 截断值;不得写完整秘密。
|
|
97
|
-
- 出现位置:源码、配置模板、测试 fixture、文档、构建产物、日志、URL、客户端存储或 Git 历史。
|
|
98
|
-
- 是否具备真实格式、是否可能有效、权限范围和受影响环境;无法确认时使用 `Needs Manual Verification`。
|
|
99
|
-
- 是否进入生产 bundle、请求 header、日志/遥测或公开接口。
|
|
100
|
-
- 建议的撤销、轮换、历史清理、权限收缩和复测步骤。
|
|
90
|
+
发现 `apiKey`、`OPENAI_API_KEY`、`secretKey`、JWT、Bearer Token、PEM 私钥或其他凭据时:
|
|
101
91
|
|
|
102
|
-
|
|
92
|
+
- `错误位置` 写字段和文件行号,不写完整值。
|
|
93
|
+
- `证据` 只写前缀、后缀、长度或 SHA-256 截断指纹。
|
|
94
|
+
- `修改建议` 必须包含撤销、轮换、权限收缩和历史清理建议(适用时)。
|
|
95
|
+
- 普通 `key`、React `key` 和业务索引没有敏感值或数据流时,不作为安全错误。
|
|
103
96
|
|
|
104
|
-
##
|
|
97
|
+
## 修复排版建议
|
|
105
98
|
|
|
106
|
-
|
|
99
|
+
最后单独列出哪些问题可以一起修复,哪些必须分开处理:
|
|
107
100
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
- CVE/OSV/GHSA 编号。
|
|
111
|
-
- 受影响范围和修复版本/升级路径。
|
|
112
|
-
- 运行时、构建时或开发时影响。
|
|
113
|
-
- 是否实际进入生产 bundle;无法确认时标记 `Needs Manual Verification`。
|
|
114
|
-
- `npm audit`、OSV、`npm ls` 或其他工具的代表性输出位置。
|
|
101
|
+
```md
|
|
102
|
+
## 修复排版建议
|
|
115
103
|
|
|
116
|
-
|
|
104
|
+
### 可以放在一起
|
|
117
105
|
|
|
118
|
-
|
|
106
|
+
- `CQ-P1-001`、`CQ-P1-002`:同一个 API client 的 HTTP 降级问题,可统一修改 transport 和生产 base URL。
|
|
107
|
+
- `CQ-P2-001`、`CQ-P2-002`:同一套 CSP 配置缺少 `frame-ancestors` 和 `object-src`,可统一调整响应头并一起验证。
|
|
119
108
|
|
|
120
|
-
|
|
109
|
+
### 不要放在一起
|
|
121
110
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
| `npm audit --json` | workspace | Executed/Incomplete/Blocked | ... | ... | ... |
|
|
111
|
+
- `CQ-P1-003` 密钥泄露与 `CQ-P1-004` DOM XSS:根因、验证方式和回滚策略不同,应分开修复。
|
|
112
|
+
- 依赖升级与认证流程修改:分别验证依赖回归和业务登录流程,不能合并成一个无边界改动。
|
|
125
113
|
|
|
126
|
-
|
|
114
|
+
### 推荐顺序
|
|
115
|
+
|
|
116
|
+
1. 先处理全部 P0。
|
|
117
|
+
2. 再处理 P1,按生产暴露面和数据敏感度排序。
|
|
118
|
+
3. 合并同一根因的 P2/P3 修复,完成后补充安全测试。
|
|
119
|
+
4. 最后处理 P4 建议。
|
|
120
|
+
```
|
|
@@ -14,7 +14,7 @@ description: 通过 trace-mcp-recorder 启动或停止 Playwright Trace 人工
|
|
|
14
14
|
1. 从原话提取 `url`、`version`、`title`、`operator`。支持 `key=value` 和自然语言表达,不改写用户给出的值。
|
|
15
15
|
2. `url` 必填;缺少时只询问目标页面地址。其他字段缺失时不要阻断录制。
|
|
16
16
|
3. 调用 `start_trace_recording`,只传入用户明确提供的可选字段。服务端会优先使用 MCP 上下文中的操作人身份。
|
|
17
|
-
4. 告知用户浏览器已打开:默认是 PC 端(viewport 1400×740
|
|
17
|
+
4. 告知用户浏览器已打开:默认是 PC 端(viewport 1400×740);左下角显示可拖拽的 2×2 半透明控制栏,第一行是“开始录制”“停止录制”,第二行是“切换移动端”“截图”,下方提供“画笔”“撤销”“清空”。画笔使用 SVG 路径覆盖层,开启后可用鼠标或触摸标注页面;点击“退出画笔”会立即关闭并清空已有标注,避免后续页面操作继续带着旧标注,截图会带上标注。先点击“切换移动端”(iPhone 14 Pro Max,430×932,DPR 3)或保持 PC 端,再点击“开始录制”;点击开始后服务会先启动 Trace,临时禁用 Chromium 缓存并刷新当前 SPA 页面,等待 DOM、CSS、字体和图片稳定后恢复缓存,随后才进入正式录制计时。刷新期间不要操作页面;页面稳定后按需操作,只有点击“截图”才会保存当前渲染画面,普通点击、输入和滚动不会生成自定义 Action。截图时所有控制按钮会临时隐藏。同一 BrowserContext 会保留 cookies、localStorage 和 sessionStorage,新打开的页面会继承当前设备模式。连续 2 分钟没有页面活动时服务会自动停止并上传。人工截图在官方 Trace Viewer 中显示为 `步骤N | 页面标题`。
|
|
18
18
|
|
|
19
19
|
示例:`trace-mcp-recorder 启动Playwright trace 访问https://cpd.dev.autobestdevops.com,version=v2.1.0 title=bug3452 operator=张三`。这里 `title=bug3452` 是本次录制的标题/功能描述,页面由 `url=https://cpd.dev.autobestdevops.com` 确定。
|
|
20
20
|
|