@patchstack/connect 0.3.18 → 0.3.20
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/AGENT-INSTALL.md +33 -18
- package/README.md +28 -11
- package/dist/cli.js +1204 -1071
- package/dist/cli.js.map +1 -1
- package/dist/protect/templates/express-guard.cjs +5 -1
- package/dist/protect/templates/express-guard.js +5 -1
- package/dist/protect/templates/express-guard.ts +5 -1
- package/dist/protect/templates/fastify-plugin.cjs +46 -0
- package/dist/protect/templates/fastify-plugin.js +45 -0
- package/dist/protect/templates/generic-guard.cjs +41 -0
- package/dist/protect/templates/generic-guard.js +42 -0
- package/dist/protect/templates/generic-guard.ts +5 -1
- package/dist/protect/templates/guard.ts +5 -1
- package/dist/protect/templates/nuxt-middleware.ts +43 -0
- package/dist/protect.cjs +1692 -92
- package/dist/protect.cjs.map +1 -1
- package/dist/protect.d.ts +24 -0
- package/dist/protect.js +501 -82
- package/dist/protect.js.map +1 -1
- package/dist/refresh-manifest-XBOGN446.js +1090 -0
- package/dist/refresh-manifest-XBOGN446.js.map +1 -0
- package/package.json +1 -1
package/AGENT-INSTALL.md
CHANGED
|
@@ -7,17 +7,17 @@ This versioned reference ships inside `@patchstack/connect` and documents each s
|
|
|
7
7
|
- Package: [`@patchstack/connect`](https://www.npmjs.com/package/@patchstack/connect), MIT-licensed, source at https://github.com/patchstack/connect. `npm view @patchstack/connect` shows the live registry metadata.
|
|
8
8
|
- It reads the project's **dependency list only** — from the lockfile (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`) or, on bun projects (`bun.lock`/`bun.lockb`), by enumerating the installed packages under `node_modules/` — and sends package names + versions to Patchstack for vulnerability matching. No source code, no env var values, no file paths, no git history. (`mark-build` additionally stamps built HTML with a coarse stack descriptor that may include hosting-related env variable *names* — e.g. `VERCEL`, `CF_PAGES` — never their values.)
|
|
9
9
|
- **`scan` makes one source edit, and only after a successful post:** it adds (or updates) the disclosure widget's `<script>` tag in the project's root HTML shell — the first of `index.html`, `public/index.html`, or `src/app.html` that exists. It touches no other file, never edits on `--dry-run` or after a failed post, leaves any pre-existing manual widget tag untouched, and is disabled entirely by `"widget": false` in `.patchstackrc.json`. `mark-build` writes to build output only (`dist/`, `build/`, `out/`, `.output/public`), never to source. `guide`, `status`, and `init` write nothing except `init`'s own `.patchstackrc.json`.
|
|
10
|
-
- **`setup` runs `scan`, then edits
|
|
11
|
-
- The package also
|
|
10
|
+
- **`setup` runs `scan`, then `protect`, then edits `package.json` scripts:** provisioning happens first so the runtime guard can bake the real site UUID. It verifies the resulting framework seam, preserves existing commands, adds `scan` after dependency installs and before builds, adds `mark-build` after builds, and uses a direct build chain for Bun. It never runs the project build. If the widget or runtime guard needs a framework-specific manual merge, it prints the exact remaining step instead of overwriting user code.
|
|
11
|
+
- The package also exposes **`protect`** directly (runtime exploit guard; its templates live under `dist/protect/`). `setup` invokes it automatically; `scan`, `guide`, `status`, and `mark-build` do not. It writes only local files and auto-wires known stacks — **TanStack Start + Supabase** (patches the Supabase client + `src/start.ts`), **Next.js** (scaffolds `middleware.ts`), **SvelteKit** (`src/hooks.server.ts`), **Astro** (`src/middleware.ts`), **Nuxt** (`server/middleware/`), **NestJS** (`app.use(patchstackMiddleware)` in the bootstrap), **Fastify** (`app.register(patchstackFastify)`), and **Express** (`app.use(patchstackMiddleware)`). On **any other stack** it scaffolds a framework-agnostic guard under `src/patchstack/` and prints a wiring plan — then you finish the install by importing that guard into your server entry (`protectFetch(handler)` for a Web-Fetch server, or `app.use(patchstackMiddleware)` for Node/Express) and running `patchstack-connect protect --check` to confirm it is wired (exit 1 until it is). Passing `--demo` seeds a broad sample rule set (for demonstrations, not production).
|
|
12
12
|
- **`demo node-serialize` is an explicit production-backed walkthrough.** It requires `node-serialize@0.0.4` to already be present in the lockfile; it does not install the vulnerable dependency. It runs the same production `scan`, polls the configured site's public Pulse rules endpoint until rule `18843` is served, runs `protect`, verifies the generated guard, and prints exploit/benign test requests. It writes the same manifest/widget and guard files as those underlying commands. It does not start/restart the app and does not send the printed requests.
|
|
13
13
|
- **`demo-guide node-serialize` is the read-only companion.** It checks the Host-created site configuration and vulnerable lockfile entry, explains the complete local prepare/run/restart/prove/cleanup sequence, and prints the next exact command. It does not require a deployment and does not change files or contact Patchstack.
|
|
14
14
|
- Patchstack is not WordPress-only. This connector monitors any JS/Node project — Vite, Next.js, plain vanilla JS, anything with a lockfile.
|
|
15
15
|
|
|
16
16
|
## Before you start — never install twice
|
|
17
17
|
|
|
18
|
-
- `npx @patchstack/connect guide` prints a read-only live checklist showing which steps are already done in the current project (install, provisioning, build hooks, widget).
|
|
18
|
+
- `npx @patchstack/connect guide` prints a read-only live checklist showing which steps are already done in the current project (install, provisioning, build hooks, widget, runtime protection).
|
|
19
19
|
- If `.patchstackrc.json` contains a `siteUuid` key, the project is already provisioned. Reuse that UUID; run `npx @patchstack/connect status` to re-print it and the dashboard URL. **Do not delete the file and provision a second site.** (A `.patchstackrc.json` with other keys — e.g. an `endpoint` override — but no `siteUuid` is *not* provisioned yet; scan normally.)
|
|
20
|
-
- If `@patchstack/connect` is already in `
|
|
20
|
+
- If `@patchstack/connect` is already in `dependencies`, skip the install command. If it is only in `devDependencies`, move it with the matching package manager so production runtimes that prune dev dependencies can load the generated guard.
|
|
21
21
|
- If the widget script tag (`cdn.patchstack.com/patchstack-widget.js`) is already in the layout, don't add a second one — `scan` also respects an existing tag: it updates its own managed tag in place and leaves a manual one untouched.
|
|
22
22
|
|
|
23
23
|
## Automated setup
|
|
@@ -25,10 +25,10 @@ This versioned reference ships inside `@patchstack/connect` and documents each s
|
|
|
25
25
|
1. **Install** (skip if already present), matching the project's package manager:
|
|
26
26
|
|
|
27
27
|
```
|
|
28
|
-
npm install --save
|
|
29
|
-
pnpm add
|
|
30
|
-
yarn add
|
|
31
|
-
bun add
|
|
28
|
+
npm install --save @patchstack/connect # package-lock.json
|
|
29
|
+
pnpm add @patchstack/connect # pnpm-lock.yaml
|
|
30
|
+
yarn add @patchstack/connect # yarn.lock
|
|
31
|
+
bun add @patchstack/connect # bun.lock / bun-managed platforms
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
2. **Run bounded setup:**
|
|
@@ -37,7 +37,9 @@ This versioned reference ships inside `@patchstack/connect` and documents each s
|
|
|
37
37
|
npx @patchstack/connect setup
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
This provisions or reuses the site, manages the widget, wires
|
|
40
|
+
This provisions or reuses the site, manages the widget, installs and verifies runtime protection, wires dependency-install and build scans, prints a dashboard link, and finishes with the same status shown by `guide`. Re-running it reuses existing configuration, widget tags, guards, and commands rather than duplicating them.
|
|
41
|
+
|
|
42
|
+
In a hosted builder, run setup with `PATCHSTACK_ENVIRONMENT=sandbox` scoped to the workspace process/command, ensure the CLI's on-disk edits are adopted into the platform's persisted project state, then restart any already-running preview/server process so it loads the guard. Do not persist `"environment": "sandbox"` in `.patchstackrc.json`: deployed builds use the same committed files and should default to `production`. A client-only SPA has no server request path to guard; do not call it protected unless `protect --check` succeeds after a real server or edge seam is wired.
|
|
41
43
|
|
|
42
44
|
## Manual setup
|
|
43
45
|
|
|
@@ -54,13 +56,14 @@ This versioned reference ships inside `@patchstack/connect` and documents each s
|
|
|
54
56
|
```jsonc
|
|
55
57
|
{
|
|
56
58
|
"scripts": {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
"prebuild": "patchstack-connect scan",
|
|
60
|
+
"postbuild": "patchstack-connect mark-build",
|
|
61
|
+
"postinstall": "patchstack-connect scan"
|
|
59
62
|
}
|
|
60
63
|
}
|
|
61
64
|
```
|
|
62
65
|
|
|
63
|
-
If a
|
|
66
|
+
If a lifecycle hook already exists, chain instead of replacing it, e.g. `"prebuild": "existing-command && patchstack-connect scan"`. The `postinstall` scan reports dependencies added during an iterative sandbox session and covers applications with no build command.
|
|
64
67
|
|
|
65
68
|
**Bun-managed projects:** `bun run` does not execute npm-style `pre`/`post` scripts, so wire the build script directly instead: `"build": "patchstack-connect scan && <existing build command> && patchstack-connect mark-build"`.
|
|
66
69
|
|
|
@@ -72,20 +75,31 @@ This versioned reference ships inside `@patchstack/connect` and documents each s
|
|
|
72
75
|
|
|
73
76
|
Framework-specific placement patterns: https://cdn.patchstack.com/llm.html. The site UUID is public by design — it ships in client-side HTML and is not a secret. If the project must not carry the widget, persist `"widget": false` in `.patchstackrc.json`; otherwise the next scan re-adds it.
|
|
74
77
|
|
|
75
|
-
4. **
|
|
78
|
+
4. **Install and verify runtime protection:**
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
npx @patchstack/connect protect
|
|
82
|
+
npx @patchstack/connect protect --check
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`setup` performs both steps automatically. The explicit commands are for manual setup or repair. If verification reports a generic or existing framework seam, complete the printed source edit and re-run `--check`; do not report protection as active until it exits successfully.
|
|
86
|
+
|
|
87
|
+
5. **Commit** `.patchstackrc.json`, the updated `package.json`, the guard/framework source changes, and the layout/HTML file carrying the widget tag, so every developer and CI run reports to the same site.
|
|
76
88
|
|
|
77
|
-
|
|
89
|
+
6. **Open the dashboard link** from the scan in a browser and sign in. The site is monitored either way, but the vulnerability reports are only visible after connecting it to an account. The same connection flow is available from the widget's "Connect this website" prompt. On the published site, the owner reaches the widget login by appending `#patchstack` to the live URL.
|
|
78
90
|
|
|
79
91
|
## Rules
|
|
80
92
|
|
|
81
93
|
- Never invent or guess a UUID — the scan provisions it, the widget silently no-ops on a fake one.
|
|
82
94
|
- The CLI never opens the dashboard link and never asks for Patchstack credentials.
|
|
95
|
+
- Label hosted workspace scans with `PATCHSTACK_ENVIRONMENT=sandbox` in that process only. Leave production builds unset (the default is `production`) and never commit a sandbox label into files shared with production.
|
|
83
96
|
- If a step fails, stop and report it. Don't proceed with placeholders.
|
|
84
97
|
- In CI where `.patchstackrc.json` can't be committed, set `PATCHSTACK_SITE_UUID` as an env var instead. Precedence: CLI flag → env var → `.patchstackrc.json`.
|
|
85
98
|
|
|
86
99
|
## Verifying the install
|
|
87
100
|
|
|
88
101
|
- `npx @patchstack/connect status` re-prints the site UUID and dashboard URL.
|
|
102
|
+
- `npx @patchstack/connect protect --check` verifies the runtime guard is connected to the request path.
|
|
89
103
|
- Load the site in a browser — the "Report a vulnerability" button should appear.
|
|
90
104
|
|
|
91
105
|
## Uninstalling
|
|
@@ -94,9 +108,10 @@ Remove only the pieces that are actually present — check for each first. If no
|
|
|
94
108
|
|
|
95
109
|
1. **Read the site UUID from `.patchstackrc.json` before deleting anything.** It is the only local record of the provisioned site — report it to the user at the end so they can identify the site in their dashboard.
|
|
96
110
|
2. **Remove the widget snippets** from the layout/template: the `<script src="https://cdn.patchstack.com/patchstack-widget.js">` tag and any `PatchstackWidget.init(...)` call (which may live in a separate client component/plugin/effect). Afterwards, grep the repo for `patchstack-widget` and `PatchstackWidget` to confirm nothing remains.
|
|
97
|
-
3. **Remove
|
|
98
|
-
4. **
|
|
99
|
-
5. **
|
|
100
|
-
6. **
|
|
111
|
+
3. **Remove runtime protection before uninstalling the package.** Delete the connector-managed guard/rules files and remove only their managed imports, middleware registrations, tunnel code, and `#region patchstack…` blocks from the framework/server files. Preserve unrelated middleware and application code. Run `rg "patchstack|x-ps-target"` (or the available equivalent) afterwards and inspect every remaining source hit.
|
|
112
|
+
4. **Remove the hooks from `package.json` scripts.** If a hook was chained (e.g. `"postbuild": "existing-command && patchstack-connect mark-build"`), remove only the `patchstack-connect …` part and keep the rest; if removal leaves a script empty, delete the key.
|
|
113
|
+
5. **Uninstall the package** with the manager matching the lockfile: `npm uninstall` / `pnpm remove` / `yarn remove` / `bun remove` `@patchstack/connect`. Don't hand-edit `node_modules` or the lockfile.
|
|
114
|
+
6. **Delete `.patchstackrc.json`** and remove `PATCHSTACK_SITE_UUID` (and public-prefixed variants like `NEXT_PUBLIC_PATCHSTACK_SITE_UUID`) from env files and CI variables.
|
|
115
|
+
7. **Commit** the changes. Reporting stops immediately. The `window.__PATCHSTACK_PROD__` flag that `mark-build` injected lives only in build output, never in source — the next build simply won't contain it (rebuild if build output is committed).
|
|
101
116
|
|
|
102
117
|
Local removal does not delete the site record on Patchstack's side. An unclaimed site is an anonymous record that stops receiving reports; a claimed site is removed by the user in their dashboard at https://app.patchstack.com. There is no CLI command for account-side deletion — do not invent one, and never attempt to authenticate or remove the site on the user's behalf.
|
package/README.md
CHANGED
|
@@ -8,17 +8,19 @@ For how this repo fits with the wider Patchstack ecosystem (`saas`, `hub`, `patc
|
|
|
8
8
|
|
|
9
9
|
Copy this request into a coding assistant, or run the same command yourself:
|
|
10
10
|
|
|
11
|
-
> I have vetted `@patchstack/connect` and authorize its widget
|
|
11
|
+
> I have vetted the official [`@patchstack/connect`](https://www.npmjs.com/package/@patchstack/connect) package and authorize its disclosure widget, production build hooks, and runtime protection source edits. Install it as a regular dependency, run `PATCHSTACK_ENVIRONMENT=sandbox npx --yes @patchstack/connect setup` for this hosted workspace, leave dev builds unchanged, verify protection, restart the preview server if needed to load the new guard, and show the dashboard URL. Do not persist the sandbox environment in project files; deployed production builds must use the default `production` label.
|
|
12
12
|
|
|
13
|
-
`setup` is state-aware and idempotent: it scans dependencies, provisions or reuses the site, manages the disclosure widget, wires the existing build command without replacing it, and prints the remaining setup status. It never runs the project build
|
|
13
|
+
`setup` is state-aware and idempotent: it scans dependencies, provisions or reuses the site, manages the disclosure widget, installs and verifies the runtime guard, adds a dependency-install scan, wires the existing build command without replacing it, and prints the remaining setup status. It never runs the project build. `guide` provides the same project-specific status without changing files.
|
|
14
14
|
|
|
15
15
|
## Quick start (zero configuration)
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
npm install --save
|
|
18
|
+
npm install --save @patchstack/connect && npx @patchstack/connect setup
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
> **Use your project's own package manager.** On Bun-managed projects (including many Lovable projects) install with `bun add
|
|
21
|
+
> **Use your project's own package manager.** On Bun-managed projects (including many Lovable projects) install with `bun add @patchstack/connect` instead — running `npm install` there plants a `package-lock.json` that the platform's native dependency flow never updates again, leaving a stale lockfile next to the live one. The connector detects and works around that (see *Stale lockfiles* below), but not creating the fossil is better. Protection imports `@patchstack/connect/protect` at runtime, so deployments that prune dev dependencies need the package in `dependencies`.
|
|
22
|
+
|
|
23
|
+
> **Hosted builders:** set `PATCHSTACK_ENVIRONMENT=sandbox` in the workspace process environment (or scope it to the setup command above), persist every file written by `setup`, and restart any already-running server so it loads the new middleware. Do not write `"environment": "sandbox"` to the committed `.patchstackrc.json`: the same project files reach production, where scans should inherit no override and default to `production`. TanStack Start + Supabase (the server shape emitted by Lovable) is auto-wired: browser Supabase traffic is tunneled through a same-origin guard, server-function arguments are inspected, and responses are screened. A client-only SPA has no server request path to protect; setup will leave a generic scaffold and `protect --check` will remain red until the host adds a server/edge seam. Set `PATCHSTACK_ROUTE_WAF=1` when the deployment should additionally screen every TanStack route request.
|
|
22
24
|
|
|
23
25
|
That's it. `setup`:
|
|
24
26
|
|
|
@@ -27,15 +29,17 @@ That's it. `setup`:
|
|
|
27
29
|
3. Patchstack provisions a fresh site and returns its UUID.
|
|
28
30
|
4. The connector writes the UUID to `.patchstackrc.json` so the next `scan` targets the same site.
|
|
29
31
|
5. The connector installs the disclosure widget's `<script>` tag into your root HTML shell (see *The disclosure widget* below) so the "Report a vulnerability" button shows up on the next preview reload.
|
|
30
|
-
6.
|
|
31
|
-
7.
|
|
32
|
+
6. Installs the runtime guard after provisioning, bakes the site UUID into it, and verifies the framework seam. Known server stacks are auto-wired; unmatched or conflicting layouts get a generic scaffold and exact manual checks.
|
|
33
|
+
7. Adds `postinstall: patchstack-connect scan`, preserving any existing command, so dependencies added during a sandbox session and build-less production installs are reported immediately.
|
|
34
|
+
8. Wires `scan` before builds and `mark-build` after builds, preserving existing commands and using direct build chaining for Bun.
|
|
35
|
+
9. Prints a dashboard link — open it in a browser to attach the new site to your Patchstack account. You can re-display it any time with `npx @patchstack/connect status`.
|
|
32
36
|
|
|
33
37
|
## Quick start (existing site)
|
|
34
38
|
|
|
35
39
|
If you already created an "Application" site in the Patchstack dashboard, pre-seed the UUID:
|
|
36
40
|
|
|
37
41
|
```bash
|
|
38
|
-
npm install --save
|
|
42
|
+
npm install --save @patchstack/connect
|
|
39
43
|
npx @patchstack/connect init <your-site-uuid>
|
|
40
44
|
npx @patchstack/connect setup
|
|
41
45
|
```
|
|
@@ -50,8 +54,8 @@ patchstack-connect scan [options] Scan the lockfile and POST to
|
|
|
50
54
|
widget tag in the root HTML shell (opt out
|
|
51
55
|
with "widget": false in .patchstackrc.json)
|
|
52
56
|
patchstack-connect setup [options] Run scan, manage the widget, and idempotently
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
install + verify runtime protection and wire
|
|
58
|
+
dependency/build scans. Never runs the build
|
|
55
59
|
patchstack-connect init <site-uuid> Optional: pre-seed .patchstackrc.json with
|
|
56
60
|
an existing site UUID
|
|
57
61
|
patchstack-connect status [options] Show current configuration
|
|
@@ -61,10 +65,10 @@ patchstack-connect mark-build [options] Stamp built HTML with a produ
|
|
|
61
65
|
patchstack-connect guide Show this project's setup status (what's done,
|
|
62
66
|
what's missing, with tailored commands), then
|
|
63
67
|
print the full setup guide
|
|
64
|
-
patchstack-connect protect
|
|
68
|
+
patchstack-connect protect Install/reconcile the always-on runtime exploit
|
|
65
69
|
guard. Auto-wires supported server stacks;
|
|
66
70
|
use --check to verify or --demo for local rules.
|
|
67
|
-
|
|
71
|
+
Also run by setup; never run by scan/guide/mark-build.
|
|
68
72
|
patchstack-connect demo node-serialize Production-backed walkthrough: require
|
|
69
73
|
node-serialize@0.0.4, scan it, wait for live
|
|
70
74
|
rule 18843, install + verify the runtime guard,
|
|
@@ -97,6 +101,7 @@ Environment variables:
|
|
|
97
101
|
- `PATCHSTACK_SITE_UUID` — the site UUID from your Patchstack dashboard
|
|
98
102
|
- `PATCHSTACK_ENDPOINT` — override the API endpoint (default `https://api.patchstack.com/monitor/pulse/manifest`)
|
|
99
103
|
- `PATCHSTACK_TIMEOUT_MS` — request timeout in milliseconds (default `30000`)
|
|
104
|
+
- `PATCHSTACK_ENVIRONMENT` — manifest label: `production` (default) or `sandbox`
|
|
100
105
|
|
|
101
106
|
`.patchstackrc.json` example:
|
|
102
107
|
|
|
@@ -111,6 +116,18 @@ Environment variables:
|
|
|
111
116
|
|
|
112
117
|
The site UUID identifies the site; it is not a secret — the disclosure widget ships the same UUID in client-side HTML, and committing `.patchstackrc.json` is the intended workflow so every developer and CI run reports to the same site. Possession of the UUID lets someone submit dependency manifests for that site (noise, not data access). In CI setups where the file isn't committed, set `PATCHSTACK_SITE_UUID` instead.
|
|
113
118
|
|
|
119
|
+
### Sandbox and production manifests
|
|
120
|
+
|
|
121
|
+
Every `scan` sends an environment label with its dependency manifest. The default is `production`; sandboxed builders should set `PATCHSTACK_ENVIRONMENT=sandbox` in the sandbox process only. Patchstack stores and deduplicates manifests per environment, so an iterative workspace scan does not replace the last production manifest.
|
|
122
|
+
|
|
123
|
+
Do not commit `"environment": "sandbox"` to `.patchstackrc.json` when the same files are deployed to production. Scope the variable to the sandbox command/process instead:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
PATCHSTACK_ENVIRONMENT=sandbox npx @patchstack/connect setup
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The generated `prebuild` scan deliberately carries no hard-coded environment. A production builder with no override reports `production`; a preview/sandbox builder must receive `PATCHSTACK_ENVIRONMENT=sandbox` from its host. Runtime protection itself is not environment-specific: `PATCHSTACK_ENVIRONMENT` labels manifests only. Use `PATCHSTACK_MODE=dry-run` when protection should observe rather than block.
|
|
130
|
+
|
|
114
131
|
## Production virtual-patch demo
|
|
115
132
|
|
|
116
133
|
The `node-serialize` scenario demonstrates dependency detection and a live, version-scoped virtual patch against a throwaway Express application. Connect/provision the project first, deliberately add the known-vulnerable package, then run:
|