canship 0.5.0 → 0.7.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-zh-CN.md +94 -127
- package/README.md +94 -127
- package/dist/cli.js +5750 -2164
- package/dist/index.js +4489 -1278
- package/package.json +5 -2
package/README-zh-CN.md
CHANGED
|
@@ -1,153 +1,112 @@
|
|
|
1
1
|
# canship
|
|
2
2
|
|
|
3
|
-
面向 JavaScript / TypeScript
|
|
3
|
+
面向 JavaScript / TypeScript Web 应用的本地静态扫描器,检查凭据暴露、访问控制配置及请求输入风险。扫描不执行项目代码、不上传文件、不联网。
|
|
4
4
|
|
|
5
5
|
[English](./README.md)
|
|
6
6
|
|
|
7
|
+
> 本文对应 `0.7.0`。使用 `npx canship --version` 确认已安装版本。
|
|
8
|
+
|
|
7
9
|
## 快速开始
|
|
8
10
|
|
|
9
11
|
```powershell
|
|
10
|
-
npx canship
|
|
12
|
+
npx canship
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
默认扫描当前目录,也可指定路径。要求 Node.js ≥18,无运行时依赖,安装可能联网。Git 检查覆盖本地跟踪文件及提交历史,不访问远程仓库;历史无法读取时标记扫描不完整。
|
|
16
|
+
|
|
17
|
+
以下报告来自发布前开发构建,使用示例数据。
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+

|
|
16
20
|
|
|
17
21
|
## 检测范围
|
|
18
22
|
|
|
19
|
-
|
|
|
20
|
-
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
| 内容可被列举的 Supabase 公开存储桶 | P2 |
|
|
27
|
-
| Firebase 无条件访问及固定日期测试规则 | P1 |
|
|
28
|
-
| 服务端数据操作未识别到鉴权 | P0 / P1 |
|
|
29
|
-
| 携带凭据的 CORS 来源回显或通配符配置 | P1 / P2 |
|
|
23
|
+
| 类别 | 级别 | 范围 |
|
|
24
|
+
|---|:---:|---|
|
|
25
|
+
| 凭据 | `P0` | 硬编码密钥、私钥、含密码的数据库连接串、公开变量中的私密值、Supabase 管理员密钥、Git 跟踪或历史中的非模板 `.env` 文件 |
|
|
26
|
+
| API 访问 | `P0/P1` | 未识别到鉴权的数据库操作、服务端信任 Supabase `getSession()`、未验证的 Stripe webhook |
|
|
27
|
+
| 数据库规则 | `P1/P2` | Supabase 表未启用 RLS、无条件放行策略、允许公开列出对象的存储桶;Firebase 开放规则及限时测试规则 |
|
|
28
|
+
| CORS | `P1/P2` | 携带凭据的来源回显或通配符配置 |
|
|
29
|
+
| 请求输入 | `P1/P2` | 请求输入参与 SQL 或命令构造、调用方可控的请求主机和重定向目标 |
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
凭据格式包括 OpenAI、Anthropic、AWS、Stripe、GitHub、npm 等。Firebase 覆盖 Firestore、Storage、Realtime Database。`--list-rules` 列出规则 ID、范围及局限。
|
|
32
32
|
|
|
33
|
-
###
|
|
33
|
+
### 服务端入口
|
|
34
34
|
|
|
35
|
-
| 框架 |
|
|
35
|
+
| 框架 | 入口 |
|
|
36
36
|
|---|---|
|
|
37
|
-
| Next.js |
|
|
38
|
-
| SvelteKit | `+server`
|
|
37
|
+
| Next.js | App Router 处理函数、Pages Router `/api`、`'use server'` 函数 |
|
|
38
|
+
| SvelteKit | `+server` 端点、`+page.server` 表单 action |
|
|
39
39
|
| Nuxt | `server/api`、`server/routes` |
|
|
40
40
|
| Remix / React Router | `app/routes` 中的 `loader`、`action` 导出 |
|
|
41
41
|
| Astro | `src/pages` 中的端点 |
|
|
42
|
+
| Express | `app`/`Router` 路由,含 `.route()` 链、挂载的子路由和其他文件中的控制器 |
|
|
43
|
+
| Hono | `app.get()` 等路由、链式调用、`basePath`,以及 `app.route()` 挂载的子应用 |
|
|
44
|
+
| Fastify | 简写与 `route()` 声明、`register()` 前缀与封装作用域、`@fastify/autoload` 目录 |
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
已识别的 Next.js/Astro 中间件可抑制覆盖范围内的结果;Server Function 需在函数内检查。本地辅助函数、SvelteKit hooks、Nuxt 中间件可降低置信度,但保留结果。不检查 SvelteKit 页面 load 与 remote function。
|
|
46
|
+
已识别的 Next.js/Astro 中间件可抑制覆盖范围内的鉴权结果;Server Function 需在函数内检查。Express、Hono、Fastify 的中间件与钩子只有解析到拒绝未认证请求的代码或已知鉴权库时才抑制鉴权结果;名称像鉴权但无法解析的中间件降低置信度。项目自定义的会话或凭据校验(如 `validateSessionToken`)及 webhook 验签(Stripe、Polar、Clerk、Svix,以及 QStash `receiver.verify` 这类须 await 的校验)只有在失败分支抛出、跳转或返回 401/403 时才算鉴权。本地辅助函数、含鉴权逻辑的项目包装函数(如 `withWorkspace`)、SvelteKit hooks、Nuxt 中间件可降低置信度或将结果标为待复核,但保留结果。输入分析追踪可见的赋值、解构和字符串构造,不以辅助函数名称证明安全。
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
Express、Hono、Fastify 路由会跟进被调项目函数中的写入,最多两层(处理函数 → service → model);文件约定路由只报告路由文件内的写入。路由分析不覆盖 SvelteKit 页面 load、remote function 和 Hono 的 `app.openapi()` 路由;凭据、CORS 等内容规则仍适用。
|
|
48
49
|
|
|
49
|
-
##
|
|
50
|
-
|
|
51
|
-
省略路径时扫描当前目录。报告正文为英文。
|
|
50
|
+
## 结果
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|---|---|
|
|
55
|
-
| `-a`、`--all` | 包含 `likely` 结果 |
|
|
56
|
-
| `--json` | 输出 JSON |
|
|
57
|
-
| `--fix-prompt` | 输出修复指令及独立的人工操作清单 |
|
|
58
|
-
| `--report[=file]` | 写入 HTML,默认 `canship-report.html` |
|
|
59
|
-
| `--sarif[=file]` | 写入 SARIF 2.1.0,默认 `canship.sarif` |
|
|
60
|
-
| `--no-excerpts` | 省略源码摘录,保留结果和退出码 |
|
|
61
|
-
| `--changed-since=ref` | 展示与变更文件相关的结果,退出码仍基于全量扫描 |
|
|
62
|
-
| `--only=ids` / `--skip=ids` | 选择或排除规则,支持逗号分隔及重复参数 |
|
|
63
|
-
| `--list-rules` | 列出规则而不扫描,支持 `--json` |
|
|
64
|
-
| `--baseline[=file]` | 抑制已有结果,默认 `canship-baseline.json` |
|
|
65
|
-
| `--baseline-write[=file]` | 记录结果后退出,默认路径同上 |
|
|
66
|
-
| `--no-config` | 忽略项目配置 |
|
|
67
|
-
| `--no-ignore-markers` | 不遵从源码忽略注释 |
|
|
68
|
-
| `--best-effort` | 允许没有结果的不完整扫描退出 `0` |
|
|
69
|
-
| `-h`、`--help` / `-v`、`--version` | 显示帮助或版本 |
|
|
52
|
+
报告正文为英文。终端按文件分组,`--verbose` 展开摘录、说明、证据和修复步骤。HTML 为自包含离线报告,支持筛选、分组、人工操作清单及修复提示复制。
|
|
70
53
|
|
|
71
|
-
|
|
54
|
+

|
|
72
55
|
|
|
73
|
-
|
|
56
|
+
`certain` 表示静态证据充分,`likely` 需人工审阅;测试和示例中的结果降为 `likely`。默认仅展示 `certain`,`--all` 显示全部。置信度仅反映静态证据,不代表凭据有效或风险已在运行时验证。
|
|
74
57
|
|
|
75
58
|
| 退出码 | 含义 |
|
|
76
59
|
|---|---|
|
|
77
|
-
| `0` |
|
|
60
|
+
| `0` | 无结果,且扫描完整或由 `--best-effort` 接受 |
|
|
78
61
|
| `1` | 至少一条 `certain` 的 P0/P1 结果 |
|
|
79
62
|
| `2` | 其他结果,包括隐藏的 `likely` |
|
|
80
63
|
| `3` | 参数错误、工具错误或未被接受的不完整扫描 |
|
|
81
64
|
|
|
82
|
-
|
|
65
|
+
退出码基于规则筛选、忽略注释和基线处理后的结果。有结果时优先于扫描不完整;`--best-effort` 不改变 `1` 或 `2`。
|
|
83
66
|
|
|
84
|
-
|
|
67
|
+
## 命令行
|
|
85
68
|
|
|
86
|
-
|
|
69
|
+
`npx canship [path] [options]`
|
|
87
70
|
|
|
88
|
-
|
|
71
|
+
| 参数 | 作用 |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `-a`、`--all` | 包含 `likely` 结果 |
|
|
74
|
+
| `--verbose` | 展开终端结果 |
|
|
75
|
+
| `--report[=file]` | 写入 HTML,默认 `canship-report.html` |
|
|
76
|
+
| `--open` | 打开 `--report` 输出;CI 和非交互终端中禁用 |
|
|
77
|
+
| `--json` | 输出 JSON |
|
|
78
|
+
| `--sarif[=file]` | 写入 SARIF 2.1.0,默认 `canship.sarif` |
|
|
79
|
+
| `--fix-prompt` | 输出修复指令及独立的人工操作清单 |
|
|
80
|
+
| `--no-excerpts` | 移除所有报告中的摘录 |
|
|
81
|
+
| `--changed-since=ref` | 展示变更文件结果,保留全量扫描退出码 |
|
|
82
|
+
| `--only=ids` / `--skip=ids` | 选择或排除规则及命名空间,逗号分隔,可重复 |
|
|
83
|
+
| `--list-rules` | 列出规则而不扫描,支持 `--json` |
|
|
84
|
+
| `--baseline[=file]` / `--baseline-write[=file]` | 抑制或记录结果,默认 `canship-baseline.json` |
|
|
85
|
+
| `--no-config` / `--no-ignore-markers` | 忽略项目配置或源码抑制注释 |
|
|
86
|
+
| `--best-effort` | 允许没有结果的不完整扫描退出 `0` |
|
|
87
|
+
| `-h`、`--help` / `-v`、`--version` | 显示帮助或版本 |
|
|
89
88
|
|
|
90
|
-
|
|
89
|
+
`--json` 与 `--fix-prompt` 互斥,均可同时输出 HTML 和 SARIF。
|
|
90
|
+
|
|
91
|
+
`--changed-since` 比较本地共同祖先与工作区,包含未被忽略的新文件,不拉取远程、不缩小扫描范围。缺少 Git、引用或共同历史时退出 `3`;不能与 `--baseline-write` 组合。
|
|
91
92
|
|
|
92
93
|
## 配置
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
`canship.config.json` 支持 `baseline`、`only`、`skip`、`all`。命令行参数优先,`only` 与 `skip` 互斥。
|
|
95
96
|
|
|
96
97
|
```json
|
|
97
|
-
{
|
|
98
|
-
"skip": ["cors/wildcard-with-credentials"],
|
|
99
|
-
"all": false
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
命令行参数优先。`only`、`skip` 互斥,接受规则 ID 或命名空间。`--best-effort` 仅限命令行。不可信项目使用 `--no-config --no-ignore-markers`。
|
|
104
|
-
|
|
105
|
-
### 忽略注释
|
|
106
|
-
|
|
107
|
-
独占注释行的 `canship-ignore-file` 排除整个文件;`canship-ignore-next-line` 抑制下一行,可限定规则:
|
|
108
|
-
|
|
109
|
-
```ts
|
|
110
|
-
// canship-ignore-next-line cors/wildcard-with-credentials
|
|
111
|
-
const corsOptions = { origin: '*', credentials: true }
|
|
98
|
+
{ "skip": ["cors/wildcard-with-credentials"], "all": false }
|
|
112
99
|
```
|
|
113
100
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
### 基线
|
|
117
|
-
|
|
118
|
-
记录已有结果,后续扫描再抑制:
|
|
119
|
-
|
|
120
|
-
```powershell
|
|
121
|
-
npx canship --baseline-write
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
```powershell
|
|
125
|
-
npx canship --baseline
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
默认路径相对扫描目录,显式路径相对工作目录;读取与写入模式互斥。写入成功退出 `0`,不代表扫描无问题;扫描不完整或启用规则筛选时会提示。
|
|
129
|
-
|
|
130
|
-
v2 指纹不受行号移动影响,凭据变化会改变指纹。缺失、损坏及 v1 基线均退出 `3`。基线不含摘录,但保留路径、规则和描述,提交前需审阅。
|
|
131
|
-
|
|
132
|
-
## API
|
|
133
|
-
|
|
134
|
-
提供 Node.js ESM 入口与 TypeScript 类型:
|
|
101
|
+
独占行注释 `canship-ignore-file` 排除整个文件;`canship-ignore-next-line [rule]` 抑制下一行,可限定单条规则。报告披露排除项;主动抑制不标记扫描不完整,可能使退出码降为 `0`。扫描不可信项目时使用 `--no-config --no-ignore-markers`。
|
|
135
102
|
|
|
136
|
-
|
|
137
|
-
import { scan, summarize, listRules } from 'canship'
|
|
138
|
-
|
|
139
|
-
const result = await scan('./my-app', { noExcerpts: true })
|
|
140
|
-
console.log(summarize(result))
|
|
141
|
-
console.log(listRules())
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
`scan()` 返回全部置信度结果,支持 `only`、`skip`、`honorIgnoreMarkers`(默认 `true`)、`noExcerpts`(默认 `false`)。不加载配置、不应用基线、不写报告、不设置退出码。无效参数或根目录抛出异常;扫描缺口保留在结果中。
|
|
103
|
+
基线表示接受已有结果,不代表问题已修复。v2 格式不受行号移动影响,但凭据变化会重新报告。
|
|
145
104
|
|
|
146
|
-
|
|
105
|
+
默认路径相对扫描目录,显式路径相对工作目录;读取与写入互斥。缺失、无效或 v1 基线退出 `3`。写入成功退出 `0`,不完整或选择性扫描会提示。
|
|
147
106
|
|
|
148
107
|
## GitHub Action
|
|
149
108
|
|
|
150
|
-
保存为 `.github/workflows/canship.yml
|
|
109
|
+
保存为 `.github/workflows/canship.yml`:
|
|
151
110
|
|
|
152
111
|
```yaml
|
|
153
112
|
name: canship
|
|
@@ -162,47 +121,57 @@ jobs:
|
|
|
162
121
|
with:
|
|
163
122
|
fetch-depth: 0
|
|
164
123
|
persist-credentials: false
|
|
165
|
-
- uses: Tasomei/canship@
|
|
124
|
+
- uses: Tasomei/canship@7dfebc9502b786edd5c7fd71266e4926d0ad764b
|
|
166
125
|
with:
|
|
167
|
-
version: '0.
|
|
126
|
+
version: '0.7.0'
|
|
168
127
|
honor-ignore-markers: false
|
|
169
128
|
```
|
|
170
129
|
|
|
171
|
-
|
|
130
|
+
提交哈希固定 Action 实现,`version` 指定 npm 扫描器版本,不使用开发分支源码。Action 使用 Node.js 22,不安装或运行项目依赖,仅输出统计摘要。
|
|
172
131
|
|
|
173
|
-
| 输入 | 默认值 |
|
|
132
|
+
| 输入 | 默认值 | 含义 |
|
|
174
133
|
|---|---|---|
|
|
175
|
-
| `version` | `0.
|
|
134
|
+
| `version` | `0.6.0` | 精确 npm 扫描器版本 |
|
|
176
135
|
| `fail-on` | `blocking` | `blocking`:确定的 P0/P1;`any`:全部结果;`none`:仅报告 |
|
|
177
|
-
| `use-config` | `false` | 启用项目配置 |
|
|
178
|
-
| `honor-ignore-markers` | `true` | 遵从整文件及逐行忽略注释 |
|
|
179
|
-
| `upload-sarif` | `false` | 上传至 GitHub 代码扫描 |
|
|
180
136
|
|
|
181
|
-
|
|
137
|
+
扫描不完整或工具错误始终失败。默认不读取项目配置、不上传 SARIF。输入输出见 [action.yml](./action.yml)。
|
|
182
138
|
|
|
183
|
-
|
|
139
|
+
上传 SARIF 需 `security-events: write` 及代码扫描支持,fork PR 可能权限不足;上传前应审阅报告。不可信 PR 使用 `pull_request`,不要使用 `pull_request_target`。
|
|
184
140
|
|
|
185
|
-
|
|
141
|
+
## API 与结构化输出
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
import { scan, summarize } from 'canship'
|
|
145
|
+
|
|
146
|
+
const result = await scan('./my-app', { noExcerpts: true })
|
|
147
|
+
console.log(summarize(result))
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
`scan()` 返回全部置信度结果,支持 `only`、`skip`、`honorIgnoreMarkers`(默认 `true`)、`noExcerpts`(默认 `false`)。不加载配置、不应用基线、不写报告、不设置进程退出码;无效参数抛出异常。`listRules()` 返回规则目录。
|
|
151
|
+
|
|
152
|
+
JSON 使用 [schemaVersion 1](./schemas/scan-report-v1.schema.json)。须独立于退出码检查 `partial`、`errors`、`skipped`、`filesScanned`。SARIF 包含证据位置和执行诊断。
|
|
186
153
|
|
|
187
154
|
## 隐私与限制
|
|
188
155
|
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
- Google/Firebase/Maps 的 `AIza
|
|
192
|
-
-
|
|
193
|
-
-
|
|
156
|
+
- 静态检查可能误报或漏报,不验证业务授权、限流、依赖漏洞或线上配置。
|
|
157
|
+
- 脱敏仅覆盖已识别格式,未知敏感值可能保留在摘录中;`--no-excerpts` 可移除摘录。路径、名称和基线描述仍可见。
|
|
158
|
+
- Google/Firebase/Maps 的 `AIza…` 密钥按公开标识符处理,不单凭其值判定泄露。Supabase 检查依据本地迁移及支持的存储桶配置。
|
|
159
|
+
- 评估快照获取和可选的 SARIF 上传可能联网。
|
|
160
|
+
- 不跟随符号链接;嵌套仓库与子模块需单独扫描。范围内跳过项及分析超限标记扫描不完整;鉴权辅助函数解析超限不会隐藏结果,改为在受影响的结果上注明。默认排除的依赖和构建目录不计为扫描缺口。
|
|
194
161
|
|
|
195
|
-
|
|
|
162
|
+
| 项目 | 上限 |
|
|
196
163
|
|---|---|
|
|
197
|
-
|
|
|
198
|
-
| 目录遍历 | 50,000
|
|
199
|
-
|
|
|
164
|
+
| 文件读取 | 单文件 2 MiB;单次 128 MiB、10,000 个文件,含探测 |
|
|
165
|
+
| 目录遍历 | 50,000 个条目;16 层 |
|
|
166
|
+
| 结果 | 每文件 100 条,优先保留高严重度、高置信度结果 |
|
|
200
167
|
| Git 历史 | 每文件 100 个相关版本;单条命令 30 秒 |
|
|
201
|
-
|
|
|
202
|
-
|
|
|
168
|
+
| 鉴权辅助函数解析 | 8 跳;每个辅助函数 64 个符号,每个路由文件共 1,024 个 |
|
|
169
|
+
| 委托写入 | 调用 2 层;每个文件 256 个被调函数;超出部分的写入不报告 |
|
|
170
|
+
| 身份/控制流 | 值解析 8 步;表达式 4,000 字符;每函数 512 个赋值/区域;区域嵌套 8 层 |
|
|
171
|
+
| 请求输入追踪 | 值解析 8 步;512 个赋值/区域;单条表达式 64 KiB;URL 分析 8 层、静态前缀 200 字符 |
|
|
203
172
|
| Supabase 策略/存储桶解析 | 单条语句 4,000 字符 |
|
|
204
173
|
|
|
205
|
-
|
|
174
|
+
证据链最多 24 步,截断时提示。
|
|
206
175
|
|
|
207
176
|
## 开发
|
|
208
177
|
|
|
@@ -218,14 +187,12 @@ npm run prepublishOnly
|
|
|
218
187
|
npm run test:package
|
|
219
188
|
```
|
|
220
189
|
|
|
221
|
-
新增规则须包含应检出与不应检出的 [夹具](./test/fixtures/)。运行离线评估:
|
|
222
|
-
|
|
223
190
|
```powershell
|
|
224
191
|
npm run evaluate
|
|
225
192
|
```
|
|
226
193
|
|
|
227
|
-
|
|
194
|
+
新增规则需包含应检出和不应检出的 [夹具](./test/fixtures/)。固定项目评估见 [清单](./test/evaluation/projects.json)、[获取脚本](./scripts/fetch-evaluation-projects.mjs)、[评估器](./scripts/evaluate-projects.ts)。样本通过不代表真实检出率。
|
|
228
195
|
|
|
229
196
|
## 许可
|
|
230
197
|
|
|
231
|
-
[MIT](./LICENSE)。Supabase/Firebase 夹具保留 Apache-2.0,Next.js/`cors` 夹具保留 MIT
|
|
198
|
+
[MIT](./LICENSE)。Supabase/Firebase 夹具保留 Apache-2.0,Next.js/`cors` 夹具保留 MIT。
|