canship 0.7.1 → 0.8.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 +58 -141
- package/README.md +58 -141
- package/dist/cli.js +3809 -665
- package/dist/index.d.ts +78 -8
- package/dist/index.js +1127 -72
- package/docs/framework-support-zh-CN.md +95 -0
- package/docs/framework-support.md +95 -0
- package/docs/reference-zh-CN.md +221 -0
- package/docs/reference.md +221 -0
- package/package.json +13 -2
- package/schemas/config-v1.schema.json +114 -0
- package/schemas/scan-report-v1.schema.json +19 -1
package/README-zh-CN.md
CHANGED
|
@@ -1,114 +1,71 @@
|
|
|
1
1
|
# canship
|
|
2
2
|
|
|
3
|
-
面向 JavaScript / TypeScript Web
|
|
3
|
+
面向 JavaScript / TypeScript Web 应用的发布前安全检查工具。Canship 在源码中查找凭据泄露、缺失的访问控制及不安全的请求输入处理,并可选择对你拥有的部署进行校验。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
静态扫描在本地运行:只读、不执行项目代码、不发起网络请求。部署校验是独立的可选模式,只访问经你确认的目标。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[English](./README.md) · [使用参考](./docs/reference-zh-CN.md) · [发布说明](https://github.com/Tasomei/canship/releases) · [npm](https://www.npmjs.com/package/canship)
|
|
8
|
+
|
|
9
|
+
> 本文对应 npm `latest` 渠道的 `0.8.0`。其他版本见[发布说明](https://github.com/Tasomei/canship/releases)。
|
|
8
10
|
|
|
9
11
|
## 快速开始
|
|
10
12
|
|
|
13
|
+
要求 Node.js 18 及以上,无运行时依赖。
|
|
14
|
+
|
|
11
15
|
```powershell
|
|
12
|
-
npx canship
|
|
16
|
+
npx canship@0.8.0
|
|
13
17
|
```
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
扫描指定目录:
|
|
20
|
+
|
|
21
|
+
```powershell
|
|
22
|
+
npx canship@0.8.0 "./my-app"
|
|
23
|
+
```
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
合成项目的输出示例:
|
|
18
26
|
|
|
19
27
|

|
|
20
28
|
|
|
21
29
|
## 检测范围
|
|
22
30
|
|
|
23
|
-
| 类别 | 级别 |
|
|
31
|
+
| 类别 | 级别 | 内容 |
|
|
24
32
|
|---|:---:|---|
|
|
25
|
-
| 凭据 | `P0` |
|
|
26
|
-
| API 访问 | `P0/P1` | 未识别到鉴权的数据库操作、服务端信任 Supabase `getSession()
|
|
27
|
-
| 数据库规则 | `P1/P2` | Supabase
|
|
28
|
-
| CORS | `P1/P2` |
|
|
29
|
-
|
|
|
30
|
-
|
|
31
|
-
凭据格式包括 OpenAI、Anthropic、AWS、Stripe、GitHub、npm 等。Firebase 覆盖 Firestore、Storage、Realtime Database。`--list-rules` 列出规则 ID、范围及局限。
|
|
33
|
+
| 凭据 | `P0` | 硬编码密钥、公开环境变量中的密钥、Supabase 服务密钥、被 Git 跟踪或存在于历史中的 `.env` 文件 |
|
|
34
|
+
| API 访问 | `P0/P1` | 未识别到鉴权的数据库操作、服务端信任 Supabase `getSession()`、未验签的 Stripe webhook |
|
|
35
|
+
| 数据库规则 | `P1/P2` | 未启用 Supabase RLS、过宽的策略、公开存储列表、开放的 Firebase 规则 |
|
|
36
|
+
| CORS | `P1/P2` | 携带凭据时回显来源或使用通配符 |
|
|
37
|
+
| 代码(Code) | `P1/P2` | 由请求输入拼接的 SQL 与 shell 命令;向调用方指定地址发起的服务端请求和重定向 |
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
路由分析覆盖 Next.js、SvelteKit、Nuxt、Remix / React Router、Astro、Express、Hono、Fastify 的指定入口,详见[入口及限制](./docs/reference-zh-CN.md#服务端入口)。
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
| SvelteKit | `+server` 端点、`+page.server` 表单 action |
|
|
39
|
-
| Nuxt | `server/api`、`server/routes` |
|
|
40
|
-
| Remix / React Router | `app/routes` 中的 `loader`、`action` 导出 |
|
|
41
|
-
| Astro | `src/pages` 中的端点 |
|
|
42
|
-
| Express | `app`/`Router` 路由,含 `.route()` 链、挂载的子路由和其他文件中的控制器 |
|
|
43
|
-
| Hono | `app.get()` 等路由、链式调用、`basePath`,以及 `app.route()` 挂载的子应用 |
|
|
44
|
-
| Fastify | 简写与 `route()` 声明、`register()` 前缀与封装作用域、`@fastify/autoload` 目录 |
|
|
45
|
-
|
|
46
|
-
已识别的 Next.js/Astro 中间件可抑制匹配路由的鉴权结果;Server Function 需在函数内检查。Express/Hono/Fastify 仅接受已解析的拒绝逻辑或已知鉴权库。Fastify 装饰器和插件的保护证据限定于当前实例。
|
|
47
|
-
|
|
48
|
-
会话校验及 webhook 验签(Stripe、Polar、Clerk、Svix、QStash)须在失败时拒绝请求,异步调用须等待或返回。项目辅助函数与包装器、SvelteKit hooks、Nuxt 中间件的间接证据可降低置信度;未解析的鉴权来源不能消除结果。
|
|
41
|
+
```powershell
|
|
42
|
+
npx canship@0.8.0 --list-rules
|
|
43
|
+
```
|
|
49
44
|
|
|
50
|
-
|
|
45
|
+
## 审阅结果
|
|
51
46
|
|
|
52
|
-
|
|
47
|
+
每条结果标为 `certain`(静态证据充分)或 `likely`(需人工审阅),默认只显示 `certain`。两者都不代表凭据有效或问题可被利用。
|
|
53
48
|
|
|
54
|
-
|
|
49
|
+
```powershell
|
|
50
|
+
npx canship@0.8.0 --all --verbose
|
|
51
|
+
```
|
|
55
52
|
|
|
56
|
-
|
|
53
|
+
```powershell
|
|
54
|
+
npx canship@0.8.0 --all --report
|
|
55
|
+
```
|
|
57
56
|
|
|
58
57
|

|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
离线 HTML 报告支持筛选和复制修复提示;`--fix-prompt` 在终端输出同样的说明。报告包含文件路径,也可能包含源码摘录:`--no-excerpts` 去除摘录,`--share-summary` 仅输出计数。可下载[合成示例报告](https://github.com/Tasomei/canship/blob/main/docs/demo.html)查看。
|
|
61
60
|
|
|
62
61
|
| 退出码 | 含义 |
|
|
63
62
|
|---|---|
|
|
64
|
-
| `0` |
|
|
63
|
+
| `0` | 无结果,且覆盖完整(或经 `--best-effort` 接受不完整覆盖) |
|
|
65
64
|
| `1` | 至少一条 `certain` 的 P0/P1 结果 |
|
|
66
|
-
| `2` |
|
|
67
|
-
| `3` |
|
|
68
|
-
|
|
69
|
-
退出码基于规则筛选、忽略注释和基线处理后的结果。有结果时优先于扫描不完整;`--best-effort` 不改变 `1` 或 `2`。
|
|
70
|
-
|
|
71
|
-
## 命令行
|
|
72
|
-
|
|
73
|
-
`npx canship [path] [options]`
|
|
74
|
-
|
|
75
|
-
| 参数 | 作用 |
|
|
76
|
-
|---|---|
|
|
77
|
-
| `-a`、`--all` | 包含 `likely` 结果 |
|
|
78
|
-
| `--verbose` | 展开终端结果 |
|
|
79
|
-
| `--report[=file]` | 写入 HTML,默认 `canship-report.html` |
|
|
80
|
-
| `--open` | 打开 `--report` 输出;CI 和非交互终端中禁用 |
|
|
81
|
-
| `--json` | 输出 JSON |
|
|
82
|
-
| `--sarif[=file]` | 写入 SARIF 2.1.0,默认 `canship.sarif` |
|
|
83
|
-
| `--fix-prompt` | 输出修复指令及独立的人工操作清单 |
|
|
84
|
-
| `--no-excerpts` | 移除所有报告中的摘录 |
|
|
85
|
-
| `--changed-since=ref` | 展示变更文件结果,保留全量扫描退出码 |
|
|
86
|
-
| `--only=ids` / `--skip=ids` | 选择或排除规则及命名空间,逗号分隔,可重复 |
|
|
87
|
-
| `--list-rules` | 列出规则而不扫描,支持 `--json` |
|
|
88
|
-
| `--baseline[=file]` / `--baseline-write[=file]` | 抑制或记录结果,默认 `canship-baseline.json` |
|
|
89
|
-
| `--no-config` / `--no-ignore-markers` | 忽略项目配置或源码抑制注释 |
|
|
90
|
-
| `--best-effort` | 允许没有结果的不完整扫描退出 `0` |
|
|
91
|
-
| `-h`、`--help` / `-v`、`--version` | 显示帮助或版本 |
|
|
92
|
-
|
|
93
|
-
`--json` 与 `--fix-prompt` 互斥,均可同时输出 HTML 和 SARIF。
|
|
94
|
-
|
|
95
|
-
`--changed-since` 比较本地共同祖先与工作区,包含未被忽略的新文件,不拉取远程、不缩小扫描范围。缺少 Git、引用或共同历史时退出 `3`;不能与 `--baseline-write` 组合。
|
|
96
|
-
|
|
97
|
-
## 配置
|
|
98
|
-
|
|
99
|
-
`canship.config.json` 支持 `baseline`、`only`、`skip`、`all`。命令行参数优先,`only` 与 `skip` 互斥。
|
|
100
|
-
|
|
101
|
-
```json
|
|
102
|
-
{ "skip": ["cors/wildcard-with-credentials"], "all": false }
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
独占行注释 `canship-ignore-file` 排除整个文件;`canship-ignore-next-line [rule]` 抑制下一行,可限定单条规则。报告披露排除项;主动抑制不标记扫描不完整,可能使退出码降为 `0`。扫描不可信项目时使用 `--no-config --no-ignore-markers`。
|
|
106
|
-
|
|
107
|
-
基线表示接受已有结果,不代表问题已修复。v2 格式不受行号移动影响,但凭据变化会重新报告。
|
|
65
|
+
| `2` | 其他结果,包括被隐藏的 `likely` |
|
|
66
|
+
| `3` | 输入无效、工具错误或覆盖不完整 |
|
|
108
67
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
## GitHub Action
|
|
68
|
+
## 接入 CI
|
|
112
69
|
|
|
113
70
|
保存为 `.github/workflows/canship.yml`:
|
|
114
71
|
|
|
@@ -125,78 +82,38 @@ jobs:
|
|
|
125
82
|
with:
|
|
126
83
|
fetch-depth: 0
|
|
127
84
|
persist-credentials: false
|
|
128
|
-
- uses: Tasomei/canship@
|
|
85
|
+
- uses: Tasomei/canship@8ae4d5f4508fbd68fc2cf440e138c1217064a0e0
|
|
129
86
|
with:
|
|
130
|
-
version: '0.
|
|
87
|
+
version: '0.8.0'
|
|
131
88
|
honor-ignore-markers: false
|
|
132
89
|
```
|
|
133
90
|
|
|
134
|
-
提交哈希固定 Action 实现,`version`
|
|
91
|
+
提交哈希固定 Action 实现,`version` 固定 npm 扫描器版本。Action 不安装项目依赖,只输出计数摘要;扫描不完整或工具出错时始终失败。SARIF 上传需显式开启。
|
|
135
92
|
|
|
136
|
-
| 输入 |
|
|
93
|
+
| 输入 | 固定 Action 的默认值 | 含义 |
|
|
137
94
|
|---|---|---|
|
|
138
|
-
| `version` | `0.
|
|
139
|
-
| `fail-on` | `blocking` | `blocking
|
|
140
|
-
|
|
141
|
-
扫描不完整或工具错误始终失败。默认不读取项目配置、不上传 SARIF。输入输出见 [action.yml](./action.yml)。
|
|
142
|
-
|
|
143
|
-
上传 SARIF 需 `security-events: write` 及代码扫描支持,fork PR 可能权限不足;上传前应审阅报告。不可信 PR 使用 `pull_request`,不要使用 `pull_request_target`。
|
|
144
|
-
|
|
145
|
-
## API 与结构化输出
|
|
146
|
-
|
|
147
|
-
```js
|
|
148
|
-
import { scan, summarize } from 'canship'
|
|
149
|
-
|
|
150
|
-
const result = await scan('./my-app', { noExcerpts: true })
|
|
151
|
-
console.log(summarize(result))
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
`scan()` 返回全部置信度结果,支持 `only`、`skip`、`honorIgnoreMarkers`(默认 `true`)、`noExcerpts`(默认 `false`)。不加载配置、不应用基线、不写报告、不设置进程退出码;无效参数抛出异常。`listRules()` 返回规则目录。
|
|
155
|
-
|
|
156
|
-
JSON 使用 [schemaVersion 1](./schemas/scan-report-v1.schema.json)。须独立于退出码检查 `partial`、`errors`、`skipped`、`filesScanned`。SARIF 包含证据位置和执行诊断。
|
|
157
|
-
|
|
158
|
-
## 隐私与限制
|
|
159
|
-
|
|
160
|
-
- 静态检查可能误报或漏报,不验证业务授权、限流、依赖漏洞或线上配置。
|
|
161
|
-
- 脱敏仅覆盖已识别格式,未知敏感值可能保留在摘录中;`--no-excerpts` 可移除摘录。路径、名称和基线描述仍可见。
|
|
162
|
-
- Google/Firebase/Maps 的 `AIza…` 密钥按公开标识符处理,不单凭其值判定泄露。Supabase 检查依据本地迁移及支持的存储桶配置。
|
|
163
|
-
- 评估快照获取和可选的 SARIF 上传可能联网。
|
|
164
|
-
- 不跟随符号链接;嵌套仓库与子模块需单独扫描。范围内跳过项及分析超限标记扫描不完整;鉴权辅助函数解析超限不会隐藏结果,改为在受影响的结果上注明。默认排除的依赖和构建目录不计为扫描缺口。
|
|
95
|
+
| `version` | `0.8.0` | 精确的 npm 扫描器版本;请如上例显式设置 |
|
|
96
|
+
| `fail-on` | `blocking` | `blocking`:`certain` 的 P0/P1;`any`:全部结果;`none`:仅报告 |
|
|
165
97
|
|
|
166
|
-
|
|
167
|
-
|---|---|
|
|
168
|
-
| 文件读取 | 单文件 2 MiB;单次 128 MiB、10,000 个文件,含探测 |
|
|
169
|
-
| 目录遍历 | 50,000 个条目;16 层 |
|
|
170
|
-
| 结果 | 每文件 100 条,优先保留高严重度、高置信度结果 |
|
|
171
|
-
| Git 历史 | 每文件 100 个相关版本;单条命令 30 秒 |
|
|
172
|
-
| 鉴权辅助函数解析 | 8 跳;每个辅助函数 64 个符号,每个路由文件共 1,024 个 |
|
|
173
|
-
| 委托写入 | 调用 2 层;每个文件 256 个被调函数;超出部分的写入不报告 |
|
|
174
|
-
| 身份/控制流 | 值解析 8 步;表达式 4,000 字符;每函数 512 个赋值/区域;区域嵌套 8 层 |
|
|
175
|
-
| 请求输入追踪 | 值解析 8 步;512 个赋值/区域;单条表达式 64 KiB;URL 分析 8 层、静态前缀 200 字符 |
|
|
176
|
-
| Supabase 策略/存储桶解析 | 单条语句 4,000 字符 |
|
|
177
|
-
|
|
178
|
-
证据链最多 24 步,截断时提示。
|
|
98
|
+
完整说明见 [Action 输入](https://github.com/Tasomei/canship/blob/main/action.yml)。
|
|
179
99
|
|
|
180
|
-
##
|
|
100
|
+
## 扫描之外
|
|
181
101
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
102
|
+
- **基线**:接受已审阅的结果,可附理由和到期时间,见[基线管理](./docs/reference-zh-CN.md#配置)。
|
|
103
|
+
- **报告比较**:比较两份已保存的 JSON 报告,列出新增、持续存在和不再出现的结果,见[命令参考](./docs/reference-zh-CN.md#命令行)。
|
|
104
|
+
- **工作区与配置**:独立扫描 monorepo 子项目、排除路径,并用 `--explain-config` 或 `--doctor` 查看生效设置。
|
|
105
|
+
- **模板**:用 `--init` 预览 CI 与 pre-commit 配置。pre-commit 钩子扫描工作区,而非暂存区快照。
|
|
106
|
+
- **部署校验**:`--probe=https://…` 预览少量无认证的 HTTPS 请求,确认计划前不会发出任何请求。使用前请阅读[范围与隐私说明](./docs/reference-zh-CN.md#部署校验)。
|
|
107
|
+
- **API 与编辑器**:[编程接口](./docs/reference-zh-CN.md#api-与结构化输出)及 [VS Code 插件预览版](https://github.com/Tasomei/canship/tree/main/extensions/vscode#readme)。
|
|
185
108
|
|
|
186
|
-
|
|
187
|
-
npm run prepublishOnly
|
|
188
|
-
```
|
|
109
|
+
## 限制
|
|
189
110
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
```powershell
|
|
195
|
-
npm run evaluate
|
|
196
|
-
```
|
|
111
|
+
- 静态分析可能漏报或误报有意为之的配置,不评估业务授权、限流或依赖漏洞。
|
|
112
|
+
- 脱敏仅覆盖已识别的密钥格式。详细报告和基线应作为内部资料处理。
|
|
113
|
+
- Google 与 Firebase 的 `AIza…` 密钥属于公开标识符,不单独作为泄露报告。
|
|
197
114
|
|
|
198
|
-
|
|
115
|
+
详见[隐私与覆盖限制](./docs/reference-zh-CN.md#隐私与限制)。
|
|
199
116
|
|
|
200
|
-
##
|
|
117
|
+
## 开发与许可
|
|
201
118
|
|
|
202
|
-
[MIT](./LICENSE)
|
|
119
|
+
见[开发参考](./docs/reference-zh-CN.md#开发)。采用 [MIT](./LICENSE) 许可;Supabase 与 Firebase 测试夹具保留 Apache-2.0,Next.js 与 `cors` 夹具保留 MIT。
|
package/README.md
CHANGED
|
@@ -1,114 +1,71 @@
|
|
|
1
1
|
# canship
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Pre-deployment security checks for JavaScript and TypeScript web applications. Canship finds exposed credentials, missing access controls and unsafe handling of request input in your source code, and can optionally probe a deployment you own.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Static scans run locally: they are read-only, execute no project code and make no network requests. Deployment probes are a separate, opt-in mode that contacts only a target you confirm.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[简体中文](./README-zh-CN.md) · [Reference](./docs/reference.md) · [Releases](https://github.com/Tasomei/canship/releases) · [npm](https://www.npmjs.com/package/canship)
|
|
8
|
+
|
|
9
|
+
> Documentation for `0.8.0` on npm `latest`. Other versions are listed under [Releases](https://github.com/Tasomei/canship/releases).
|
|
8
10
|
|
|
9
11
|
## Quick start
|
|
10
12
|
|
|
13
|
+
Requires Node.js 18 or later; no runtime dependencies.
|
|
14
|
+
|
|
11
15
|
```powershell
|
|
12
|
-
npx canship
|
|
16
|
+
npx canship@0.8.0
|
|
13
17
|
```
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
Scan a specific directory:
|
|
20
|
+
|
|
21
|
+
```powershell
|
|
22
|
+
npx canship@0.8.0 "./my-app"
|
|
23
|
+
```
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
Example output for a synthetic project:
|
|
18
26
|
|
|
19
27
|

|
|
20
28
|
|
|
21
29
|
## Checks
|
|
22
30
|
|
|
23
|
-
| Category | Severity |
|
|
31
|
+
| Category | Severity | Covers |
|
|
24
32
|
|---|:---:|---|
|
|
25
|
-
| Credentials | `P0` | Hardcoded
|
|
33
|
+
| Credentials | `P0` | Hardcoded secrets, secrets in public environment variables, Supabase service keys, `.env` files tracked by Git or present in history |
|
|
26
34
|
| API access | `P0/P1` | Database operations without recognised authentication, server-side trust in Supabase `getSession()`, unverified Stripe webhooks |
|
|
27
|
-
| Database rules | `P1/P2` | Supabase
|
|
28
|
-
| CORS | `P1/P2` | Reflected or wildcard origins with credentials |
|
|
29
|
-
|
|
|
30
|
-
|
|
31
|
-
Credential formats include OpenAI, Anthropic, AWS, Stripe, GitHub, and npm. Firebase covers Firestore, Storage, and Realtime Database. `--list-rules` lists rule IDs, scope, and limitations.
|
|
35
|
+
| Database rules | `P1/P2` | Missing Supabase RLS, permissive policies, public storage listing, open Firebase rules |
|
|
36
|
+
| CORS | `P1/P2` | Reflected or wildcard origins combined with credentials |
|
|
37
|
+
| Code | `P1/P2` | SQL and shell commands built from request input; server-side requests and redirects to caller-chosen URLs |
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
Route analysis covers documented entry points in Next.js, SvelteKit, Nuxt, Remix / React Router, Astro, Express, Hono and Fastify. See [entry points and limits](./docs/reference.md#server-entry-points).
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
| SvelteKit | `+server` endpoints and `+page.server` form actions |
|
|
39
|
-
| Nuxt | `server/api`, `server/routes` |
|
|
40
|
-
| Remix / React Router | `loader` and `action` exports in `app/routes` |
|
|
41
|
-
| Astro | Endpoints in `src/pages` |
|
|
42
|
-
| Express | `app`/`Router` routes, including `.route()` chains, mounted routers, and controllers in other files |
|
|
43
|
-
| Hono | `app.get()`-style routes, chains, `basePath`, and sub-apps mounted with `app.route()` |
|
|
44
|
-
| Fastify | Shorthand and `route()` declarations, `register()` prefixes and encapsulation, `@fastify/autoload` directories |
|
|
45
|
-
|
|
46
|
-
Recognised Next.js/Astro middleware may suppress covered auth findings; Server Functions need local checks. Express/Hono/Fastify require resolved rejection logic or known auth libraries. Fastify decorator and plugin evidence is scoped to the local instance.
|
|
47
|
-
|
|
48
|
-
Session checks and webhook verification (Stripe, Polar, Clerk, Svix, QStash) must reject failures; asynchronous calls must be awaited or returned. Indirect evidence from project helpers/wrappers, SvelteKit hooks, or Nuxt middleware may lower confidence. Unresolved auth sources do not suppress findings.
|
|
41
|
+
```powershell
|
|
42
|
+
npx canship@0.8.0 --list-rules
|
|
43
|
+
```
|
|
49
44
|
|
|
50
|
-
|
|
45
|
+
## Reviewing findings
|
|
51
46
|
|
|
52
|
-
|
|
47
|
+
Each finding is rated `certain` (strong static evidence) or `likely` (needs review); only `certain` findings are shown by default. Neither rating proves that a credential is valid or that an issue is exploitable.
|
|
53
48
|
|
|
54
|
-
|
|
49
|
+
```powershell
|
|
50
|
+
npx canship@0.8.0 --all --verbose
|
|
51
|
+
```
|
|
55
52
|
|
|
56
|
-
|
|
53
|
+
```powershell
|
|
54
|
+
npx canship@0.8.0 --all --report
|
|
55
|
+
```
|
|
57
56
|
|
|
58
57
|

|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
The offline HTML report supports filtering and copyable repair prompts; `--fix-prompt` prints the same instructions in the terminal. Reports include file paths and may include source excerpts: use `--no-excerpts` to omit excerpts, or `--share-summary` for counts only. A [synthetic sample report](https://github.com/Tasomei/canship/blob/main/docs/demo.html) is available for download.
|
|
61
60
|
|
|
62
|
-
| Exit | Meaning |
|
|
61
|
+
| Exit code | Meaning |
|
|
63
62
|
|---|---|
|
|
64
|
-
| `0` | No findings
|
|
63
|
+
| `0` | No findings, with complete coverage (or incomplete coverage accepted via `--best-effort`) |
|
|
65
64
|
| `1` | At least one `certain` P0/P1 finding |
|
|
66
|
-
| `2` | Other findings, including hidden `likely`
|
|
67
|
-
| `3` | Invalid
|
|
68
|
-
|
|
69
|
-
Status is calculated after rule selection, ignore comments, and baselines. Findings take precedence over incomplete coverage; `--best-effort` never changes `1` or `2`.
|
|
70
|
-
|
|
71
|
-
## CLI
|
|
72
|
-
|
|
73
|
-
`npx canship [path] [options]`
|
|
74
|
-
|
|
75
|
-
| Option | Effect |
|
|
76
|
-
|---|---|
|
|
77
|
-
| `-a`, `--all` | Include `likely` findings |
|
|
78
|
-
| `--verbose` | Expand terminal findings |
|
|
79
|
-
| `--report[=file]` | Write HTML; default `canship-report.html` |
|
|
80
|
-
| `--open` | Open `--report` output; disabled in CI and non-interactive shells |
|
|
81
|
-
| `--json` | Print JSON |
|
|
82
|
-
| `--sarif[=file]` | Write SARIF 2.1.0; default `canship.sarif` |
|
|
83
|
-
| `--fix-prompt` | Print repair instructions and separate manual actions |
|
|
84
|
-
| `--no-excerpts` | Remove excerpts from all reports |
|
|
85
|
-
| `--changed-since=ref` | Show changed-file findings; preserve full-scan status |
|
|
86
|
-
| `--only=ids` / `--skip=ids` | Select/exclude rules or namespaces; comma-separated, repeatable |
|
|
87
|
-
| `--list-rules` | List rules without scanning; supports `--json` |
|
|
88
|
-
| `--baseline[=file]` / `--baseline-write[=file]` | Suppress/record findings; default `canship-baseline.json` |
|
|
89
|
-
| `--no-config` / `--no-ignore-markers` | Ignore project configuration/source suppression comments |
|
|
90
|
-
| `--best-effort` | Allow incomplete coverage with no findings to exit `0` |
|
|
91
|
-
| `-h`, `--help` / `-v`, `--version` | Show help/version |
|
|
92
|
-
|
|
93
|
-
`--json` and `--fix-prompt` are mutually exclusive; either supports HTML and SARIF output.
|
|
94
|
-
|
|
95
|
-
`--changed-since` compares the local merge base with the working tree, including non-ignored untracked files. It does not fetch or narrow scan scope. Missing Git, refs, or shared history exits `3`; it cannot be combined with `--baseline-write`.
|
|
96
|
-
|
|
97
|
-
## Configuration
|
|
98
|
-
|
|
99
|
-
`canship.config.json` accepts `baseline`, `only`, `skip`, and `all`. CLI options take precedence; `only` and `skip` are mutually exclusive.
|
|
100
|
-
|
|
101
|
-
```json
|
|
102
|
-
{ "skip": ["cors/wildcard-with-credentials"], "all": false }
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
A standalone `canship-ignore-file` comment excludes a file. `canship-ignore-next-line [rule]` suppresses the next line, optionally for one rule. Exclusions are disclosed and may reduce status to `0` without marking coverage incomplete. For untrusted projects, use `--no-config --no-ignore-markers`.
|
|
106
|
-
|
|
107
|
-
Baselines accept existing findings without fixing them. Format v2 tolerates line moves but reports credential changes.
|
|
65
|
+
| `2` | Other findings, including hidden `likely` findings |
|
|
66
|
+
| `3` | Invalid input, tool error, or incomplete coverage |
|
|
108
67
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
## GitHub Action
|
|
68
|
+
## Continuous integration
|
|
112
69
|
|
|
113
70
|
Save as `.github/workflows/canship.yml`:
|
|
114
71
|
|
|
@@ -125,78 +82,38 @@ jobs:
|
|
|
125
82
|
with:
|
|
126
83
|
fetch-depth: 0
|
|
127
84
|
persist-credentials: false
|
|
128
|
-
- uses: Tasomei/canship@
|
|
85
|
+
- uses: Tasomei/canship@8ae4d5f4508fbd68fc2cf440e138c1217064a0e0
|
|
129
86
|
with:
|
|
130
|
-
version: '0.
|
|
87
|
+
version: '0.8.0'
|
|
131
88
|
honor-ignore-markers: false
|
|
132
89
|
```
|
|
133
90
|
|
|
134
|
-
The commit hash pins the Action
|
|
91
|
+
The commit hash pins the Action and `version` pins the npm scanner. The Action does not install project dependencies and writes a counts-only job summary; it always fails on incomplete scans or tool errors. SARIF upload is opt-in.
|
|
135
92
|
|
|
136
|
-
| Input | Default | Meaning |
|
|
93
|
+
| Input | Default in the pinned Action | Meaning |
|
|
137
94
|
|---|---|---|
|
|
138
|
-
| `version` | `0.
|
|
139
|
-
| `fail-on` | `blocking` | `blocking`: certain P0/P1; `any`: all findings; `none`: report only |
|
|
140
|
-
|
|
141
|
-
Incomplete scans and tool errors always fail. Project configuration and SARIF upload are disabled by default. Inputs and outputs: [action.yml](./action.yml).
|
|
142
|
-
|
|
143
|
-
SARIF upload requires `security-events: write` and code scanning support; fork PRs may lack permission. Review reports before upload. Use `pull_request`, not `pull_request_target`, for untrusted PRs.
|
|
144
|
-
|
|
145
|
-
## API and structured output
|
|
146
|
-
|
|
147
|
-
```js
|
|
148
|
-
import { scan, summarize } from 'canship'
|
|
149
|
-
|
|
150
|
-
const result = await scan('./my-app', { noExcerpts: true })
|
|
151
|
-
console.log(summarize(result))
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
`scan()` returns all confidence levels. Options: `only`, `skip`, `honorIgnoreMarkers` (default `true`), `noExcerpts` (default `false`). It does not load configuration, apply baselines, write reports, or set process exit status. Invalid arguments throw. `listRules()` returns the rule catalogue.
|
|
155
|
-
|
|
156
|
-
JSON uses [schemaVersion 1](./schemas/scan-report-v1.schema.json). Check `partial`, `errors`, `skipped`, and `filesScanned` independently of exit status. SARIF includes evidence locations and execution diagnostics.
|
|
157
|
-
|
|
158
|
-
## Privacy and limits
|
|
159
|
-
|
|
160
|
-
- Static checks may miss issues or flag intentional configurations. Business authorisation, rate limiting, dependency vulnerabilities, and deployed settings are not verified.
|
|
161
|
-
- Redaction covers recognised formats only. Unknown secrets may remain in excerpts; `--no-excerpts` omits excerpts. Paths, names, and baseline descriptions remain visible.
|
|
162
|
-
- Google/Firebase/Maps `AIza…` keys are treated as public identifiers, not leak evidence alone. Supabase checks use local migrations and supported bucket configuration.
|
|
163
|
-
- Evaluation snapshot downloads and optional SARIF uploads may use the network.
|
|
164
|
-
- Symbolic links are not followed; nested repositories and submodules need separate scans. In-scope skipped paths and analysis limits mark coverage incomplete; auth helper resolution limits are noted on the affected finding instead, because they cannot hide findings. Dependency and build directories excluded by default do not count as coverage gaps.
|
|
95
|
+
| `version` | `0.8.0` | Exact npm scanner version; set explicitly as above |
|
|
96
|
+
| `fail-on` | `blocking` | `blocking`: `certain` P0/P1; `any`: all findings; `none`: report only |
|
|
165
97
|
|
|
166
|
-
|
|
167
|
-
|---|---|
|
|
168
|
-
| File reads | 2 MiB per file; 128 MiB and 10,000 files per scan, including probes |
|
|
169
|
-
| Directory discovery | 50,000 entries; 16 levels |
|
|
170
|
-
| Findings | 100 per file, prioritising severity and confidence |
|
|
171
|
-
| Git history | 100 relevant revisions per file; 30 seconds per command |
|
|
172
|
-
| Auth helper resolution | 8 hops; 64 symbols per helper, 1,024 per route file |
|
|
173
|
-
| Delegated writes | 2 call levels; 256 callees per file; writes beyond these limits are not reported |
|
|
174
|
-
| Identity/control flow | 8 value hops; 4,000 expression characters; 512 assignments/regions per function; 8 nested regions |
|
|
175
|
-
| Request-input tracking | 8 value hops; 512 assignments/regions; 64 KiB per expression; 8 URL-analysis levels; 200 static-prefix characters |
|
|
176
|
-
| Supabase policy/bucket parsing | 4,000 characters per statement |
|
|
177
|
-
|
|
178
|
-
Evidence traces are capped at 24 steps and disclose truncation.
|
|
98
|
+
See all [Action inputs](https://github.com/Tasomei/canship/blob/main/action.yml).
|
|
179
99
|
|
|
180
|
-
##
|
|
100
|
+
## Beyond scanning
|
|
181
101
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
102
|
+
- **Baselines**: accept reviewed findings with an optional reason and expiry date. See [baseline management](./docs/reference.md#configuration).
|
|
103
|
+
- **Report comparison**: compare two saved JSON reports to list added, persisting and no-longer-observed findings. See the [CLI reference](./docs/reference.md#cli).
|
|
104
|
+
- **Workspaces and configuration**: scan monorepo packages independently, exclude paths, and inspect effective settings with `--explain-config` or `--doctor`.
|
|
105
|
+
- **Templates**: preview CI and pre-commit setups with `--init`. The pre-commit hook scans the working tree, not the staged snapshot.
|
|
106
|
+
- **Deployment probes**: `--probe=https://…` previews a small set of unauthenticated HTTPS requests; nothing is sent until you confirm the plan. Review the [scope and privacy notes](./docs/reference.md#deployment-probes) first.
|
|
107
|
+
- **API and editor**: a [programmatic API](./docs/reference.md#api-and-structured-output) and a [VS Code extension preview](https://github.com/Tasomei/canship/tree/main/extensions/vscode#readme).
|
|
185
108
|
|
|
186
|
-
|
|
187
|
-
npm run prepublishOnly
|
|
188
|
-
```
|
|
109
|
+
## Limitations
|
|
189
110
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
```powershell
|
|
195
|
-
npm run evaluate
|
|
196
|
-
```
|
|
111
|
+
- Static analysis can miss issues or flag intentional configurations. It does not assess business authorisation, rate limiting or dependency vulnerabilities.
|
|
112
|
+
- Redaction covers recognised secret formats only. Treat detailed reports and baselines as internal material.
|
|
113
|
+
- Google and Firebase `AIza…` keys are public identifiers and are not reported as leaks on their own.
|
|
197
114
|
|
|
198
|
-
|
|
115
|
+
See [privacy and coverage limits](./docs/reference.md#privacy-and-limits).
|
|
199
116
|
|
|
200
|
-
##
|
|
117
|
+
## Development and license
|
|
201
118
|
|
|
202
|
-
[MIT](./LICENSE)
|
|
119
|
+
See the [development reference](./docs/reference.md#development). Licensed under [MIT](./LICENSE); Supabase and Firebase test fixtures retain Apache-2.0, and Next.js and `cors` fixtures retain MIT.
|