securenow 5.18.0 → 6.0.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.
Files changed (85) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +40 -239
  3. package/cli.js +455 -415
  4. package/console-instrumentation.js +136 -147
  5. package/docs/ALL-FRAMEWORKS-QUICKSTART.md +455 -1339
  6. package/docs/ARCHITECTURE.md +3 -3
  7. package/docs/AUTO-BODY-CAPTURE.md +1 -1
  8. package/docs/AUTO-SETUP.md +4 -4
  9. package/docs/AUTOMATIC-IP-CAPTURE.md +5 -5
  10. package/docs/BODY-CAPTURE-QUICKSTART.md +2 -2
  11. package/docs/CHANGELOG-NEXTJS.md +1 -1
  12. package/docs/CUSTOMER-GUIDE.md +16 -16
  13. package/docs/EASIEST-SETUP.md +5 -5
  14. package/docs/ENVIRONMENT-VARIABLES.md +652 -880
  15. package/docs/EXPRESS-BODY-CAPTURE.md +12 -13
  16. package/docs/EXPRESS-SETUP-GUIDE.md +720 -719
  17. package/docs/INDEX.md +4 -22
  18. package/docs/LOGGING-GUIDE.md +708 -701
  19. package/docs/LOGGING-QUICKSTART.md +239 -234
  20. package/docs/NEXTJS-BODY-CAPTURE.md +2 -2
  21. package/docs/NEXTJS-GUIDE.md +14 -14
  22. package/docs/NEXTJS-QUICKSTART.md +1 -1
  23. package/docs/NEXTJS-WRAPPER-APPROACH.md +1 -1
  24. package/docs/QUICKSTART-BODY-CAPTURE.md +2 -2
  25. package/docs/REDACTION-EXAMPLES.md +1 -1
  26. package/docs/REQUEST-BODY-CAPTURE.md +10 -19
  27. package/docs/VERCEL-OTEL-MIGRATION.md +3 -3
  28. package/examples/README.md +6 -6
  29. package/examples/instrumentation-with-auto-capture.ts +1 -1
  30. package/examples/nextjs-env-example.txt +2 -2
  31. package/examples/nextjs-instrumentation.js +1 -1
  32. package/examples/nextjs-instrumentation.ts +1 -1
  33. package/examples/nextjs-with-logging-example.md +6 -6
  34. package/examples/nextjs-with-options.ts +1 -1
  35. package/examples/test-nextjs-setup.js +1 -1
  36. package/nextjs-auto-capture.js +207 -199
  37. package/nextjs-middleware.js +181 -186
  38. package/nextjs-webpack-config.js +53 -88
  39. package/nextjs-wrapper.js +158 -158
  40. package/nextjs.d.ts +1 -1
  41. package/nextjs.js +135 -190
  42. package/package.json +45 -67
  43. package/postinstall.js +6 -6
  44. package/register.d.ts +1 -1
  45. package/register.js +4 -39
  46. package/tracing.d.ts +1 -2
  47. package/tracing.js +22 -287
  48. package/web-vite.mjs +156 -239
  49. package/CONSUMING-APPS-GUIDE.md +0 -455
  50. package/NPM_README.md +0 -1933
  51. package/SKILL-API.md +0 -600
  52. package/SKILL-CLI.md +0 -409
  53. package/cidr.js +0 -83
  54. package/cli/apps.js +0 -585
  55. package/cli/auth.js +0 -280
  56. package/cli/client.js +0 -115
  57. package/cli/config.js +0 -173
  58. package/cli/firewall.js +0 -100
  59. package/cli/fp.js +0 -638
  60. package/cli/init.js +0 -201
  61. package/cli/monitor.js +0 -440
  62. package/cli/run.js +0 -133
  63. package/cli/security.js +0 -1064
  64. package/cli/ui.js +0 -386
  65. package/docs/API-KEYS-GUIDE.md +0 -233
  66. package/docs/AUTO-SETUP-SUMMARY.md +0 -331
  67. package/docs/BODY-CAPTURE-FIX.md +0 -261
  68. package/docs/COMPLETION-REPORT.md +0 -408
  69. package/docs/FINAL-SOLUTION.md +0 -335
  70. package/docs/FIREWALL-GUIDE.md +0 -426
  71. package/docs/IMPLEMENTATION-SUMMARY.md +0 -410
  72. package/docs/NEXTJS-BODY-CAPTURE-COMPARISON.md +0 -323
  73. package/docs/NEXTJS-SETUP-COMPLETE.md +0 -795
  74. package/docs/NUXT-GUIDE.md +0 -166
  75. package/docs/SOLUTION-SUMMARY.md +0 -312
  76. package/firewall-cloud.js +0 -212
  77. package/firewall-iptables.js +0 -139
  78. package/firewall-only.js +0 -38
  79. package/firewall-tcp.js +0 -74
  80. package/firewall.js +0 -720
  81. package/free-trial-banner.js +0 -174
  82. package/nuxt-server-plugin.mjs +0 -423
  83. package/nuxt.d.ts +0 -60
  84. package/nuxt.mjs +0 -75
  85. package/resolve-ip.js +0 -77
@@ -1,139 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Layer 3: OS-level firewall via iptables/nftables.
5
- * Manages a dedicated SECURENOW_BLOCK chain — never touches customer rules.
6
- * Linux only, requires root or CAP_NET_ADMIN. Falls back gracefully otherwise.
7
- */
8
-
9
- const { execSync } = require('child_process');
10
- const os = require('os');
11
-
12
- const CHAIN_NAME = 'SECURENOW_BLOCK';
13
-
14
- let _options = null;
15
- let _active = false;
16
- let _useNft = false;
17
-
18
- function exec(cmd) {
19
- return execSync(cmd, { stdio: 'pipe', timeout: 10000 }).toString().trim();
20
- }
21
-
22
- function canRun(cmd) {
23
- try { exec(cmd); return true; } catch { return false; }
24
- }
25
-
26
- function detectBackend() {
27
- if (canRun('nft --version')) return 'nft';
28
- if (canRun('iptables --version')) return 'iptables';
29
- return null;
30
- }
31
-
32
- // ────── iptables backend ──────
33
-
34
- function iptablesSetup() {
35
- try { exec(`iptables -N ${CHAIN_NAME}`); } catch (_) {} // chain may already exist
36
- try { exec(`iptables -C INPUT -j ${CHAIN_NAME}`); } catch (_) {
37
- exec(`iptables -I INPUT 1 -j ${CHAIN_NAME}`);
38
- }
39
- }
40
-
41
- function iptablesSync(ips) {
42
- exec(`iptables -F ${CHAIN_NAME}`);
43
- for (const ip of ips) {
44
- exec(`iptables -A ${CHAIN_NAME} -s ${ip} -j DROP`);
45
- }
46
- }
47
-
48
- function iptablesCleanup() {
49
- try { exec(`iptables -D INPUT -j ${CHAIN_NAME}`); } catch (_) {}
50
- try { exec(`iptables -F ${CHAIN_NAME}`); } catch (_) {}
51
- try { exec(`iptables -X ${CHAIN_NAME}`); } catch (_) {}
52
- }
53
-
54
- // ────── nftables backend ──────
55
-
56
- function nftSetup() {
57
- try { exec(`nft list chain ip filter ${CHAIN_NAME}`); } catch (_) {
58
- exec(`nft add chain ip filter ${CHAIN_NAME}`);
59
- }
60
- try { exec(`nft insert rule ip filter INPUT jump ${CHAIN_NAME}`); } catch (_) {}
61
- }
62
-
63
- function nftSync(ips) {
64
- exec(`nft flush chain ip filter ${CHAIN_NAME}`);
65
- for (const ip of ips) {
66
- exec(`nft add rule ip filter ${CHAIN_NAME} ip saddr ${ip} drop`);
67
- }
68
- }
69
-
70
- function nftCleanup() {
71
- try { exec(`nft flush chain ip filter ${CHAIN_NAME}`); } catch (_) {}
72
- try { exec(`nft delete chain ip filter ${CHAIN_NAME}`); } catch (_) {}
73
- }
74
-
75
- // ────── Public API ──────
76
-
77
- let _syncCallback = null;
78
-
79
- function init(options) {
80
- _options = options;
81
-
82
- if (os.platform() !== 'linux') {
83
- if (_options.log) console.warn('[securenow] Firewall iptables: only supported on Linux, skipping');
84
- return;
85
- }
86
-
87
- const backend = detectBackend();
88
- if (!backend) {
89
- if (_options.log) console.warn('[securenow] Firewall iptables: neither iptables nor nft found, skipping');
90
- return;
91
- }
92
-
93
- _useNft = backend === 'nft';
94
- const label = _useNft ? 'nftables' : 'iptables';
95
-
96
- try {
97
- if (_useNft) nftSetup(); else iptablesSetup();
98
- _active = true;
99
- if (_options.log) console.log('[securenow] Firewall iptables: %s chain %s ready', label, CHAIN_NAME);
100
- } catch (e) {
101
- if (_options.log) console.warn('[securenow] Firewall iptables: setup failed (need root or CAP_NET_ADMIN):', e.message);
102
- }
103
- }
104
-
105
- /**
106
- * Called by the firewall core after each successful blocklist sync.
107
- * @param {string[]} ips - Array of IPs and CIDRs to block
108
- */
109
- function sync(ips) {
110
- if (!_active) return;
111
-
112
- const maxRules = (_options && _options.iptablesMax) || 10000;
113
- const limited = ips.length > maxRules ? ips.slice(0, maxRules) : ips;
114
-
115
- if (ips.length > maxRules && _options.log) {
116
- console.warn('[securenow] Firewall iptables: truncated to %d rules (max %d)', maxRules, maxRules);
117
- }
118
-
119
- try {
120
- if (_useNft) nftSync(limited); else iptablesSync(limited);
121
- } catch (e) {
122
- if (_options && _options.log) {
123
- console.warn('[securenow] Firewall iptables: sync failed:', e.message);
124
- }
125
- }
126
- }
127
-
128
- function shutdown() {
129
- if (!_active) return;
130
- try {
131
- if (_useNft) nftCleanup(); else iptablesCleanup();
132
- if (_options && _options.log) console.log('[securenow] Firewall iptables: chain %s cleaned up', CHAIN_NAME);
133
- } catch (e) {
134
- if (_options && _options.log) console.warn('[securenow] Firewall iptables: cleanup failed:', e.message);
135
- }
136
- _active = false;
137
- }
138
-
139
- module.exports = { init, sync, shutdown };
package/firewall-only.js DELETED
@@ -1,38 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Standalone firewall preload — no OpenTelemetry, no tracing.
5
- *
6
- * Usage:
7
- * node -r securenow/firewall-only app.js
8
- * NODE_OPTIONS='-r securenow/firewall-only' next start
9
- *
10
- * Reads .env via dotenv (if installed), then initialises the HTTP-level
11
- * firewall when SECURENOW_API_KEY is present.
12
- */
13
-
14
- try { require('dotenv').config(); } catch (_) {}
15
-
16
- const env = (k) =>
17
- process.env[k] ?? process.env[k.toUpperCase()] ?? process.env[k.toLowerCase()];
18
-
19
- const firewallApiKey = env('SECURENOW_API_KEY');
20
-
21
- if (firewallApiKey && env('SECURENOW_FIREWALL_ENABLED') !== '0') {
22
- require('./firewall').init({
23
- apiKey: firewallApiKey,
24
- apiUrl: env('SECURENOW_API_URL') || 'https://api.securenow.ai',
25
- versionCheckInterval: parseInt(env('SECURENOW_FIREWALL_VERSION_INTERVAL'), 10) || 10,
26
- syncInterval: parseInt(env('SECURENOW_FIREWALL_SYNC_INTERVAL'), 10) || 300,
27
- failMode: env('SECURENOW_FIREWALL_FAIL_MODE') || 'open',
28
- statusCode: parseInt(env('SECURENOW_FIREWALL_STATUS_CODE'), 10) || 403,
29
- log: env('SECURENOW_FIREWALL_LOG') !== '0',
30
- tcp: env('SECURENOW_FIREWALL_TCP') === '1',
31
- iptables: env('SECURENOW_FIREWALL_IPTABLES') === '1',
32
- cloud: env('SECURENOW_FIREWALL_CLOUD') || null,
33
- });
34
-
35
- const shutdown = () => { try { require('./firewall').shutdown(); } catch (_) {} };
36
- process.on('SIGINT', shutdown);
37
- process.on('SIGTERM', shutdown);
38
- }
package/firewall-tcp.js DELETED
@@ -1,74 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Layer 2: TCP-level blocking via net.Server connection event.
5
- * Destroys the socket before HTTP parsing starts. Zero bytes sent back.
6
- *
7
- * Caveat: only sees socket.remoteAddress (direct connection IP).
8
- * If behind a reverse proxy, the proxy IP is seen instead.
9
- * Proxy IPs are skipped (let through to Layer 1 for proper header-based resolution).
10
- */
11
-
12
- const net = require('net');
13
- const { resolveSocketIp, isFromTrustedProxy } = require('./resolve-ip');
14
-
15
- let _getMatcher = null;
16
- let _getAllowlistMatcher = null;
17
- let _options = null;
18
- let _patched = false;
19
- const _origListen = net.Server.prototype.listen;
20
-
21
- function onConnection(socket) {
22
- const ip = resolveSocketIp(socket);
23
-
24
- // Skip if the connection is from a trusted proxy — Layer 1 will handle it
25
- // with proper X-Forwarded-For resolution
26
- if (isFromTrustedProxy(ip) || isFromTrustedProxy('::ffff:' + ip)) return;
27
-
28
- // Allowlist check: if active, only listed IPs pass
29
- const allowlistMatcher = _getAllowlistMatcher ? _getAllowlistMatcher() : null;
30
- if (allowlistMatcher && allowlistMatcher.stats().total > 0) {
31
- if (!allowlistMatcher.isBlocked(ip)) {
32
- if (_options && _options.log) {
33
- console.log('[securenow] Firewall: blocked %s via TCP (not in allowlist)', ip);
34
- }
35
- socket.destroy();
36
- return;
37
- }
38
- return; // on allowlist — allow
39
- }
40
-
41
- // Blocklist check
42
- const matcher = _getMatcher();
43
- if (!matcher) return;
44
-
45
- if (matcher.isBlocked(ip)) {
46
- if (_options && _options.log) {
47
- console.log('[securenow] Firewall: blocked %s via TCP (socket destroyed)', ip);
48
- }
49
- socket.destroy();
50
- }
51
- }
52
-
53
- function init(getMatcher, options, getAllowlistMatcher) {
54
- _getMatcher = getMatcher;
55
- _getAllowlistMatcher = getAllowlistMatcher || null;
56
- _options = options;
57
-
58
- if (_patched) return;
59
- _patched = true;
60
-
61
- net.Server.prototype.listen = function(...args) {
62
- this.on('connection', onConnection);
63
- return _origListen.apply(this, args);
64
- };
65
- }
66
-
67
- function shutdown() {
68
- if (_patched) {
69
- net.Server.prototype.listen = _origListen;
70
- _patched = false;
71
- }
72
- }
73
-
74
- module.exports = { init, shutdown };