ai-saas-guard 0.30.1 → 0.30.2
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 +7 -5
- package/dist/scanners/actions.js +11 -1
- package/dist/scanners/deploy.js +9 -2
- package/docs/README.zh-CN.md +7 -5
- package/docs/hosted-operational-release-gate.md +21 -0
- package/docs/hosted-operations-evidence.md +16 -0
- package/docs/launch-gate-positioning.md +33 -0
- package/docs/npm-publishing.md +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -124,6 +124,8 @@ One command returns a launch-readiness report with:
|
|
|
124
124
|
| Are tools and CI overpowered? | MCP side-effect classes, local policy/receipt templates, GitHub Actions permissions, concurrency, checkout depth, action pinning |
|
|
125
125
|
| Can reviewers trust the PR? | `pr-risk` ranking for auth, billing, RLS, deploy, API, storage, tests, silent-success paths, missing spec context, and large AI diffs |
|
|
126
126
|
|
|
127
|
+
For a concise comparison with Semgrep, zizmor, OpenSSF Scorecard, Snyk, and GitHub code scanning, see [docs/launch-gate-positioning.md](docs/launch-gate-positioning.md).
|
|
128
|
+
|
|
127
129
|
## Quick Start
|
|
128
130
|
|
|
129
131
|
Run the published CLI without installing it globally:
|
|
@@ -185,13 +187,13 @@ The CLI is published on npm as `ai-saas-guard`, and the GitHub Action is availab
|
|
|
185
187
|
| Area | Status |
|
|
186
188
|
| --- | --- |
|
|
187
189
|
| Public GitHub repository | Available |
|
|
188
|
-
| npm CLI | `ai-saas-guard@0.30.
|
|
189
|
-
| GitHub Action | `zr9959/ai-saas-guard@v0` or fixed tag `v0.30.
|
|
190
|
+
| npm CLI | `ai-saas-guard@0.30.2` |
|
|
191
|
+
| GitHub Action | `zr9959/ai-saas-guard@v0` or fixed tag `v0.30.2` |
|
|
190
192
|
| Outputs | Short summary, terminal, JSON, SARIF, and PR-focused markdown |
|
|
191
193
|
| Project config | `.ai-saas-guard.json` rule toggles, severity overrides, suppressions, and fail thresholds |
|
|
192
194
|
| Privacy model | Local-first, read-only scan commands, no LLM calls, no code upload |
|
|
193
|
-
| Versioned Action tags | `v0.30.
|
|
194
|
-
| Current release | `0.30.
|
|
195
|
+
| Versioned Action tags | `v0.30.2`, `v0` |
|
|
196
|
+
| Current release | `0.30.2` adds post-release quality tuning: lower-noise Vercel/Actions checks, focused launch-gate positioning docs, and hosted worker evidence boundaries |
|
|
195
197
|
| npm publishing | Trusted Publisher/OIDC, no long-lived publish token |
|
|
196
198
|
| Repository trust hardening | Strict branch protection, Dependabot, CodeQL, fast-check fuzzing, signed release provenance assets, private vulnerability reporting, secret scanning, and push protection |
|
|
197
199
|
| Cloudflare hosted ingress | Deployed at `https://ai-saas-guard-hosted.zr9959.workers.dev`; signed GitHub App webhook delivery and compact Check Run smoke now pass in staging |
|
|
@@ -358,7 +360,7 @@ Use `suppressions` for narrower false-positive handling when one rule is noisy o
|
|
|
358
360
|
|
|
359
361
|
## GitHub Action
|
|
360
362
|
|
|
361
|
-
The repo includes a composite Action. Use `v0` for the latest compatible pre-1.0 Action, a specific release tag such as `v0.30.
|
|
363
|
+
The repo includes a composite Action. Use `v0` for the latest compatible pre-1.0 Action, a specific release tag such as `v0.30.2` for controlled upgrades, or pin a reviewed commit SHA for stricter supply-chain control:
|
|
362
364
|
|
|
363
365
|
```yaml
|
|
364
366
|
name: ai-saas-guard
|
package/dist/scanners/actions.js
CHANGED
|
@@ -101,7 +101,17 @@ function runsOnPullRequestOrPush(content) {
|
|
|
101
101
|
return /^\s*(pull_request(?:_target)?|push):/im.test(content);
|
|
102
102
|
}
|
|
103
103
|
function hasCancelInProgressConcurrency(content) {
|
|
104
|
-
|
|
104
|
+
if (!/^\s*concurrency:/im.test(content))
|
|
105
|
+
return false;
|
|
106
|
+
const match = /^\s*cancel-in-progress:\s*(.+?)\s*$/im.exec(content);
|
|
107
|
+
if (!match)
|
|
108
|
+
return false;
|
|
109
|
+
const value = match[1]?.trim() ?? "";
|
|
110
|
+
if (/^true\b/i.test(value))
|
|
111
|
+
return true;
|
|
112
|
+
if (/^\$\{\{[\s\S]*\}\}$/.test(value) && !/\bfalse\b/i.test(value))
|
|
113
|
+
return true;
|
|
114
|
+
return false;
|
|
105
115
|
}
|
|
106
116
|
function hasPathFilters(content) {
|
|
107
117
|
return /^\s*(paths|paths-ignore):\s*$/im.test(content) || /^\s*(paths|paths-ignore):\s*\[/im.test(content);
|
package/dist/scanners/deploy.js
CHANGED
|
@@ -180,11 +180,18 @@ function isImportantServerEnv(name) {
|
|
|
180
180
|
return /(STRIPE|SUPABASE|DATABASE|NEXTAUTH|AUTH|WEBHOOK|SECRET|TOKEN|OPENAI|ANTHROPIC|PAYMENT)/.test(name);
|
|
181
181
|
}
|
|
182
182
|
function hasSecurityHeaders(files) {
|
|
183
|
-
const
|
|
183
|
+
const nextOrMiddleware = files
|
|
184
184
|
.filter((file) => /(^|\/)(next\.config\.[cm]?[jt]s|middleware\.[cm]?[jt]s)$/i.test(file.path))
|
|
185
185
|
.map((file) => file.content)
|
|
186
186
|
.join("\n");
|
|
187
|
-
|
|
187
|
+
if (/\bheaders\s*\(/i.test(nextOrMiddleware) && hasBrowserSecurityHeaderNames(nextOrMiddleware))
|
|
188
|
+
return true;
|
|
189
|
+
return files.some((file) => {
|
|
190
|
+
return /(^|\/)vercel\.json$/i.test(file.path) && /"headers"\s*:/i.test(file.content) && hasBrowserSecurityHeaderNames(file.content);
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
function hasBrowserSecurityHeaderNames(content) {
|
|
194
|
+
return /(X-Frame-Options|Content-Security-Policy|X-Content-Type-Options|Referrer-Policy)/i.test(content);
|
|
188
195
|
}
|
|
189
196
|
function usesUnboundedNextImage(path, content, nextConfigContent) {
|
|
190
197
|
if (/next\.config\.(ts|js|mjs|cjs)$/.test(path) && /remotePatterns[\s\S]{0,240}hostname\s*:\s*["'](?:\*\*|\*)["']/i.test(content))
|
package/docs/README.zh-CN.md
CHANGED
|
@@ -123,6 +123,8 @@ Next steps
|
|
|
123
123
|
| 工具和 CI 权限是不是过大? | MCP side-effect 分类、本地 policy/receipt 模板、GitHub Actions 权限、concurrency、checkout depth、Action pinning |
|
|
124
124
|
| reviewer 能不能看懂 AI PR? | `pr-risk` 对 auth、billing、RLS、deploy、API、storage、测试、silent-success、缺 spec context 和大型 diff 排序 |
|
|
125
125
|
|
|
126
|
+
如果想看它和 Semgrep、zizmor、OpenSSF Scorecard、Snyk、GitHub code scanning 的边界区别,见 [launch-gate-positioning.md](launch-gate-positioning.md)。
|
|
127
|
+
|
|
126
128
|
## 快速开始
|
|
127
129
|
|
|
128
130
|
无需全局安装,直接运行:
|
|
@@ -167,18 +169,18 @@ node dist/cli.js scan --root /path/to/your-saas
|
|
|
167
169
|
|
|
168
170
|
这个仓库是公开 GitHub 仓库。
|
|
169
171
|
|
|
170
|
-
CLI 已发布到 npm:`ai-saas-guard@0.30.
|
|
172
|
+
CLI 已发布到 npm:`ai-saas-guard@0.30.2`。GitHub Action 支持 `v0` 浮动标签,也支持固定版本标签,例如 `v0.30.2`。
|
|
171
173
|
|
|
172
174
|
| 模块 | 状态 |
|
|
173
175
|
| --- | --- |
|
|
174
176
|
| 公开 GitHub 仓库 | 已可用 |
|
|
175
|
-
| npm CLI | `ai-saas-guard@0.30.
|
|
176
|
-
| GitHub Action | `zr9959/ai-saas-guard@v0` 或固定标签 `v0.30.
|
|
177
|
+
| npm CLI | `ai-saas-guard@0.30.2` |
|
|
178
|
+
| GitHub Action | `zr9959/ai-saas-guard@v0` 或固定标签 `v0.30.2` |
|
|
177
179
|
| 输出格式 | 短 summary、Terminal、JSON、SARIF 和 PR markdown |
|
|
178
180
|
| 项目配置 | `.ai-saas-guard.json` 支持规则开关、severity 覆盖、suppressions 和 fail threshold |
|
|
179
181
|
| 隐私模型 | 本地优先、只读扫描、不调用 LLM、不上传代码 |
|
|
180
|
-
| 当前版本 | `0.30.
|
|
181
|
-
| Action 标签 | `v0.30.
|
|
182
|
+
| 当前版本 | `0.30.2` 做发布后质量优化:降低 Vercel/Actions 误报、增加 launch-gate 定位文档,并补 hosted worker 证据边界 |
|
|
183
|
+
| Action 标签 | `v0.30.2`、`v0` |
|
|
182
184
|
| npm 发布 | GitHub Actions Trusted Publisher/OIDC,无需长期 npm token |
|
|
183
185
|
| 仓库可信度加固 | 严格 branch protection、Dependabot、CodeQL、fast-check fuzzing、signed release provenance assets、private vulnerability reporting、secret scanning 和 push protection |
|
|
184
186
|
| Cloudflare hosted ingress | 已部署到 `https://ai-saas-guard-hosted.zr9959.workers.dev`;签名 GitHub App webhook delivery 和 compact Check Run staging smoke 已通过 |
|
|
@@ -137,6 +137,27 @@ Required evidence:
|
|
|
137
137
|
|
|
138
138
|
The worker must not persist repository files across jobs.
|
|
139
139
|
|
|
140
|
+
### Read-Only Checkout Worker Evidence
|
|
141
|
+
|
|
142
|
+
For the first source checkout worker, the release blocks unless the deployed artifact records fresh evidence for both success and failure cleanup.
|
|
143
|
+
|
|
144
|
+
Required proof:
|
|
145
|
+
|
|
146
|
+
- checkout identity comes only from signed GitHub event fields and selected-repository installation scope.
|
|
147
|
+
- repository token permissions are limited to `contents: read` for checkout.
|
|
148
|
+
- runtime credentials reach git through temporary askpass material only.
|
|
149
|
+
- the CLI phase runs after credential material is removed from the environment.
|
|
150
|
+
- the worker command is fixed to the deterministic read-only `pr-risk --json` shape.
|
|
151
|
+
- success deletes the worker checkout, askpass material, generated JSON/SARIF scratch files, and local package tarballs.
|
|
152
|
+
- failure cleanup covers clone failure, timeout, CLI failure, malformed JSON output, Check Run write failure, cancellation, and process interruption.
|
|
153
|
+
- cleanup failures create an operator-review event without returning raw source, raw diffs, installation tokens, checkout paths, private URLs, or low-level filesystem errors to users.
|
|
154
|
+
|
|
155
|
+
### Log Boundary Evidence
|
|
156
|
+
|
|
157
|
+
Before exposure, sample ingress, queue, worker, report, and Check Run logs for the release candidate. The sample may contain scan key, installation ID, repository ID, PR number, head SHA, scanner version, duration, summary counts, error class, and cleanup status.
|
|
158
|
+
|
|
159
|
+
The sample must show no raw source, no raw diffs, no secrets, no installation tokens, no customer payloads, no private URLs, no checkout paths, and no untrusted PR prose.
|
|
160
|
+
|
|
140
161
|
## Dependency And Container Scanning
|
|
141
162
|
|
|
142
163
|
Hosted releases must include dependency and container scanning for the deployed artifact.
|
|
@@ -29,6 +29,22 @@ The hosted release gate still requires fresh deployed evidence for:
|
|
|
29
29
|
- dependency and container artifact scanning for the deployed worker image
|
|
30
30
|
- retention and uninstall cleanup against the deployed provider stores
|
|
31
31
|
|
|
32
|
+
## Read-Only Checkout Worker Evidence Checklist
|
|
33
|
+
|
|
34
|
+
Before any hosted source checkout worker is exposed beyond staging, attach fresh evidence for each row below. The current Cloudflare ingress evidence above does not satisfy these rows because it publishes compact PR-risk signals without running a full source checkout scan worker.
|
|
35
|
+
|
|
36
|
+
| Evidence area | Required proof | Status before hosted exposure |
|
|
37
|
+
| --- | --- | --- |
|
|
38
|
+
| Trusted checkout identity | Worker input is derived from signed GitHub event identity, selected-repository installation scope, and repository `contents: read`; PR title, body, branch names, README, and code cannot choose the repository, token scope, checkout path, or command | Required |
|
|
39
|
+
| Runtime credential boundary | Installation credentials are passed to git only through temporary askpass material, are removed before the CLI scan phase, and are never returned in worker output, compact reports, Check Runs, or logs | Required |
|
|
40
|
+
| Fixed scanner command | Worker runs the fixed read-only command shape `ai-saas-guard pr-risk --root <worker-checkout> --base <trusted-base-sha> --json` without shell parsing or PR-authored arguments | Required |
|
|
41
|
+
| Success cleanup | A successful worker run deletes the checkout directory, askpass material, generated JSON/SARIF scratch files, and any local package tarballs | Required |
|
|
42
|
+
| Failure cleanup | A failed clone, timeout, CLI non-zero exit, malformed JSON output, Check Run write failure, cancellation, or process interruption still attempts checkout deletion and records only a safe cleanup status | Required |
|
|
43
|
+
| Log boundary | Logs may include scan key, installation ID, repository ID, PR number, head SHA, scanner version, duration, summary counts, error class, and cleanup status; logs must include no raw source, no raw diffs, no secrets, no installation tokens, no customer payloads, no private URLs, and no checkout paths | Required |
|
|
44
|
+
| Retention boundary | Compact report retention and uninstall cleanup delete repository-scoped records and worker checkout references without exposing low-level cleanup errors | Required |
|
|
45
|
+
|
|
46
|
+
Use the checklist above together with [hosted-operational-release-gate.md](hosted-operational-release-gate.md). The release remains blocked until deployed worker evidence covers success, failure cleanup, log boundary sampling, monitoring, rollback, and incident response.
|
|
47
|
+
|
|
32
48
|
## Smoke Procedure
|
|
33
49
|
|
|
34
50
|
Use this sequence after each hosted Worker deployment:
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Launch Gate Positioning
|
|
2
|
+
|
|
3
|
+
`ai-saas-guard` is a local-first launch gate for AI-built SaaS apps. It is focused on the code paths that decide whether a product is ready to invite users: auth, billing, tenant data, provider failure handling, deploy config, MCP tool power, GitHub Actions hygiene, and AI-heavy PR review.
|
|
4
|
+
|
|
5
|
+
The narrow bet is simple: a founder or reviewer should know which launch-risk files to inspect first, what manual proof to run, and what fix direction to try before traffic reaches real users.
|
|
6
|
+
|
|
7
|
+
## Where It Fits
|
|
8
|
+
|
|
9
|
+
| Tool category | Typical strength | How ai-saas-guard fits beside it |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| Semgrep | Broad customizable static rules across many languages and frameworks | Adds SaaS launch-specific heuristics and review wording for Stripe, Supabase, silent-success, Next/Vercel, MCP, Actions, and AI PR trust boundaries |
|
|
12
|
+
| zizmor | Deep GitHub Actions security analysis | Adds a smaller launch-readiness hygiene check for workflow permissions, PR concurrency, docs-only CI cost, shallow checkout risk, and first-run guidance |
|
|
13
|
+
| OpenSSF Scorecard | Repository supply-chain posture signals | Adds app-level launch triage inside the repo, while Scorecard remains useful for public project maintenance controls |
|
|
14
|
+
| Snyk and dependency scanners | Dependency, container, license, and known-vulnerability workflows | Adds local source review for SaaS trust-boundary mistakes that may not be dependency vulnerabilities |
|
|
15
|
+
| GitHub code scanning | SARIF ingestion and code-security workflow inside GitHub | Emits SARIF, but keeps the primary workflow local-first and focused on launch review queues |
|
|
16
|
+
|
|
17
|
+
## What It Optimizes For
|
|
18
|
+
|
|
19
|
+
- local-first: source stays on the machine or in the caller's CI job
|
|
20
|
+
- deterministic: no LLM calls and no code upload
|
|
21
|
+
- founder-readable output: severity, rule ID, file evidence, why, manual proof, and fix direction
|
|
22
|
+
- AI-built SaaS launch risk: not every static-analysis finding, only the paths likely to break auth, billing, data access, deploy, or review trust
|
|
23
|
+
- PR triage: ranking trust-boundary files before cosmetic or unrelated AI-generated changes
|
|
24
|
+
|
|
25
|
+
## What It Does Not Try To Be
|
|
26
|
+
|
|
27
|
+
- not a general vulnerability management platform
|
|
28
|
+
- not a dependency advisory database
|
|
29
|
+
- not a cloud posture dashboard
|
|
30
|
+
- not a runtime WAF or MCP proxy
|
|
31
|
+
- not a guarantee that an app is safe to launch
|
|
32
|
+
|
|
33
|
+
Use it as a short, evidence-first launch review queue alongside dependency scanning, repository hardening, code scanning, manual two-account authorization tests, Stripe webhook replay, deploy-preview checks, and human review.
|
package/docs/npm-publishing.md
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
## Current State
|
|
6
6
|
|
|
7
7
|
- Package name: `ai-saas-guard`
|
|
8
|
-
- Current published version: `0.30.
|
|
8
|
+
- Current published version: `0.30.2`
|
|
9
9
|
- Next source candidate: none
|
|
10
10
|
- npm registry state: published at <https://www.npmjs.com/package/ai-saas-guard>
|
|
11
11
|
- First npm-published version: `0.1.1`
|
|
12
|
-
- GitHub Release: `v0.30.
|
|
12
|
+
- GitHub Release: `v0.30.2`
|
|
13
13
|
- Publish workflow: `.github/workflows/npm-publish.yml`
|
|
14
14
|
- Trusted Publisher: GitHub Actions, `zr9959/ai-saas-guard`, workflow `npm-publish.yml`, allowed action `npm publish`
|
|
15
15
|
- Long-lived npm publish token: not required
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
Use GitHub Actions with npm Trusted Publisher/OIDC:
|
|
20
20
|
|
|
21
|
-
1. Create and review a release tag such as `v0.30.
|
|
21
|
+
1. Create and review a release tag such as `v0.30.2`.
|
|
22
22
|
2. Publish from the GitHub Release or run the `Publish npm` workflow manually with `ref` set to that tag.
|
|
23
23
|
3. Keep `permissions.id-token: write` in the workflow so npm can exchange the GitHub Actions OIDC identity for a short-lived publish credential.
|
|
24
24
|
4. Run `npm publish --access public` from the workflow. Trusted publishing automatically generates provenance for this public package from this public repository.
|
package/package.json
CHANGED