securenow 6.0.2 → 6.1.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/CONSUMING-APPS-GUIDE.md +455 -0
- package/NPM_README.md +2029 -0
- package/README.md +297 -40
- package/SKILL-API.md +634 -0
- package/SKILL-CLI.md +454 -0
- package/cidr.js +83 -0
- package/cli/apps.js +585 -0
- package/cli/auth.js +280 -0
- package/cli/client.js +115 -0
- package/cli/config.js +173 -0
- package/cli/diagnostics.js +387 -0
- package/cli/firewall.js +100 -0
- package/cli/fp.js +638 -0
- package/cli/init.js +201 -0
- package/cli/monitor.js +440 -0
- package/cli/run.js +148 -0
- package/cli/security.js +980 -0
- package/cli/ui.js +386 -0
- package/cli/utils.js +127 -0
- package/cli.js +466 -455
- package/console-instrumentation.js +147 -136
- package/docs/ALL-FRAMEWORKS-QUICKSTART.md +1377 -455
- package/docs/API-KEYS-GUIDE.md +233 -0
- package/docs/ARCHITECTURE.md +3 -3
- package/docs/AUTO-BODY-CAPTURE.md +1 -1
- package/docs/AUTO-SETUP-SUMMARY.md +331 -0
- package/docs/AUTO-SETUP.md +4 -4
- package/docs/AUTOMATIC-IP-CAPTURE.md +5 -5
- package/docs/BODY-CAPTURE-FIX.md +261 -0
- package/docs/BODY-CAPTURE-QUICKSTART.md +2 -2
- package/docs/CHANGELOG-NEXTJS.md +1 -35
- package/docs/COMPLETION-REPORT.md +408 -0
- package/docs/CUSTOMER-GUIDE.md +16 -16
- package/docs/EASIEST-SETUP.md +5 -5
- package/docs/ENVIRONMENT-VARIABLES.md +880 -652
- package/docs/EXPRESS-BODY-CAPTURE.md +13 -12
- package/docs/EXPRESS-SETUP-GUIDE.md +719 -720
- package/docs/FINAL-SOLUTION.md +335 -0
- package/docs/FIREWALL-GUIDE.md +426 -0
- package/docs/IMPLEMENTATION-SUMMARY.md +410 -0
- package/docs/INDEX.md +22 -4
- package/docs/LOGGING-GUIDE.md +701 -708
- package/docs/LOGGING-QUICKSTART.md +234 -255
- package/docs/NEXTJS-BODY-CAPTURE-COMPARISON.md +323 -0
- package/docs/NEXTJS-BODY-CAPTURE.md +2 -2
- package/docs/NEXTJS-GUIDE.md +14 -14
- package/docs/NEXTJS-QUICKSTART.md +1 -1
- package/docs/NEXTJS-SETUP-COMPLETE.md +795 -0
- package/docs/NEXTJS-WRAPPER-APPROACH.md +1 -1
- package/docs/NUXT-GUIDE.md +166 -0
- package/docs/QUICKSTART-BODY-CAPTURE.md +2 -2
- package/docs/REDACTION-EXAMPLES.md +1 -1
- package/docs/REQUEST-BODY-CAPTURE.md +19 -10
- package/docs/SOLUTION-SUMMARY.md +312 -0
- package/docs/VERCEL-OTEL-MIGRATION.md +3 -3
- package/examples/README.md +6 -6
- package/examples/instrumentation-with-auto-capture.ts +1 -1
- package/examples/nextjs-env-example.txt +2 -2
- package/examples/nextjs-instrumentation.js +1 -1
- package/examples/nextjs-instrumentation.ts +1 -1
- package/examples/nextjs-with-logging-example.md +6 -6
- package/examples/nextjs-with-options.ts +1 -1
- package/examples/test-nextjs-setup.js +1 -1
- package/firewall-cloud.js +212 -0
- package/firewall-iptables.js +139 -0
- package/firewall-only.js +38 -0
- package/firewall-tcp.js +74 -0
- package/firewall.js +720 -0
- package/free-trial-banner.js +174 -0
- package/nextjs-auto-capture.js +199 -207
- package/nextjs-middleware.js +186 -181
- package/nextjs-webpack-config.js +88 -53
- package/nextjs-wrapper.js +158 -158
- package/nextjs.d.ts +1 -1
- package/nextjs.js +639 -647
- package/nuxt-server-plugin.mjs +423 -0
- package/nuxt.d.ts +60 -0
- package/nuxt.mjs +75 -0
- package/package.json +186 -164
- package/postinstall.js +6 -6
- package/register.d.ts +1 -1
- package/register.js +39 -4
- package/resolve-ip.js +77 -0
- package/tracing.d.ts +2 -1
- package/tracing.js +295 -34
- package/web-vite.mjs +239 -156
- package/LICENSE +0 -15
package/SKILL-CLI.md
ADDED
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
# SecureNow CLI — Agent Skill
|
|
2
|
+
|
|
3
|
+
Use the `securenow` CLI to perform security DevOps from the terminal: manage apps, investigate threats, control the firewall, analyze traces, handle false positives, and run instrumented Node.js processes. Every command supports `--json` for machine-readable output.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install globally (recommended for CLI usage)
|
|
9
|
+
npm install -g securenow
|
|
10
|
+
|
|
11
|
+
# Or install per-project and use via npx
|
|
12
|
+
npm install securenow
|
|
13
|
+
npx securenow <command>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Full parity with the SDK:** every capability the `securenow` Node SDK exposes has a CLI counterpart — redaction, CIDR matching, log/span emission, firewall preload, config inspection. If you can do it in code, you can do it from the terminal.
|
|
17
|
+
|
|
18
|
+
### Authenticate
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
securenow login # opens browser OAuth; stores JWT in ~/.securenow/credentials.json
|
|
22
|
+
securenow login --token <JWT> # headless / CI login (get token from dashboard Settings)
|
|
23
|
+
securenow login --local # save credentials to this project only (.securenow/)
|
|
24
|
+
securenow whoami # verify session (shows auth source)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Per-project credentials:** Use `--local` to keep separate logins in different project directories on the same machine. Credentials resolve in order: `SECURENOW_TOKEN` env var → project `.securenow/credentials.json` → global `~/.securenow/credentials.json`.
|
|
28
|
+
|
|
29
|
+
### Integrate With Your App
|
|
30
|
+
|
|
31
|
+
The CLI can also instrument any Node.js app at launch — no code changes:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Express, Fastify, NestJS, Koa, Hapi, raw Node.js
|
|
35
|
+
securenow run src/index.js
|
|
36
|
+
|
|
37
|
+
# Or via the Node preload flag
|
|
38
|
+
node -r securenow/register src/index.js
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For Next.js, run the interactive scaffolding:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
securenow init --key snk_live_...
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This auto-detects your framework and creates the necessary `instrumentation.ts`, `next.config.js` changes, and writes your API key to `.env.local`.
|
|
48
|
+
|
|
49
|
+
### Install This Skill in Cursor
|
|
50
|
+
|
|
51
|
+
Save this file as `.cursor/skills/securenow-cli/SKILL.md` in your project. Your AI agent will auto-discover it whenever you ask about CLI commands, security investigations, or firewall management.
|
|
52
|
+
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
Config lives in `~/.securenow/` (global) and optionally `.securenow/` (per-project):
|
|
56
|
+
|
|
57
|
+
| File | Content |
|
|
58
|
+
|------|---------|
|
|
59
|
+
| `~/.securenow/config.json` | `apiUrl`, `appUrl`, `defaultApp`, `output` |
|
|
60
|
+
| `~/.securenow/credentials.json` | `token`, `email`, `expiresAt` (global) |
|
|
61
|
+
| `.securenow/credentials.json` | `token`, `email`, `expiresAt` (project-local, use `login --local`) |
|
|
62
|
+
|
|
63
|
+
**Credential resolution order:** `SECURENOW_TOKEN` env var → `.securenow/credentials.json` (project) → `~/.securenow/credentials.json` (global).
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
securenow config set apiUrl https://api.securenow.ai
|
|
67
|
+
securenow config set defaultApp my-app-key
|
|
68
|
+
securenow config get # show all
|
|
69
|
+
securenow config get defaultApp # show one
|
|
70
|
+
securenow config path # print file paths + active auth source
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Environment overrides: `SECURENOW_TOKEN` (JWT), `SECURENOW_API_URL`, `SECURENOW_APP_URL`, `SECURENOW_APP` (default app key).
|
|
74
|
+
|
|
75
|
+
## Global Flags
|
|
76
|
+
|
|
77
|
+
| Flag | Short | Effect |
|
|
78
|
+
|------|-------|--------|
|
|
79
|
+
| `--json` | `-j` | JSON output (pipe-friendly) |
|
|
80
|
+
| `--help` | | Show help for any command |
|
|
81
|
+
| `--verbose` | `-v` | Verbose output |
|
|
82
|
+
| `--force` | `-f` | Skip confirmations |
|
|
83
|
+
| `--yes` | `-y` | Auto-confirm prompts |
|
|
84
|
+
|
|
85
|
+
Debug mode: `SECURENOW_DEBUG=1 securenow <cmd>` prints stack traces on errors.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Command Reference
|
|
90
|
+
|
|
91
|
+
### Run — Instrument Any Node.js App
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
securenow run <script> # auto-detect CJS/ESM, inject OTel preload
|
|
95
|
+
securenow run --watch src/index.js # pass Node flags through
|
|
96
|
+
securenow run --inspect src/server.js --port 3000
|
|
97
|
+
securenow run --firewall-only app.js # preload firewall only (no tracing overhead)
|
|
98
|
+
securenow src/index.js # shorthand — auto-detected as "run"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Spawns `node --require securenow/register [--import otel/hook.mjs] <script>`. ESM detection uses nearest `package.json` `"type"` field or `.mjs`/`.cjs` extension. With `--firewall-only`, uses `securenow/firewall-only` instead (dotenv + firewall, no OpenTelemetry).
|
|
102
|
+
|
|
103
|
+
### Authentication
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
securenow login # browser-based OAuth (stores in global ~/.securenow/)
|
|
107
|
+
securenow login --token <JWT> # headless / CI login
|
|
108
|
+
securenow login --local # save credentials to project .securenow/ (per-project session)
|
|
109
|
+
securenow logout # clear active credentials (local if present, else global)
|
|
110
|
+
securenow logout --local # clear project-local credentials only
|
|
111
|
+
securenow whoami # show email, user ID, API URL, auth source, expiry, default app
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Applications
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
securenow apps # list all apps (default subcommand)
|
|
118
|
+
securenow apps list # same as above
|
|
119
|
+
securenow apps create <name> [--hosts h1,h2] [--instance <id>] # interactive instance picker
|
|
120
|
+
securenow apps info <id> # show app details
|
|
121
|
+
securenow apps delete <id> [--force] # delete an app
|
|
122
|
+
securenow apps default <app-key> # set default app for all commands
|
|
123
|
+
securenow apps discover [appId] [--domain example.com] # discover subdomains, add as apps
|
|
124
|
+
securenow apps scan [--yes] # scan all app domains for new subdomains
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Init — Project Setup
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
securenow init [--key <API_KEY>]
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Auto-detects framework (Next.js, Nuxt, Express, Fastify, Koa, Hapi, Node) from `package.json`. Then:
|
|
134
|
+
- **Next.js**: creates `instrumentation.ts/js`, suggests `withSecureNow()` in `next.config`
|
|
135
|
+
- **Nuxt**: tells you to add `securenow/nuxt` to modules
|
|
136
|
+
- **Node/Express/etc.**: suggests adding `-r securenow/register` to start script
|
|
137
|
+
- Writes `SECURENOW_API_KEY` to `.env.local` or `.env` if `--key` provided
|
|
138
|
+
|
|
139
|
+
### Dashboard & Status
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
securenow status [--app <key>] # dashboard overview
|
|
143
|
+
securenow analytics [--app <key>] # response analytics
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### Traces
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
securenow traces [--app <key>] [--limit N] [--start ISO] [--end ISO]
|
|
152
|
+
securenow traces list --app my-app --limit 50
|
|
153
|
+
securenow traces show <traceId> # full trace detail with spans
|
|
154
|
+
securenow traces analyze <traceId> # AI-powered trace analysis
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Logs
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
securenow logs [--app <key>] [--limit N] [--minutes M] [--level error|warn|info]
|
|
161
|
+
securenow logs list --app my-app --minutes 30 --level error
|
|
162
|
+
securenow logs trace <traceId> # logs correlated to a specific trace
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Notifications
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
securenow notifications [--limit N] [--page P]
|
|
169
|
+
securenow notifications list --limit 20
|
|
170
|
+
securenow notifications read <id> # mark one as read
|
|
171
|
+
securenow notifications read-all # mark all as read
|
|
172
|
+
securenow notifications unread # unread count
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Alerts
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
securenow alerts # list alert rules (default)
|
|
179
|
+
securenow alerts rules # list alert rules (columns: Status, Applications, Schedule)
|
|
180
|
+
securenow alerts rules show <id> # one rule; JSON: --json
|
|
181
|
+
securenow alerts rules update <id> --applications-all # all current & future apps
|
|
182
|
+
securenow alerts rules update <id> --apps key1,key2 # explicit app keys only
|
|
183
|
+
securenow alerts channels # list alert channels (Slack, email, etc.)
|
|
184
|
+
securenow alerts history [--limit N] # past triggered alerts
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
### IP Intelligence
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
securenow ip <ip-address> # lookup (geo, ASN, threat score, reputation)
|
|
193
|
+
securenow ip lookup <ip-address> # same as above
|
|
194
|
+
securenow ip traces <ip-address> # traces originating from this IP
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Forensics — Natural Language Security Queries
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
securenow forensics "show me all SQL injection attempts in the last 24h"
|
|
201
|
+
securenow forensics query "top 10 IPs by blocked requests" --app my-app
|
|
202
|
+
securenow forensics chat --app my-app # interactive forensics chat session
|
|
203
|
+
securenow forensics library # view saved/template queries
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### API Map
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
securenow api-map # list discovered API endpoints
|
|
210
|
+
securenow api-map list # same
|
|
211
|
+
securenow api-map stats # endpoint statistics
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
### Firewall
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
securenow firewall # show status (default)
|
|
220
|
+
securenow firewall status # layers, sync time, blocked count, API key info
|
|
221
|
+
securenow firewall test-ip <ip> # check if IP would be blocked
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Blocklist — Block Malicious IPs
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
securenow blocklist # list blocked IPs
|
|
228
|
+
securenow blocklist list
|
|
229
|
+
securenow blocklist add <ip> [--reason "Brute force"]
|
|
230
|
+
securenow blocklist remove <id>
|
|
231
|
+
securenow blocklist stats # block counts, top reasons
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Allowlist — Restrict to Known IPs
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
securenow allowlist # list allowed IPs
|
|
238
|
+
securenow allowlist list
|
|
239
|
+
securenow allowlist add <ip> [--label "Office"] [--reason "Corporate VPN"]
|
|
240
|
+
securenow allowlist remove <id>
|
|
241
|
+
securenow allowlist stats
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Trusted Proxies
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
securenow trusted # list trusted IPs
|
|
248
|
+
securenow trusted list
|
|
249
|
+
securenow trusted add <ip> [--label "CloudFlare edge"]
|
|
250
|
+
securenow trusted remove <id>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
### False Positive Management
|
|
256
|
+
|
|
257
|
+
The `fp` command manages exclusion rules that prevent known-safe traffic from triggering security alerts.
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
securenow fp # list all exclusion rules
|
|
261
|
+
securenow fp list
|
|
262
|
+
securenow fp show <id> # rule details
|
|
263
|
+
securenow fp delete <id> [--yes]
|
|
264
|
+
|
|
265
|
+
# Create exclusion rules
|
|
266
|
+
securenow fp create \
|
|
267
|
+
--conditions '[{"field":"http.target","op":"starts_with","value":"/api/health"}]' \
|
|
268
|
+
--match-mode all \
|
|
269
|
+
--rule-scope any_rule \
|
|
270
|
+
--reason "Health check endpoint"
|
|
271
|
+
|
|
272
|
+
# Shorthand safe-value presets
|
|
273
|
+
securenow fp create \
|
|
274
|
+
--path /api/events \
|
|
275
|
+
--method POST \
|
|
276
|
+
--path-safe standard \
|
|
277
|
+
--ua-safe standard \
|
|
278
|
+
--headers-safe standard \
|
|
279
|
+
--query-keys page,limit \
|
|
280
|
+
--headers-keys host,content-type \
|
|
281
|
+
--reason "Event webhook"
|
|
282
|
+
|
|
283
|
+
# Edit an existing rule
|
|
284
|
+
securenow fp edit <id> [--active true|false] [--conditions '[...]']
|
|
285
|
+
|
|
286
|
+
# Test conditions against a request body
|
|
287
|
+
securenow fp test-body '{"user":"admin"}' --conditions '[{"field":"body.user","op":"eq","value":"admin"}]'
|
|
288
|
+
securenow fp test-body @request.json --conditions '[...]'
|
|
289
|
+
|
|
290
|
+
# Dry-run conditions against the last 3 days of live traces
|
|
291
|
+
securenow fp dry-run --conditions '[{"field":"http.target","op":"starts_with","value":"/api/webhook"}]'
|
|
292
|
+
|
|
293
|
+
# AI-generate exclusion conditions from a description
|
|
294
|
+
securenow fp ai-fill --description "Stripe webhook POST to /api/stripe/webhook" \
|
|
295
|
+
--context '{"method":"POST","path":"/api/stripe/webhook"}'
|
|
296
|
+
|
|
297
|
+
# Mark an IP as false positive on a specific notification
|
|
298
|
+
securenow fp mark <notification-id> <ip> \
|
|
299
|
+
[--conditions '[...]'] \
|
|
300
|
+
[--reason "Known partner IP"] \
|
|
301
|
+
[--rule-scope this_rule|specific_rules|all_existing|any_rule] \
|
|
302
|
+
[--target-rules id1,id2]
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Condition fields:** `http.target`, `http.method`, `http.url`, `http.user_agent`, `http.request.header.*`, `body.*`, `http.status_code`, `net.peer.ip`, and more.
|
|
306
|
+
|
|
307
|
+
**Operators:** `eq`, `neq`, `contains`, `not_contains`, `starts_with`, `ends_with`, `regex`, `in`, `not_in`, `exists`, `not_exists`, `gt`, `lt`, `gte`, `lte`.
|
|
308
|
+
|
|
309
|
+
**Match modes:** `all` (AND logic), `any` (OR logic).
|
|
310
|
+
|
|
311
|
+
**Rule scopes:** `this_rule` (single alert rule), `specific_rules` (comma-separated IDs via `--target-rules`), `all_existing` (all current rules), `any_rule` (all current and future rules).
|
|
312
|
+
|
|
313
|
+
**Safe-value presets:** `standard` or `strict`. These auto-generate conditions that whitelist common safe patterns for paths, query strings, user-agents, and headers.
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
### Instances
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
securenow instances # list ClickHouse instances
|
|
321
|
+
securenow instances list
|
|
322
|
+
securenow instances test <id> # test connection
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
### Telemetry — Emit Logs and Spans From the Shell
|
|
328
|
+
|
|
329
|
+
Mirrors the SDK's `getLogger()` and tracing APIs. Useful for cron jobs, shell scripts, and CI pipelines that need to push events into SecureNow without booting the full OTel SDK.
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
# Send a structured log record to the OTLP collector
|
|
333
|
+
securenow log send "Deployment completed" --level info --attrs version=1.2.3,service=api
|
|
334
|
+
securenow log send "Backup failed" --level error --attrs host=db-01
|
|
335
|
+
|
|
336
|
+
# Emit a test span to verify the collector accepts OTLP traffic
|
|
337
|
+
securenow test-span
|
|
338
|
+
securenow test-span "ci.smoke-test" # custom span name
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Both commands use the resolved `SECURENOW_INSTANCE` / `OTEL_EXPORTER_OTLP_*` endpoints. Honors `OTEL_EXPORTER_OTLP_HEADERS` for API-key auth. Returns non-zero on HTTP errors so CI/cron can detect failures.
|
|
342
|
+
|
|
343
|
+
### Utilities — Redaction, CIDR, Diagnostics
|
|
344
|
+
|
|
345
|
+
These mirror the SDK exports (`redactSensitiveData`, `createMatcher`, `parseCidr`) so agents can validate behavior without writing Node.
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
# Redact sensitive fields (password, token, card, ssn, etc.)
|
|
349
|
+
securenow redact '{"user":"alice","password":"s3cret","card":"4242"}'
|
|
350
|
+
securenow redact @request.json --fields internal_id,sessionHash
|
|
351
|
+
|
|
352
|
+
# CIDR operations — match an IP against a list, or parse a range
|
|
353
|
+
securenow cidr match 10.0.0.5 10.0.0.0/24,192.168.0.0/16
|
|
354
|
+
securenow cidr parse 10.0.0.0/24 # network, broadcast, mask, size
|
|
355
|
+
|
|
356
|
+
# Show resolved config (service name, endpoints, env vars, firewall layers)
|
|
357
|
+
securenow env # human-readable
|
|
358
|
+
securenow env --json # pipe to jq
|
|
359
|
+
|
|
360
|
+
# End-to-end diagnostic: probe OTLP + API endpoints, check config
|
|
361
|
+
securenow doctor # exits 0 if healthy, 1 otherwise
|
|
362
|
+
securenow doctor --json
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
The `redact` command accepts a JSON string or `@path/to/file.json`, layers your `--fields` flag on top of `DEFAULT_SENSITIVE_FIELDS`, and also honors `SECURENOW_SENSITIVE_FIELDS` from the env. Exit code from `cidr match` is `0` if the IP matches the list, `2` otherwise — scriptable.
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## Workflow Examples for Agentic AI
|
|
370
|
+
|
|
371
|
+
### Investigate a Security Alert
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
securenow notifications list --limit 5 --json
|
|
375
|
+
# IMPORTANT: parse the ipInvestigations array for each notification — see statuses below
|
|
376
|
+
securenow ip <attacker-ip> --json
|
|
377
|
+
securenow ip traces <attacker-ip> --json
|
|
378
|
+
securenow traces show <trace-id> --json
|
|
379
|
+
securenow traces analyze <trace-id> --json
|
|
380
|
+
# Decision: block the IP
|
|
381
|
+
securenow blocklist add <attacker-ip> --reason "Automated: SQL injection detected"
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
#### Notification IP Investigation Statuses
|
|
385
|
+
|
|
386
|
+
Each notification contains an `ipInvestigations` array. **Every IP has its own `status` field** that you MUST check before taking action or raising flags. Do not rely only on top-level notification fields — always cross-reference each IP's individual investigation status.
|
|
387
|
+
|
|
388
|
+
| Status | Meaning | Action |
|
|
389
|
+
|--------|---------|--------|
|
|
390
|
+
| `open` | Still needs review — no determination yet | Investigate: run `securenow ip <ip>`, check traces, decide to block or dismiss |
|
|
391
|
+
| `false_positive` | Trusted/dismissed by exclusion rule, verified bot, or trusted IP list | **Skip** — greyed out in UI, no action needed |
|
|
392
|
+
| `blocked` | Already on the user's blocklist | **Skip** — already handled |
|
|
393
|
+
| `clean` | Pipeline analyzed and cleared as benign | **Skip** — verified safe |
|
|
394
|
+
|
|
395
|
+
**Critical workflow rule:** When investigating notifications, iterate `ipInvestigations[]` and **only flag or act on IPs with `status: "open"`**. IPs marked `false_positive`, `blocked`, or `clean` have already been triaged — do not re-flag them.
|
|
396
|
+
|
|
397
|
+
### Triage and Suppress a False Positive
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
securenow notifications list --json
|
|
401
|
+
# Identify a false positive notification
|
|
402
|
+
securenow fp ai-fill --description "Stripe webhook calls to /api/stripe/webhook"
|
|
403
|
+
# Review the suggested conditions, then create the rule
|
|
404
|
+
securenow fp create --conditions '<ai-suggested-conditions>' --rule-scope any_rule --reason "Stripe webhook"
|
|
405
|
+
# Or directly mark the notification's IP as FP
|
|
406
|
+
securenow fp mark <notification-id> <ip> --rule-scope this_rule --reason "Known Stripe IP"
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Onboard a New Application
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
securenow apps create my-new-app --hosts api.example.com,app.example.com
|
|
413
|
+
securenow apps default my-new-app
|
|
414
|
+
securenow init --key snk_live_abc123...
|
|
415
|
+
securenow run src/index.js
|
|
416
|
+
securenow status --json
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Security Posture Check
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
securenow status --json
|
|
423
|
+
securenow firewall status --json
|
|
424
|
+
securenow blocklist stats --json
|
|
425
|
+
securenow api-map stats --json
|
|
426
|
+
securenow forensics "summarize all attacks in the last 7 days"
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Discover Attack Surface
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
securenow apps discover --domain example.com
|
|
433
|
+
securenow apps scan --yes
|
|
434
|
+
securenow api-map list --json
|
|
435
|
+
securenow api-map stats --json
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## Output Parsing
|
|
441
|
+
|
|
442
|
+
All commands support `--json` for structured output. When piping to other tools or parsing programmatically, always use `--json`. Table output is the default for human readability.
|
|
443
|
+
|
|
444
|
+
## Error Handling
|
|
445
|
+
|
|
446
|
+
| Exit code / Error | Meaning | Recovery |
|
|
447
|
+
|------------------|---------|----------|
|
|
448
|
+
| `Session expired` | JWT expired | `securenow login` (or `login --local`) |
|
|
449
|
+
| `Not logged in` | No token found | `securenow login` or set `SECURENOW_TOKEN` env var |
|
|
450
|
+
| `Access denied (403)` | Insufficient plan or permissions | Upgrade plan or check user role |
|
|
451
|
+
| `Cannot connect` | API unreachable | Check `SECURENOW_API_URL` or network |
|
|
452
|
+
| `Unknown command` | Typo or unrecognized command | `securenow help` |
|
|
453
|
+
|
|
454
|
+
Set `SECURENOW_DEBUG=1` for full stack traces on any error.
|
package/cidr.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Bitmask-based CIDR matching. No regex on user input — prevents ReDoS.
|
|
5
|
+
* All operations use unsigned 32-bit integers for IPv4 addresses.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
function ipToInt(ip) {
|
|
9
|
+
const parts = ip.split('.');
|
|
10
|
+
if (parts.length !== 4) return null;
|
|
11
|
+
let result = 0;
|
|
12
|
+
for (let i = 0; i < 4; i++) {
|
|
13
|
+
const n = parseInt(parts[i], 10);
|
|
14
|
+
if (isNaN(n) || n < 0 || n > 255) return null;
|
|
15
|
+
result = (result << 8) + n;
|
|
16
|
+
}
|
|
17
|
+
return result >>> 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function parseCidr(cidr) {
|
|
21
|
+
const slash = cidr.indexOf('/');
|
|
22
|
+
if (slash === -1) return null;
|
|
23
|
+
const ip = cidr.slice(0, slash);
|
|
24
|
+
const bits = parseInt(cidr.slice(slash + 1), 10);
|
|
25
|
+
if (isNaN(bits) || bits < 0 || bits > 32) return null;
|
|
26
|
+
const network = ipToInt(ip);
|
|
27
|
+
if (network === null) return null;
|
|
28
|
+
const mask = bits === 0 ? 0 : (~((1 << (32 - bits)) - 1)) >>> 0;
|
|
29
|
+
return { network: (network & mask) >>> 0, mask };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function matchesCidr(ipInt, cidrEntry) {
|
|
33
|
+
return ((ipInt & cidrEntry.mask) >>> 0) === cidrEntry.network;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Create a matcher from a list of IPs and CIDRs.
|
|
38
|
+
* Returns { isBlocked(ip), stats() }.
|
|
39
|
+
* Exact IPs use a Set for O(1) lookup; CIDRs use array scan (typically < 100 entries).
|
|
40
|
+
*/
|
|
41
|
+
function createMatcher(ipList) {
|
|
42
|
+
const exactSet = new Set();
|
|
43
|
+
const cidrRanges = [];
|
|
44
|
+
|
|
45
|
+
for (const entry of ipList) {
|
|
46
|
+
const trimmed = (entry || '').trim();
|
|
47
|
+
if (!trimmed) continue;
|
|
48
|
+
|
|
49
|
+
if (trimmed.includes('/')) {
|
|
50
|
+
const parsed = parseCidr(trimmed);
|
|
51
|
+
if (parsed) cidrRanges.push(parsed);
|
|
52
|
+
} else {
|
|
53
|
+
const normalized = trimmed.replace(/^::ffff:/, '');
|
|
54
|
+
exactSet.add(normalized);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isBlocked(ip) {
|
|
59
|
+
if (!ip) return false;
|
|
60
|
+
const normalized = ip.replace(/^::ffff:/, '');
|
|
61
|
+
|
|
62
|
+
if (exactSet.has(normalized)) return true;
|
|
63
|
+
|
|
64
|
+
if (cidrRanges.length > 0) {
|
|
65
|
+
const ipInt = ipToInt(normalized);
|
|
66
|
+
if (ipInt !== null) {
|
|
67
|
+
for (const cidr of cidrRanges) {
|
|
68
|
+
if (matchesCidr(ipInt, cidr)) return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function stats() {
|
|
77
|
+
return { exact: exactSet.size, cidr: cidrRanges.length, total: exactSet.size + cidrRanges.length };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return { isBlocked, stats };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
module.exports = { ipToInt, parseCidr, matchesCidr, createMatcher };
|