securenow 7.4.0 → 7.5.1
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/NPM_README.md +40 -24
- package/README.md +22 -6
- package/SKILL-API.md +19 -16
- package/SKILL-CLI.md +16 -5
- package/cli/diagnostics.js +21 -2
- package/cli/init.js +94 -51
- package/cli/ui.js +22 -12
- package/cli.js +14 -9
- package/docs/ALL-FRAMEWORKS-QUICKSTART.md +21 -18
- package/docs/API-KEYS-GUIDE.md +2 -2
- package/docs/ENVIRONMENT-VARIABLES.md +10 -9
- package/docs/FIREWALL-GUIDE.md +5 -4
- package/docs/MCP-GUIDE.md +50 -0
- package/mcp/catalog.js +770 -0
- package/mcp/server.js +238 -0
- package/nextjs-auto-capture.d.ts +1 -1
- package/package.json +10 -2
package/cli/ui.js
CHANGED
|
@@ -111,13 +111,21 @@ function keyValue(pairs) {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
function heading(text) {
|
|
115
|
-
console.log(`\n${c.bold(c.cyan(text))}`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function
|
|
119
|
-
|
|
120
|
-
}
|
|
114
|
+
function heading(text) {
|
|
115
|
+
console.log(`\n${c.bold(c.cyan(text))}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function header(text) {
|
|
119
|
+
heading(text);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function bold(text) {
|
|
123
|
+
return c.bold(text);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function subheading(text) {
|
|
127
|
+
console.log(`\n ${c.bold(text)}`);
|
|
128
|
+
}
|
|
121
129
|
|
|
122
130
|
function success(msg) {
|
|
123
131
|
console.log(`${c.green('✓')} ${msg}`);
|
|
@@ -361,11 +369,13 @@ function durationColor(ms) {
|
|
|
361
369
|
module.exports = {
|
|
362
370
|
c,
|
|
363
371
|
NO_COLOR,
|
|
364
|
-
stripAnsi,
|
|
365
|
-
table,
|
|
366
|
-
keyValue,
|
|
367
|
-
heading,
|
|
368
|
-
|
|
372
|
+
stripAnsi,
|
|
373
|
+
table,
|
|
374
|
+
keyValue,
|
|
375
|
+
heading,
|
|
376
|
+
header,
|
|
377
|
+
bold,
|
|
378
|
+
subheading,
|
|
369
379
|
success,
|
|
370
380
|
error,
|
|
371
381
|
warn,
|
package/cli.js
CHANGED
|
@@ -365,14 +365,19 @@ const COMMANDS = {
|
|
|
365
365
|
usage: 'securenow doctor [--json]',
|
|
366
366
|
run: (a, f) => require('./cli/diagnostics').doctor(a, f),
|
|
367
367
|
},
|
|
368
|
-
env: {
|
|
369
|
-
desc: 'Show resolved SecureNow configuration (service name, endpoints, env vars)',
|
|
370
|
-
usage: 'securenow env [--json]',
|
|
371
|
-
run: (a, f) => require('./cli/diagnostics').env(a, f),
|
|
372
|
-
},
|
|
373
|
-
|
|
374
|
-
desc: '
|
|
375
|
-
|
|
368
|
+
env: {
|
|
369
|
+
desc: 'Show resolved SecureNow configuration (service name, endpoints, env vars)',
|
|
370
|
+
usage: 'securenow env [--json]',
|
|
371
|
+
run: (a, f) => require('./cli/diagnostics').env(a, f),
|
|
372
|
+
},
|
|
373
|
+
mcp: {
|
|
374
|
+
desc: 'Start the SecureNow MCP server over stdio',
|
|
375
|
+
usage: 'securenow mcp',
|
|
376
|
+
run: () => require('./mcp/server'),
|
|
377
|
+
},
|
|
378
|
+
version: {
|
|
379
|
+
desc: 'Show CLI version',
|
|
380
|
+
run: () => {
|
|
376
381
|
try {
|
|
377
382
|
const pkg = require('./package.json');
|
|
378
383
|
console.log(`securenow v${pkg.version}`);
|
|
@@ -437,7 +442,7 @@ function showHelp(commandName) {
|
|
|
437
442
|
'Firewall': ['firewall'],
|
|
438
443
|
'Remediation': ['blocklist', 'allowlist', 'trusted'],
|
|
439
444
|
'Telemetry': ['log', 'test-span'],
|
|
440
|
-
'Utilities': ['redact', 'cidr', 'doctor', 'env'],
|
|
445
|
+
'Utilities': ['redact', 'cidr', 'doctor', 'env', 'mcp'],
|
|
441
446
|
'Settings': ['instances', 'config', 'version'],
|
|
442
447
|
};
|
|
443
448
|
|
|
@@ -119,9 +119,10 @@ SECURENOW_NO_UUID=1
|
|
|
119
119
|
|----------|---------|---------|
|
|
120
120
|
| `SECURENOW_APPID` | Your app key (from `securenow apps create`) | **Required** |
|
|
121
121
|
| `SECURENOW_INSTANCE` | OTLP collector endpoint | `https://freetrial.securenow.ai:4318` |
|
|
122
|
-
| `SECURENOW_LOGGING_ENABLED` | Auto-forward all `console.*` calls as OTLP logs | `
|
|
122
|
+
| `SECURENOW_LOGGING_ENABLED` | Auto-forward all `console.*` calls as OTLP logs | `1` |
|
|
123
123
|
| `SECURENOW_NO_UUID` | Keep `service.name` equal to your app key (no UUID suffix) | `0` |
|
|
124
|
-
| `SECURENOW_CAPTURE_BODY` | Capture request/response bodies in traces | `
|
|
124
|
+
| `SECURENOW_CAPTURE_BODY` | Capture request/response bodies in traces | `1` |
|
|
125
|
+
| `SECURENOW_CAPTURE_MULTIPART` | Capture multipart field/file metadata | `1` |
|
|
125
126
|
| `SECURENOW_MAX_BODY_SIZE` | Max captured body size in bytes | `10240` |
|
|
126
127
|
| `SECURENOW_SENSITIVE_FIELDS` | Extra field names to auto-redact (comma-separated) | — |
|
|
127
128
|
| `SECURENOW_TRUSTED_PROXIES` | Comma-separated proxy IPs for X-Forwarded-For | — |
|
|
@@ -137,7 +138,8 @@ SECURENOW_APPID=my-app-prod
|
|
|
137
138
|
SECURENOW_INSTANCE=https://collector.yourcompany.com:4318
|
|
138
139
|
SECURENOW_LOGGING_ENABLED=1
|
|
139
140
|
SECURENOW_NO_UUID=1
|
|
140
|
-
SECURENOW_CAPTURE_BODY=
|
|
141
|
+
SECURENOW_CAPTURE_BODY=1
|
|
142
|
+
SECURENOW_CAPTURE_MULTIPART=1
|
|
141
143
|
SECURENOW_TRUSTED_PROXIES=10.0.0.1,10.0.0.2
|
|
142
144
|
NODE_ENV=production
|
|
143
145
|
```
|
|
@@ -203,7 +205,7 @@ node app.js
|
|
|
203
205
|
|---------|-----------|
|
|
204
206
|
| Traces | Yes |
|
|
205
207
|
| Logs | Yes |
|
|
206
|
-
| Body Capture | Yes
|
|
208
|
+
| Body Capture | Yes - default on |
|
|
207
209
|
|
|
208
210
|
---
|
|
209
211
|
|
|
@@ -249,7 +251,7 @@ node app.js
|
|
|
249
251
|
|---------|-----------|
|
|
250
252
|
| Traces | Yes |
|
|
251
253
|
| Logs | Yes |
|
|
252
|
-
| Body Capture |
|
|
254
|
+
| Body Capture | Yes - default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
|
|
253
255
|
|
|
254
256
|
---
|
|
255
257
|
|
|
@@ -299,7 +301,7 @@ node app.js
|
|
|
299
301
|
|---------|-----------|
|
|
300
302
|
| Traces | Yes |
|
|
301
303
|
| Logs | Yes |
|
|
302
|
-
| Body Capture | Yes
|
|
304
|
+
| Body Capture | Yes - default on |
|
|
303
305
|
|
|
304
306
|
---
|
|
305
307
|
|
|
@@ -376,7 +378,7 @@ Add both to your `package.json`:
|
|
|
376
378
|
|---------|-----------|
|
|
377
379
|
| Traces | Yes |
|
|
378
380
|
| Logs | Yes |
|
|
379
|
-
| Body Capture | Yes
|
|
381
|
+
| Body Capture | Yes - default on |
|
|
380
382
|
|
|
381
383
|
---
|
|
382
384
|
|
|
@@ -426,7 +428,7 @@ node app.js
|
|
|
426
428
|
|---------|-----------|
|
|
427
429
|
| Traces | Yes |
|
|
428
430
|
| Logs | Yes |
|
|
429
|
-
| Body Capture |
|
|
431
|
+
| Body Capture | Yes - default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
|
|
430
432
|
|
|
431
433
|
---
|
|
432
434
|
|
|
@@ -473,7 +475,7 @@ node app.js
|
|
|
473
475
|
|---------|-----------|
|
|
474
476
|
| Traces | Yes |
|
|
475
477
|
| Logs | Yes |
|
|
476
|
-
| Body Capture | Yes
|
|
478
|
+
| Body Capture | Yes - default on |
|
|
477
479
|
|
|
478
480
|
---
|
|
479
481
|
|
|
@@ -528,7 +530,7 @@ node app.js
|
|
|
528
530
|
|---------|-----------|
|
|
529
531
|
| Traces | Yes |
|
|
530
532
|
| Logs | Yes |
|
|
531
|
-
| Body Capture | Yes
|
|
533
|
+
| Body Capture | Yes - default on |
|
|
532
534
|
|
|
533
535
|
---
|
|
534
536
|
|
|
@@ -591,7 +593,7 @@ node app.js
|
|
|
591
593
|
|---------|-----------|
|
|
592
594
|
| Traces | Yes |
|
|
593
595
|
| Logs | Yes |
|
|
594
|
-
| Body Capture | Yes
|
|
596
|
+
| Body Capture | Yes - default on |
|
|
595
597
|
|
|
596
598
|
---
|
|
597
599
|
|
|
@@ -632,7 +634,7 @@ node -r securenow/register app.mjs
|
|
|
632
634
|
|---------|-----------|
|
|
633
635
|
| Traces | Yes |
|
|
634
636
|
| Logs | Yes |
|
|
635
|
-
| Body Capture |
|
|
637
|
+
| Body Capture | Yes - default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
|
|
636
638
|
|
|
637
639
|
---
|
|
638
640
|
|
|
@@ -687,7 +689,7 @@ node app.js
|
|
|
687
689
|
|---------|-----------|
|
|
688
690
|
| Traces | Yes |
|
|
689
691
|
| Logs | Yes |
|
|
690
|
-
| Body Capture | Yes
|
|
692
|
+
| Body Capture | Yes - default on |
|
|
691
693
|
|
|
692
694
|
---
|
|
693
695
|
|
|
@@ -1284,7 +1286,8 @@ pm2 start ecosystem.config.cjs
|
|
|
1284
1286
|
script: 'app.mjs',
|
|
1285
1287
|
node_args: '-r securenow/register',
|
|
1286
1288
|
env: {
|
|
1287
|
-
SECURENOW_CAPTURE_BODY: '
|
|
1289
|
+
SECURENOW_CAPTURE_BODY: '1',
|
|
1290
|
+
SECURENOW_CAPTURE_MULTIPART: '1',
|
|
1288
1291
|
/* ... other vars ... */
|
|
1289
1292
|
}
|
|
1290
1293
|
}
|
|
@@ -1315,14 +1318,14 @@ CMD ["node", "-r", "securenow/register", "app.js"]
|
|
|
1315
1318
|
| Framework | Traces | Logs | Body Capture | Init Method | Notes |
|
|
1316
1319
|
|-----------|--------|------|--------------|-------------|-------|
|
|
1317
1320
|
| Express | Yes | Yes | Yes | `require()` or `-r` | Fully compatible |
|
|
1318
|
-
| Fastify | Yes | Yes |
|
|
1321
|
+
| Fastify | Yes | Yes | Yes | `require()` or `-r` | Default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
|
|
1319
1322
|
| Koa | Yes | Yes | Yes | `require()` or `-r` | Needs `koa-bodyparser` |
|
|
1320
1323
|
| NestJS | Yes | Yes | Yes | `instrument.js` + `-r ./instrument.js` | Create `instrument.js` with `require('securenow/register')` |
|
|
1321
|
-
| Hapi | Yes | Yes |
|
|
1324
|
+
| Hapi | Yes | Yes | Yes | `require()` or `-r` | Default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
|
|
1322
1325
|
| h3 | Yes | Yes | Yes | `require()` or `-r` | Uses `toNodeListener()` |
|
|
1323
1326
|
| Polka | Yes | Yes | Yes | `require()` or `-r` | Needs manual body parser |
|
|
1324
1327
|
| Micro/HTTP | Yes | Yes | Yes | `require()` or `-r` | Raw `http.createServer` |
|
|
1325
|
-
| Hono | Yes | Yes |
|
|
1328
|
+
| Hono | Yes | Yes | Yes | `-r` flag only (ESM) | Default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
|
|
1326
1329
|
| Feathers | Yes | Yes | Yes | `require()` or `-r` | Express transport |
|
|
1327
1330
|
| Next.js | Yes | Yes | Yes | `instrumentation.ts` | Use `securenow init` |
|
|
1328
1331
|
|
|
@@ -1349,7 +1352,7 @@ Do **not** add `require('securenow/register')` inside `.mjs` files.
|
|
|
1349
1352
|
|
|
1350
1353
|
### Body capture crashes / empty payloads
|
|
1351
1354
|
|
|
1352
|
-
|
|
1355
|
+
Body capture is on by default. If a specific framework version or plugin stack reports request-stream conflicts, set `SECURENOW_CAPTURE_BODY=0` as a local override for that app.
|
|
1353
1356
|
|
|
1354
1357
|
### CLI says "Not logged in"
|
|
1355
1358
|
|
package/docs/API-KEYS-GUIDE.md
CHANGED
|
@@ -54,8 +54,8 @@ Since v7.1.0, the firewall reads its API key from `.securenow/credentials.json`
|
|
|
54
54
|
### Writing the key to the credentials file
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
|
-
# Interactive onboarding
|
|
58
|
-
# mints a key scoped firewall:read + blocklist:read + allowlist:read
|
|
57
|
+
# Interactive onboarding - picks/creates an app, enables that app's firewall,
|
|
58
|
+
# and mints a key scoped firewall:read + blocklist:read + allowlist:read
|
|
59
59
|
# (the "firewall" preset, used by default for CLI firewall onboarding)
|
|
60
60
|
# and writes it to ./.securenow/credentials.json automatically.
|
|
61
61
|
npx securenow login
|
|
@@ -16,7 +16,7 @@ Complete reference for all environment variables supported by SecureNow.
|
|
|
16
16
|
| **SECURENOW_INSTANCE** | Optional | `https://freetrial.securenow.ai:4318` | OTLP collector base URL |
|
|
17
17
|
| **SECURENOW_API_KEY** | Optional | from credentials file | API key (same UUID as APPID). Enables firewall. |
|
|
18
18
|
| **SECURENOW_LOGGING_ENABLED** | Optional | `1` (on) | Forward `console.*` as OTLP logs. Set to `0` to disable. |
|
|
19
|
-
| **SECURENOW_CAPTURE_BODY** | Optional | `1` (on) | Capture request body. Set to `0` for
|
|
19
|
+
| **SECURENOW_CAPTURE_BODY** | Optional | `1` (on) | Capture request body. Set to `0` only for a local stream conflict. |
|
|
20
20
|
| **SECURENOW_CAPTURE_MULTIPART** | Optional | `1` (on) | Capture multipart field/file metadata. |
|
|
21
21
|
| **SECURENOW_MAX_BODY_SIZE** | Optional | `10240` | Max body size in bytes |
|
|
22
22
|
| **SECURENOW_SENSITIVE_FIELDS** | Optional | - | Comma-separated extra fields to redact |
|
|
@@ -288,11 +288,12 @@ export SECURENOW_LOGGING_ENABLED=0
|
|
|
288
288
|
|
|
289
289
|
**Format:** `1` (enabled) or `0` (disabled)
|
|
290
290
|
|
|
291
|
-
**Default:** `
|
|
291
|
+
**Default:** `1` (enabled)
|
|
292
292
|
|
|
293
293
|
**Example:**
|
|
294
294
|
```bash
|
|
295
|
-
|
|
295
|
+
# Default is enabled. Use this only to opt out:
|
|
296
|
+
export SECURENOW_CAPTURE_BODY=0
|
|
296
297
|
```
|
|
297
298
|
|
|
298
299
|
**Supported content types:**
|
|
@@ -300,8 +301,7 @@ export SECURENOW_CAPTURE_BODY=1
|
|
|
300
301
|
- `application/x-www-form-urlencoded`
|
|
301
302
|
- `application/graphql`
|
|
302
303
|
|
|
303
|
-
**Not captured
|
|
304
|
-
- `multipart/form-data` — requires `SECURENOW_CAPTURE_MULTIPART=1` (see below)
|
|
304
|
+
**Not captured:**
|
|
305
305
|
- Bodies larger than `SECURENOW_MAX_BODY_SIZE`
|
|
306
306
|
|
|
307
307
|
**Security:**
|
|
@@ -373,11 +373,12 @@ export SECURENOW_SENSITIVE_FIELDS="custom_secret,private_data,internal_id"
|
|
|
373
373
|
|
|
374
374
|
**Format:** `1` (enabled) or `0` (disabled)
|
|
375
375
|
|
|
376
|
-
**Default:** `
|
|
376
|
+
**Default:** `1` (enabled)
|
|
377
377
|
|
|
378
378
|
**Example:**
|
|
379
379
|
```bash
|
|
380
|
-
|
|
380
|
+
# Default is enabled. Use this only to opt out:
|
|
381
|
+
export SECURENOW_CAPTURE_MULTIPART=0
|
|
381
382
|
```
|
|
382
383
|
|
|
383
384
|
**What gets captured:**
|
|
@@ -405,7 +406,7 @@ export SECURENOW_CAPTURE_MULTIPART=1
|
|
|
405
406
|
|
|
406
407
|
**Parts limit:** 100 parts maximum per request (safety guard).
|
|
407
408
|
|
|
408
|
-
**
|
|
409
|
+
**Relationship to body capture:** multipart metadata capture has its own opt-out flag. Leave `SECURENOW_CAPTURE_MULTIPART` unset, `1`, or `true` to keep it enabled.
|
|
409
410
|
|
|
410
411
|
**Since:** v5.8.0
|
|
411
412
|
|
|
@@ -533,7 +534,7 @@ export NODE_ENV=test
|
|
|
533
534
|
export SECURENOW_API_KEY=snk_live_a1b2c3d4e5f6...
|
|
534
535
|
```
|
|
535
536
|
|
|
536
|
-
**v7.
|
|
537
|
+
**v7.4.0+:** the firewall also reads this key from `.securenow/credentials.json` (written by `securenow login`, which enables the selected app firewall by default, or by `securenow api-key set`). The env var only wins if it starts with `snk_live_` — otherwise the credentials file is used, so you can rely on the file for local dev without unsetting any stray env var. Setting an app UUID here (the old pre-7.1 habit) is ignored for firewall auth and would produce silent 401s; always use a `snk_live_...` key.
|
|
537
538
|
|
|
538
539
|
---
|
|
539
540
|
|
package/docs/FIREWALL-GUIDE.md
CHANGED
|
@@ -47,10 +47,11 @@ All layers share the same in-memory blocklist, synced from the SecureNow API usi
|
|
|
47
47
|
Two ways to get the firewall wired up — pick whichever fits:
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
# (a) Zero-config (v7.
|
|
51
|
-
# The
|
|
52
|
-
#
|
|
53
|
-
|
|
50
|
+
# (a) Zero-config (v7.4+): run login, pick/create an app, and connect.
|
|
51
|
+
# The selected app's firewall toggle is enabled automatically.
|
|
52
|
+
# The dashboard mints a key scoped firewall:read + blocklist:read + allowlist:read
|
|
53
|
+
# and the CLI writes it to .securenow/credentials.json. No further config needed.
|
|
54
|
+
npx securenow login
|
|
54
55
|
|
|
55
56
|
# (b) Already have a key? Drop it into the credentials file directly:
|
|
56
57
|
npx securenow api-key set snk_live_abc123...
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# SecureNow MCP Guide
|
|
2
|
+
|
|
3
|
+
SecureNow ships an MCP server for agent clients such as Codex and Claude.
|
|
4
|
+
|
|
5
|
+
## Local stdio MCP
|
|
6
|
+
|
|
7
|
+
Use this when the agent is running on the same machine as your project:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx securenow login
|
|
11
|
+
codex mcp add securenow -- npx securenow mcp
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
You can also run the server directly:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx -p securenow securenow-mcp
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The local MCP server reads the same project-local `.securenow/credentials.json`
|
|
21
|
+
as the CLI and SDK. No production deployment is required.
|
|
22
|
+
|
|
23
|
+
## Hosted MCP
|
|
24
|
+
|
|
25
|
+
For hosted clients, expose the secured API endpoint:
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
https://api.securenow.ai/mcp
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The hosted endpoint must be authenticated with `Authorization: Bearer ...`.
|
|
32
|
+
It accepts SecureNow JWT sessions and `snk_live_...` API keys through the same
|
|
33
|
+
API auth path used by the rest of SecureNow.
|
|
34
|
+
|
|
35
|
+
## Security Model
|
|
36
|
+
|
|
37
|
+
- Read tools require the matching `*:read` scope.
|
|
38
|
+
- Write tools require the matching `*:write` scope or `applications:write` for
|
|
39
|
+
app firewall settings.
|
|
40
|
+
- Write tools also require `confirm: true` and a non-empty `reason`.
|
|
41
|
+
- Full tokens and API keys are never returned by tools or resources.
|
|
42
|
+
- Hosted MCP validates browser origins and rate-limits requests.
|
|
43
|
+
- Tool calls are proxied through existing API routes so tenant isolation and
|
|
44
|
+
scope enforcement stay centralized.
|
|
45
|
+
|
|
46
|
+
## Tools
|
|
47
|
+
|
|
48
|
+
The MCP exposes applications, traces, logs, firewall, IP intelligence,
|
|
49
|
+
forensics, notifications, blocklist, allowlist, trusted IPs, analytics, bundled
|
|
50
|
+
docs resources, and setup prompts.
|