securenow 7.5.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.
@@ -39,6 +39,7 @@ function resolvedConfig() {
39
39
  const apiUrl = config.getApiUrl();
40
40
  const loggingEnabled = !/^(0|false)$/i.test(String(process.env.SECURENOW_LOGGING_ENABLED ?? ''));
41
41
  const captureBody = !/^(0|false)$/i.test(String(process.env.SECURENOW_CAPTURE_BODY ?? ''));
42
+ const captureMultipart = !/^(0|false)$/i.test(String(process.env.SECURENOW_CAPTURE_MULTIPART ?? ''));
42
43
  const firewallEnabled =
43
44
  !!apiKey && process.env.SECURENOW_FIREWALL_ENABLED !== '0';
44
45
 
@@ -52,6 +53,7 @@ function resolvedConfig() {
52
53
  apiUrl,
53
54
  loggingEnabled,
54
55
  captureBody,
56
+ captureMultipart,
55
57
  firewallEnabled,
56
58
  firewallLayers: {
57
59
  http: firewallEnabled,
@@ -62,6 +64,21 @@ function resolvedConfig() {
62
64
  };
63
65
  }
64
66
 
67
+ function maskSecret(value) {
68
+ if (!value) return '';
69
+ const text = String(value);
70
+ if (text.length <= 12) return '***';
71
+ return `${text.slice(0, 12)}...${text.slice(-4)}`;
72
+ }
73
+
74
+ function redactConfig(cfg) {
75
+ return {
76
+ ...cfg,
77
+ headers: cfg.headers ? '***' : '',
78
+ apiKey: cfg.apiKey ? maskSecret(cfg.apiKey) : '',
79
+ };
80
+ }
81
+
65
82
  function parseHeaders(str) {
66
83
  const out = {};
67
84
  if (!str) return out;
@@ -305,6 +322,7 @@ function env(_args, flags) {
305
322
  SECURENOW_API_URL: cfg.apiUrl,
306
323
  SECURENOW_LOGGING_ENABLED: cfg.loggingEnabled ? '1' : '0',
307
324
  SECURENOW_CAPTURE_BODY: cfg.captureBody ? '1' : '0',
325
+ SECURENOW_CAPTURE_MULTIPART: cfg.captureMultipart ? '1' : '0',
308
326
  SECURENOW_NO_UUID: process.env.SECURENOW_NO_UUID || `(auto: ${require('../app-config').resolveNoUuid() ? '1' : '0'})`,
309
327
  SECURENOW_FIREWALL_TCP: process.env.SECURENOW_FIREWALL_TCP || '0',
310
328
  SECURENOW_FIREWALL_IPTABLES: process.env.SECURENOW_FIREWALL_IPTABLES || '0',
@@ -313,7 +331,7 @@ function env(_args, flags) {
313
331
  };
314
332
 
315
333
  if (flags.json) {
316
- ui.json({ resolved: cfg, env: vars });
334
+ ui.json({ resolved: redactConfig(cfg), env: vars });
317
335
  return;
318
336
  }
319
337
 
@@ -324,6 +342,7 @@ function env(_args, flags) {
324
342
  ['Logs endpoint', cfg.logsEndpoint],
325
343
  ['Logging', cfg.loggingEnabled ? ui.c.green('enabled') : ui.c.dim('disabled')],
326
344
  ['Body capture', cfg.captureBody ? ui.c.green('enabled') : ui.c.dim('disabled')],
345
+ ['Multipart capture', cfg.captureMultipart ? ui.c.green('enabled') : ui.c.dim('disabled')],
327
346
  ['Firewall', cfg.firewallEnabled ? ui.c.green('enabled') : ui.c.dim('disabled (no API key)')],
328
347
  ]);
329
348
 
@@ -377,7 +396,7 @@ async function doctor(_args, flags) {
377
396
  const ok = checks.every((c) => c.ok);
378
397
 
379
398
  if (flags.json) {
380
- ui.json({ ok, resolved: cfg, checks, warnings });
399
+ ui.json({ ok, resolved: redactConfig(cfg), checks, warnings });
381
400
  process.exit(ok ? 0 : 1);
382
401
  }
383
402
 
package/cli/init.js CHANGED
@@ -1,24 +1,52 @@
1
1
  'use strict';
2
2
 
3
- const fs = require('fs');
4
- const path = require('path');
5
- const ui = require('./ui');
6
-
7
- const INSTRUMENTATION_JS = `export async function register() {
8
- if (process.env.NEXT_RUNTIME === 'nodejs') {
9
- const { registerSecureNow } = require('securenow/nextjs');
10
- registerSecureNow();
11
- }
12
- }
13
- `;
14
-
15
- const INSTRUMENTATION_TS = `export async function register() {
16
- if (process.env.NEXT_RUNTIME === 'nodejs') {
17
- const { registerSecureNow } = require('securenow/nextjs');
18
- registerSecureNow();
19
- }
20
- }
21
- `;
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const ui = require('./ui');
6
+ const config = require('./config');
7
+
8
+ const DEFAULT_ENV = {
9
+ SECURENOW_LOGGING_ENABLED: '1',
10
+ SECURENOW_CAPTURE_BODY: '1',
11
+ SECURENOW_CAPTURE_MULTIPART: '1',
12
+ SECURENOW_FIREWALL_ENABLED: '1',
13
+ };
14
+
15
+ const INSTRUMENTATION_JS = `import { createRequire } from 'node:module';
16
+
17
+ const require = createRequire(import.meta.url);
18
+
19
+ export async function register() {
20
+ if (process.env.NEXT_RUNTIME !== 'nodejs') return;
21
+
22
+ process.env.SECURENOW_LOGGING_ENABLED ??= '1';
23
+ process.env.SECURENOW_CAPTURE_BODY ??= '1';
24
+ process.env.SECURENOW_CAPTURE_MULTIPART ??= '1';
25
+ process.env.SECURENOW_FIREWALL_ENABLED ??= '1';
26
+
27
+ const { registerSecureNow } = require('securenow/nextjs');
28
+ registerSecureNow({ captureBody: true });
29
+ require('securenow/nextjs-auto-capture');
30
+ }
31
+ `;
32
+
33
+ const INSTRUMENTATION_TS = `import { createRequire } from 'node:module';
34
+
35
+ const require = createRequire(import.meta.url);
36
+
37
+ export async function register() {
38
+ if (process.env.NEXT_RUNTIME !== 'nodejs') return;
39
+
40
+ process.env.SECURENOW_LOGGING_ENABLED ??= '1';
41
+ process.env.SECURENOW_CAPTURE_BODY ??= '1';
42
+ process.env.SECURENOW_CAPTURE_MULTIPART ??= '1';
43
+ process.env.SECURENOW_FIREWALL_ENABLED ??= '1';
44
+
45
+ const { registerSecureNow } = require('securenow/nextjs');
46
+ registerSecureNow({ captureBody: true });
47
+ require('securenow/nextjs-auto-capture');
48
+ }
49
+ `;
22
50
 
23
51
  function detectProject(dir) {
24
52
  const pkgPath = path.join(dir, 'package.json');
@@ -165,37 +193,52 @@ function initNode(dir, project) {
165
193
  }
166
194
  }
167
195
 
168
- function initEnv(dir, flags) {
169
- const envFiles = ['.env', '.env.local'];
170
- let envPath = null;
171
-
172
- for (const f of envFiles) {
173
- const p = path.join(dir, f);
174
- if (fs.existsSync(p)) {
175
- const content = fs.readFileSync(p, 'utf8');
176
- if (content.includes('SECURENOW_API_KEY')) {
177
- ui.info(`SECURENOW_API_KEY already set in ${f}`);
178
- return;
179
- }
180
- envPath = p;
181
- break;
182
- }
183
- }
184
-
185
- if (!envPath) envPath = path.join(dir, '.env.local');
186
-
187
- const apiKey = flags.key || flags['api-key'] || '';
188
- if (apiKey) {
189
- const existing = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf8') : '';
190
- const sep = existing && !existing.endsWith('\n') ? '\n' : '';
191
- fs.appendFileSync(envPath, `${sep}SECURENOW_API_KEY=${apiKey}\n`, 'utf8');
192
- ui.success(`Added SECURENOW_API_KEY to ${path.basename(envPath)}`);
193
- } else {
194
- ui.warn(`Add your API key to ${path.basename(envPath)}:`);
195
- console.log('');
196
- console.log(' SECURENOW_API_KEY=snk_live_...');
197
- console.log('');
198
- }
199
- }
196
+ function initEnv(dir, flags) {
197
+ const envFiles = ['.env', '.env.local'];
198
+ let envPath = null;
199
+
200
+ for (const f of envFiles) {
201
+ const p = path.join(dir, f);
202
+ if (fs.existsSync(p)) {
203
+ envPath = p;
204
+ break;
205
+ }
206
+ }
207
+
208
+ if (!envPath) envPath = path.join(dir, '.env.local');
209
+
210
+ const existing = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf8') : '';
211
+ const additions = [];
212
+ for (const [key, value] of Object.entries(DEFAULT_ENV)) {
213
+ if (!hasEnvKey(existing, key)) additions.push(`${key}=${value}`);
214
+ }
215
+
216
+ const explicitApiKey = flags.key || flags['api-key'] || '';
217
+ const hasApiKey = hasEnvKey(existing, 'SECURENOW_API_KEY');
218
+ if (explicitApiKey && !hasApiKey) additions.push(`SECURENOW_API_KEY=${explicitApiKey}`);
219
+
220
+ if (additions.length > 0) {
221
+ const sep = existing && !existing.endsWith('\n') ? '\n' : '';
222
+ fs.appendFileSync(envPath, `${sep}${additions.join('\n')}\n`, 'utf8');
223
+ ui.success(`Updated ${path.basename(envPath)} with SecureNow defaults`);
224
+ } else {
225
+ ui.info(`${path.basename(envPath)} already contains SecureNow defaults`);
226
+ }
227
+
228
+ if (hasApiKey || explicitApiKey) {
229
+ ui.info(`SECURENOW_API_KEY is set in ${path.basename(envPath)}`);
230
+ } else if (config.getApiKey()) {
231
+ ui.info('Using firewall API key from project .securenow/credentials.json');
232
+ } else {
233
+ ui.warn(`Add your API key to ${path.basename(envPath)}:`);
234
+ console.log('');
235
+ console.log(' SECURENOW_API_KEY=snk_live_...');
236
+ console.log('');
237
+ }
238
+ }
239
+
240
+ function hasEnvKey(content, key) {
241
+ return new RegExp(`^\\s*${key}\\s*=`, 'm').test(content || '');
242
+ }
200
243
 
201
244
  module.exports = { init };
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 subheading(text) {
119
- console.log(`\n ${c.bold(text)}`);
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
- subheading,
372
+ stripAnsi,
373
+ table,
374
+ keyValue,
375
+ heading,
376
+ header,
377
+ bold,
378
+ subheading,
369
379
  success,
370
380
  error,
371
381
  warn,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securenow",
3
- "version": "7.5.0",
3
+ "version": "7.5.1",
4
4
  "description": "OpenTelemetry instrumentation for Node.js, Next.js, and Nuxt - Send traces and logs to any OTLP-compatible backend",
5
5
  "type": "commonjs",
6
6
  "main": "register.js",