securenow 8.11.1 → 8.11.3
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 +3 -1
- package/README.md +2 -0
- package/SKILL-API.md +3 -1
- package/SKILL-CLI.md +625 -632
- package/TELEMETRY-SQL.md +6 -1
- package/cidr.js +83 -83
- package/cli/client.js +102 -102
- package/cli/diagnostics.js +4 -0
- package/cli/firewall.js +141 -141
- package/cli/fp.js +638 -638
- package/cli/monitor.js +398 -398
- package/cli/run.js +132 -132
- package/cli/security.js +1866 -1856
- package/cli/ui.js +374 -374
- package/cli.js +923 -922
- package/firewall-cloud.js +202 -202
- package/firewall-iptables.js +139 -139
- package/firewall-only.js +46 -46
- package/firewall-tcp.js +74 -74
- package/firewall.js +1470 -1470
- package/legacy-semconv.js +4 -3
- package/mcp/catalog.js +2358 -2346
- package/nextjs-auto-capture.d.ts +29 -29
- package/nextjs-auto-capture.js +280 -274
- package/nextjs-middleware.d.ts +57 -57
- package/nextjs-middleware.js +274 -268
- package/nextjs-webpack-config.js +79 -79
- package/nextjs-wrapper.d.ts +95 -95
- package/nextjs-wrapper.js +240 -234
- package/nextjs.js +19 -12
- package/nuxt-server-plugin.mjs +11 -5
- package/nuxt.mjs +74 -74
- package/otp-redaction.js +99 -0
- package/package.json +3 -2
- package/register.d.ts +42 -42
- package/register.js +44 -44
- package/resolve-ip.js +13 -13
- package/telemetry-schema.json +3 -1
- package/tracing.js +860 -855
package/cli/firewall.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
3
|
const { api, requireAuth } = require('./client');
|
|
4
4
|
const ui = require('./ui');
|
|
5
5
|
|
|
6
6
|
function resolveEnvironment(flags) {
|
|
7
7
|
return flags.env || flags.environment || 'production';
|
|
8
8
|
}
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
async function status(args, flags) {
|
|
11
11
|
requireAuth();
|
|
12
12
|
const s = ui.spinner('Checking firewall status');
|
|
@@ -17,64 +17,64 @@ async function status(args, flags) {
|
|
|
17
17
|
const query = { environment };
|
|
18
18
|
if (appKey) query.appKey = appKey;
|
|
19
19
|
const data = await api.get('/firewall/status', { query });
|
|
20
|
-
|
|
21
|
-
s.stop('Firewall status retrieved');
|
|
22
|
-
|
|
23
|
-
if (flags.json) {
|
|
24
|
-
ui.json(data);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
console.log('');
|
|
20
|
+
|
|
21
|
+
s.stop('Firewall status retrieved');
|
|
22
|
+
|
|
23
|
+
if (flags.json) {
|
|
24
|
+
ui.json(data);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
console.log('');
|
|
29
29
|
const enabledLabel = data.firewallEnabled === false
|
|
30
30
|
? ui.c.bold(ui.c.yellow('Firewall: DISABLED FOR APP/ENV'))
|
|
31
31
|
: ui.c.bold(ui.c.green('Firewall: ENABLED'));
|
|
32
32
|
console.log(` ${enabledLabel}`);
|
|
33
|
-
console.log('');
|
|
34
|
-
ui.keyValue([
|
|
33
|
+
console.log('');
|
|
34
|
+
ui.keyValue([
|
|
35
35
|
['Blocked IPs', `${data.totalIps} total`],
|
|
36
36
|
['Global blocked IPs', `${data.globalBlockIps ?? data.totalIps} total (${data.exactCount} exact + ${data.cidrCount} CIDR ranges)`],
|
|
37
37
|
['Scoped block rules', String(data.scopedBlockRuleCount ?? 0)],
|
|
38
38
|
['App scope', appKey || 'all apps'],
|
|
39
39
|
['Environment', data.environment || environment],
|
|
40
|
-
['Last updated', data.updatedAt || 'unknown'],
|
|
40
|
+
['Last updated', data.updatedAt || 'unknown'],
|
|
41
41
|
['Allowed IPs', data.allowlistCount != null ? `${data.allowlistCount} total (${data.allowlistExactCount} exact + ${data.allowlistCidrCount} CIDR ranges)` : '0'],
|
|
42
42
|
['Allowlist updated', data.allowlistUpdatedAt || 'never'],
|
|
43
43
|
['Rate limit rules', String(data.rateLimitCount ?? 0)],
|
|
44
44
|
['Sync TTL', `${data.ttl || 60}s`],
|
|
45
45
|
]);
|
|
46
|
-
if (data.allowlistCount > 0) {
|
|
47
|
-
console.log('');
|
|
48
|
-
console.log(` ${ui.c.yellow('!')} Allowlist is active — only ${data.allowlistCount} IP(s) can reach your app`);
|
|
49
|
-
}
|
|
50
|
-
console.log('');
|
|
51
|
-
console.log(` ${ui.c.dim('Manage your blocklist:')} securenow blocklist`);
|
|
52
|
-
console.log(` ${ui.c.dim('Manage your allowlist:')} securenow allowlist`);
|
|
53
|
-
console.log(` ${ui.c.dim('Test an IP:')} securenow firewall test-ip <ip>`);
|
|
54
|
-
console.log('');
|
|
55
|
-
} catch (err) {
|
|
56
|
-
if (err.statusCode === 401 || err.status === 401) {
|
|
57
|
-
s.fail('Authentication failed');
|
|
58
|
-
ui.error('API key is invalid or missing the firewall:read scope.');
|
|
59
|
-
ui.info('Create an API key with firewall:read scope in the dashboard.');
|
|
60
|
-
} else {
|
|
61
|
-
s.fail('Failed to check firewall status');
|
|
62
|
-
throw err;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async function testIp(args, flags) {
|
|
68
|
-
requireAuth();
|
|
69
|
-
const ip = args[0];
|
|
70
|
-
if (!ip) {
|
|
71
|
-
ui.error('Usage: securenow firewall test-ip <ip-address>');
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const s = ui.spinner(`Testing IP ${ip}`);
|
|
76
|
-
|
|
77
|
-
try {
|
|
46
|
+
if (data.allowlistCount > 0) {
|
|
47
|
+
console.log('');
|
|
48
|
+
console.log(` ${ui.c.yellow('!')} Allowlist is active — only ${data.allowlistCount} IP(s) can reach your app`);
|
|
49
|
+
}
|
|
50
|
+
console.log('');
|
|
51
|
+
console.log(` ${ui.c.dim('Manage your blocklist:')} securenow blocklist`);
|
|
52
|
+
console.log(` ${ui.c.dim('Manage your allowlist:')} securenow allowlist`);
|
|
53
|
+
console.log(` ${ui.c.dim('Test an IP:')} securenow firewall test-ip <ip>`);
|
|
54
|
+
console.log('');
|
|
55
|
+
} catch (err) {
|
|
56
|
+
if (err.statusCode === 401 || err.status === 401) {
|
|
57
|
+
s.fail('Authentication failed');
|
|
58
|
+
ui.error('API key is invalid or missing the firewall:read scope.');
|
|
59
|
+
ui.info('Create an API key with firewall:read scope in the dashboard.');
|
|
60
|
+
} else {
|
|
61
|
+
s.fail('Failed to check firewall status');
|
|
62
|
+
throw err;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function testIp(args, flags) {
|
|
68
|
+
requireAuth();
|
|
69
|
+
const ip = args[0];
|
|
70
|
+
if (!ip) {
|
|
71
|
+
ui.error('Usage: securenow firewall test-ip <ip-address>');
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const s = ui.spinner(`Testing IP ${ip}`);
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
78
|
const environment = resolveEnvironment(flags);
|
|
79
79
|
const appKey = await resolveAppKey(flags);
|
|
80
80
|
const query = { environment };
|
|
@@ -82,14 +82,14 @@ async function testIp(args, flags) {
|
|
|
82
82
|
if (flags.path || flags.route) query.path = flags.path || flags.route;
|
|
83
83
|
if (flags.method) query.method = flags.method;
|
|
84
84
|
const data = await api.get(`/firewall/check/${encodeURIComponent(ip)}`, { query });
|
|
85
|
-
|
|
86
|
-
s.stop(`IP ${ip} checked`);
|
|
87
|
-
|
|
88
|
-
if (flags.json) {
|
|
89
|
-
ui.json(data);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
85
|
+
|
|
86
|
+
s.stop(`IP ${ip} checked`);
|
|
87
|
+
|
|
88
|
+
if (flags.json) {
|
|
89
|
+
ui.json(data);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
93
|
console.log('');
|
|
94
94
|
if (data.firewallEnabled === false) {
|
|
95
95
|
console.log(` ${ui.c.bold(ui.c.yellow('NOT ENFORCED'))} — firewall is disabled for ${appKey || 'this app'} (${data.environment || environment})`);
|
|
@@ -98,11 +98,11 @@ async function testIp(args, flags) {
|
|
|
98
98
|
return;
|
|
99
99
|
}
|
|
100
100
|
if (data.blocked) {
|
|
101
|
-
if (data.allowlistActive && !data.allowlisted) {
|
|
102
|
-
console.log(` ${ui.c.bold(ui.c.red('BLOCKED'))} — ${ip} is not on the allowlist`);
|
|
103
|
-
console.log(` ${ui.c.dim('Allowlist is active — only listed IPs are permitted')}`);
|
|
104
|
-
} else {
|
|
105
|
-
console.log(` ${ui.c.bold(ui.c.red('BLOCKED'))} — ${ip} is in the blocklist`);
|
|
101
|
+
if (data.allowlistActive && !data.allowlisted) {
|
|
102
|
+
console.log(` ${ui.c.bold(ui.c.red('BLOCKED'))} — ${ip} is not on the allowlist`);
|
|
103
|
+
console.log(` ${ui.c.dim('Allowlist is active — only listed IPs are permitted')}`);
|
|
104
|
+
} else {
|
|
105
|
+
console.log(` ${ui.c.bold(ui.c.red('BLOCKED'))} — ${ip} is in the blocklist`);
|
|
106
106
|
if (data.matchedEntry && data.matchedEntry !== ip) {
|
|
107
107
|
console.log(` ${ui.c.dim(`Matched by: ${data.matchedEntry}`)}`);
|
|
108
108
|
}
|
|
@@ -113,89 +113,89 @@ async function testIp(args, flags) {
|
|
|
113
113
|
console.log(` ${ui.c.dim(`Rule scope: ${scope}`)}`);
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
|
-
} else {
|
|
117
|
-
if (data.allowlisted) {
|
|
118
|
-
console.log(` ${ui.c.bold(ui.c.green('ALLOWED'))} — ${ip} is on the allowlist`);
|
|
119
|
-
} else {
|
|
120
|
-
console.log(` ${ui.c.bold(ui.c.green('ALLOWED'))} — ${ip} is not in the blocklist`);
|
|
121
|
-
}
|
|
116
|
+
} else {
|
|
117
|
+
if (data.allowlisted) {
|
|
118
|
+
console.log(` ${ui.c.bold(ui.c.green('ALLOWED'))} — ${ip} is on the allowlist`);
|
|
119
|
+
} else {
|
|
120
|
+
console.log(` ${ui.c.bold(ui.c.green('ALLOWED'))} — ${ip} is not in the blocklist`);
|
|
121
|
+
}
|
|
122
122
|
}
|
|
123
123
|
console.log(` ${ui.c.dim(`App scope: ${appKey || 'all apps'} · Environment: ${data.environment || environment}`)}`);
|
|
124
124
|
if (data.path) console.log(` ${ui.c.dim(`Request scope: ${data.method || 'GET'} ${data.path}`)}`);
|
|
125
125
|
if (data.scopedMatchRequiresPath) console.log(` ${ui.c.dim('Scoped block rules exist; pass --path to test route-specific matches')}`);
|
|
126
126
|
console.log(` ${ui.c.dim(`Blocklist contains ${data.totalBlockedIps} entries (${data.scopedBlockRuleCount || 0} scoped)`)}`);
|
|
127
|
-
if (data.allowlistActive) {
|
|
128
|
-
console.log(` ${ui.c.dim('Allowlist is active')}`);
|
|
129
|
-
}
|
|
130
|
-
console.log('');
|
|
131
|
-
} catch (err) {
|
|
132
|
-
s.fail('Failed to test IP');
|
|
133
|
-
throw err;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async function resolveAppKey(flags) {
|
|
138
|
-
if (flags && flags.app) return String(flags.app);
|
|
139
|
-
try {
|
|
140
|
-
const { resolveAppKey: r } = require('../app-config');
|
|
141
|
-
const k = r();
|
|
142
|
-
if (k) return k;
|
|
143
|
-
} catch (_) {}
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async function setEnabled(args, flags, enabled) {
|
|
148
|
-
requireAuth();
|
|
149
|
-
const appKey = await resolveAppKey(flags);
|
|
150
|
-
if (!appKey) {
|
|
127
|
+
if (data.allowlistActive) {
|
|
128
|
+
console.log(` ${ui.c.dim('Allowlist is active')}`);
|
|
129
|
+
}
|
|
130
|
+
console.log('');
|
|
131
|
+
} catch (err) {
|
|
132
|
+
s.fail('Failed to test IP');
|
|
133
|
+
throw err;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function resolveAppKey(flags) {
|
|
138
|
+
if (flags && flags.app) return String(flags.app);
|
|
139
|
+
try {
|
|
140
|
+
const { resolveAppKey: r } = require('../app-config');
|
|
141
|
+
const k = r();
|
|
142
|
+
if (k) return k;
|
|
143
|
+
} catch (_) {}
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function setEnabled(args, flags, enabled) {
|
|
148
|
+
requireAuth();
|
|
149
|
+
const appKey = await resolveAppKey(flags);
|
|
150
|
+
if (!appKey) {
|
|
151
151
|
ui.error('No app selected. Pass --app <key> or run `securenow app connect` / `securenow apps default <key>`.');
|
|
152
|
-
process.exit(1);
|
|
153
|
-
}
|
|
154
|
-
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
155
|
const environment = resolveEnvironment(flags);
|
|
156
156
|
const verb = enabled ? 'Enabling' : 'Disabling';
|
|
157
157
|
const s = ui.spinner(`${verb} firewall for ${appKey} (${environment})`);
|
|
158
158
|
try {
|
|
159
159
|
const data = await api.patch(`/firewall/app/${encodeURIComponent(appKey)}`, { enabled, environment });
|
|
160
|
-
s.stop(`Firewall ${enabled ? 'enabled' : 'disabled'}`);
|
|
161
|
-
|
|
162
|
-
if (flags.json) { ui.json(data); return; }
|
|
163
|
-
|
|
164
|
-
const app = data.app || {};
|
|
165
|
-
console.log('');
|
|
166
|
-
console.log(` ${ui.c.bold(enabled ? ui.c.green('Firewall: ENABLED') : ui.c.yellow('Firewall: DISABLED'))} — ${app.name || appKey}`);
|
|
160
|
+
s.stop(`Firewall ${enabled ? 'enabled' : 'disabled'}`);
|
|
161
|
+
|
|
162
|
+
if (flags.json) { ui.json(data); return; }
|
|
163
|
+
|
|
164
|
+
const app = data.app || {};
|
|
165
|
+
console.log('');
|
|
166
|
+
console.log(` ${ui.c.bold(enabled ? ui.c.green('Firewall: ENABLED') : ui.c.yellow('Firewall: DISABLED'))} — ${app.name || appKey}`);
|
|
167
167
|
console.log(` ${ui.c.dim('App key:')} ${app.key || appKey}`);
|
|
168
168
|
console.log(` ${ui.c.dim('Environment:')} ${app.environment || environment}`);
|
|
169
|
-
console.log('');
|
|
170
|
-
console.log(` ${ui.c.dim('Running SDK instances pick up the change within ~10s.')}`);
|
|
171
|
-
console.log('');
|
|
172
|
-
} catch (err) {
|
|
173
|
-
s.fail(`Failed to ${enabled ? 'enable' : 'disable'} firewall`);
|
|
174
|
-
throw err;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
async function enable(args, flags) { return setEnabled(args, flags, true); }
|
|
179
|
-
async function disable(args, flags) { return setEnabled(args, flags, false); }
|
|
180
|
-
|
|
181
|
-
async function appsList(args, flags) {
|
|
182
|
-
requireAuth();
|
|
183
|
-
const s = ui.spinner('Loading apps');
|
|
184
|
-
try {
|
|
185
|
-
const data = await api.get('/firewall/apps');
|
|
186
|
-
s.stop('Apps loaded');
|
|
187
|
-
|
|
188
|
-
if (flags.json) { ui.json(data); return; }
|
|
189
|
-
|
|
190
|
-
const apps = data.apps || [];
|
|
191
|
-
if (apps.length === 0) {
|
|
192
|
-
console.log('');
|
|
193
|
-
console.log(` ${ui.c.dim('No apps yet. Create one with `securenow apps create <name>`.')}`);
|
|
194
|
-
console.log('');
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
console.log('');
|
|
169
|
+
console.log('');
|
|
170
|
+
console.log(` ${ui.c.dim('Running SDK instances pick up the change within ~10s.')}`);
|
|
171
|
+
console.log('');
|
|
172
|
+
} catch (err) {
|
|
173
|
+
s.fail(`Failed to ${enabled ? 'enable' : 'disable'} firewall`);
|
|
174
|
+
throw err;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async function enable(args, flags) { return setEnabled(args, flags, true); }
|
|
179
|
+
async function disable(args, flags) { return setEnabled(args, flags, false); }
|
|
180
|
+
|
|
181
|
+
async function appsList(args, flags) {
|
|
182
|
+
requireAuth();
|
|
183
|
+
const s = ui.spinner('Loading apps');
|
|
184
|
+
try {
|
|
185
|
+
const data = await api.get('/firewall/apps');
|
|
186
|
+
s.stop('Apps loaded');
|
|
187
|
+
|
|
188
|
+
if (flags.json) { ui.json(data); return; }
|
|
189
|
+
|
|
190
|
+
const apps = data.apps || [];
|
|
191
|
+
if (apps.length === 0) {
|
|
192
|
+
console.log('');
|
|
193
|
+
console.log(` ${ui.c.dim('No apps yet. Create one with `securenow apps create <name>`.')}`);
|
|
194
|
+
console.log('');
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
console.log('');
|
|
199
199
|
for (const a of apps) {
|
|
200
200
|
const tag = a.firewallEnabled ? ui.c.green('ON ') : ui.c.yellow('OFF');
|
|
201
201
|
console.log(` ${tag} ${ui.c.bold(a.name)} ${ui.c.dim(a.key)}`);
|
|
@@ -206,14 +206,14 @@ async function appsList(args, flags) {
|
|
|
206
206
|
if (envLine) console.log(` ${ui.c.dim(envLine)}`);
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
|
-
console.log('');
|
|
210
|
-
console.log(` ${ui.c.dim('Toggle:')} securenow firewall enable --app <key>`);
|
|
211
|
-
console.log(` ${ui.c.dim(' :')} securenow firewall disable --app <key>`);
|
|
212
|
-
console.log('');
|
|
213
|
-
} catch (err) {
|
|
214
|
-
s.fail('Failed to list apps');
|
|
215
|
-
throw err;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
module.exports = { status, testIp, enable, disable, appsList };
|
|
209
|
+
console.log('');
|
|
210
|
+
console.log(` ${ui.c.dim('Toggle:')} securenow firewall enable --app <key>`);
|
|
211
|
+
console.log(` ${ui.c.dim(' :')} securenow firewall disable --app <key>`);
|
|
212
|
+
console.log('');
|
|
213
|
+
} catch (err) {
|
|
214
|
+
s.fail('Failed to list apps');
|
|
215
|
+
throw err;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
module.exports = { status, testIp, enable, disable, appsList };
|