securenow 6.0.2 → 7.0.0-anas

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 (88) hide show
  1. package/CONSUMING-APPS-GUIDE.md +455 -0
  2. package/NPM_README.md +2029 -0
  3. package/README.md +297 -40
  4. package/SKILL-API.md +634 -0
  5. package/SKILL-CLI.md +454 -0
  6. package/app-config.js +130 -0
  7. package/cidr.js +83 -0
  8. package/cli/apps.js +608 -0
  9. package/cli/auth.js +298 -0
  10. package/cli/client.js +115 -0
  11. package/cli/config.js +202 -0
  12. package/cli/diagnostics.js +387 -0
  13. package/cli/firewall.js +100 -0
  14. package/cli/fp.js +638 -0
  15. package/cli/init.js +201 -0
  16. package/cli/monitor.js +440 -0
  17. package/cli/run.js +148 -0
  18. package/cli/security.js +980 -0
  19. package/cli/ui.js +386 -0
  20. package/cli/utils.js +127 -0
  21. package/cli.js +469 -455
  22. package/console-instrumentation.js +147 -136
  23. package/docs/ALL-FRAMEWORKS-QUICKSTART.md +1377 -455
  24. package/docs/API-KEYS-GUIDE.md +233 -0
  25. package/docs/ARCHITECTURE.md +3 -3
  26. package/docs/AUTO-BODY-CAPTURE.md +1 -1
  27. package/docs/AUTO-SETUP-SUMMARY.md +331 -0
  28. package/docs/AUTO-SETUP.md +4 -4
  29. package/docs/AUTOMATIC-IP-CAPTURE.md +5 -5
  30. package/docs/BODY-CAPTURE-FIX.md +261 -0
  31. package/docs/BODY-CAPTURE-QUICKSTART.md +2 -2
  32. package/docs/CHANGELOG-NEXTJS.md +1 -35
  33. package/docs/COMPLETION-REPORT.md +408 -0
  34. package/docs/CUSTOMER-GUIDE.md +16 -16
  35. package/docs/EASIEST-SETUP.md +5 -5
  36. package/docs/ENVIRONMENT-VARIABLES.md +880 -652
  37. package/docs/EXPRESS-BODY-CAPTURE.md +13 -12
  38. package/docs/EXPRESS-SETUP-GUIDE.md +719 -720
  39. package/docs/FINAL-SOLUTION.md +335 -0
  40. package/docs/FIREWALL-GUIDE.md +426 -0
  41. package/docs/IMPLEMENTATION-SUMMARY.md +410 -0
  42. package/docs/INDEX.md +22 -4
  43. package/docs/LOGGING-GUIDE.md +701 -708
  44. package/docs/LOGGING-QUICKSTART.md +234 -255
  45. package/docs/NEXTJS-BODY-CAPTURE-COMPARISON.md +323 -0
  46. package/docs/NEXTJS-BODY-CAPTURE.md +2 -2
  47. package/docs/NEXTJS-GUIDE.md +14 -14
  48. package/docs/NEXTJS-QUICKSTART.md +1 -1
  49. package/docs/NEXTJS-SETUP-COMPLETE.md +795 -0
  50. package/docs/NEXTJS-WRAPPER-APPROACH.md +1 -1
  51. package/docs/NUXT-GUIDE.md +166 -0
  52. package/docs/QUICKSTART-BODY-CAPTURE.md +2 -2
  53. package/docs/REDACTION-EXAMPLES.md +1 -1
  54. package/docs/REQUEST-BODY-CAPTURE.md +19 -10
  55. package/docs/SOLUTION-SUMMARY.md +312 -0
  56. package/docs/VERCEL-OTEL-MIGRATION.md +3 -3
  57. package/examples/README.md +6 -6
  58. package/examples/instrumentation-with-auto-capture.ts +1 -1
  59. package/examples/nextjs-env-example.txt +2 -2
  60. package/examples/nextjs-instrumentation.js +1 -1
  61. package/examples/nextjs-instrumentation.ts +1 -1
  62. package/examples/nextjs-with-logging-example.md +6 -6
  63. package/examples/nextjs-with-options.ts +1 -1
  64. package/examples/test-nextjs-setup.js +1 -1
  65. package/firewall-cloud.js +212 -0
  66. package/firewall-iptables.js +139 -0
  67. package/firewall-only.js +38 -0
  68. package/firewall-tcp.js +74 -0
  69. package/firewall.js +720 -0
  70. package/free-trial-banner.js +174 -0
  71. package/nextjs-auto-capture.js +198 -207
  72. package/nextjs-middleware.js +186 -181
  73. package/nextjs-webpack-config.js +88 -53
  74. package/nextjs-wrapper.js +158 -158
  75. package/nextjs.d.ts +1 -1
  76. package/nextjs.js +638 -647
  77. package/nuxt-server-plugin.mjs +425 -0
  78. package/nuxt.d.ts +60 -0
  79. package/nuxt.mjs +75 -0
  80. package/package.json +172 -164
  81. package/postinstall.js +42 -14
  82. package/register.d.ts +1 -1
  83. package/register.js +39 -4
  84. package/resolve-ip.js +77 -0
  85. package/tracing.d.ts +2 -1
  86. package/tracing.js +318 -45
  87. package/web-vite.mjs +239 -156
  88. package/LICENSE +0 -15
package/package.json CHANGED
@@ -1,164 +1,172 @@
1
- {
2
- "name": "securenow",
3
- "version": "6.0.2",
4
- "description": "OpenTelemetry instrumentation for Node.js and Next.js - Send traces and logs to SigNoz or any OTLP backend",
5
- "type": "commonjs",
6
- "main": "register.js",
7
- "types": "register.d.ts",
8
- "bin": {
9
- "securenow": "cli.js"
10
- },
11
- "scripts": {
12
- "postinstall": "node postinstall.js || exit 0"
13
- },
14
- "repository": {
15
- "type": "git",
16
- "url": "git+https://github.com/securenow-ai/securenow-npm.git"
17
- },
18
- "homepage": "https://securenow.ai",
19
- "bugs": {
20
- "url": "https://github.com/securenow-ai/securenow-npm/issues",
21
- "email": "support@securenow.ai"
22
- },
23
- "author": "SecureNow <support@securenow.ai> (https://securenow.ai)",
24
- "keywords": [
25
- "opentelemetry",
26
- "otel",
27
- "tracing",
28
- "logging",
29
- "logs",
30
- "observability",
31
- "apm",
32
- "monitoring",
33
- "nextjs",
34
- "next.js",
35
- "signoz",
36
- "instrumentation",
37
- "telemetry",
38
- "distributed-tracing",
39
- "node",
40
- "express",
41
- "fastify",
42
- "nestjs"
43
- ],
44
- "exports": {
45
- ".": {
46
- "types": "./register.d.ts",
47
- "default": "./register.js"
48
- },
49
- "./register": {
50
- "types": "./register.d.ts",
51
- "default": "./register.js"
52
- },
53
- "./tracing": {
54
- "types": "./tracing.d.ts",
55
- "default": "./tracing.js"
56
- },
57
- "./console-instrumentation": {
58
- "default": "./console-instrumentation.js"
59
- },
60
- "./nextjs": {
61
- "types": "./nextjs.d.ts",
62
- "default": "./nextjs.js"
63
- },
64
- "./nextjs-auto-capture": {
65
- "types": "./nextjs-auto-capture.d.ts",
66
- "default": "./nextjs-auto-capture.js"
67
- },
68
- "./nextjs-middleware": {
69
- "types": "./nextjs-middleware.d.ts",
70
- "default": "./nextjs-middleware.js"
71
- },
72
- "./nextjs-wrapper": {
73
- "types": "./nextjs-wrapper.d.ts",
74
- "default": "./nextjs-wrapper.js"
75
- },
76
- "./nextjs-webpack-config": "./nextjs-webpack-config.js",
77
- "./register-vite": "./register-vite.js",
78
- "./web-vite": {
79
- "import": "./web-vite.mjs",
80
- "default": "./web-vite.mjs"
81
- }
82
- },
83
- "files": [
84
- "register.js",
85
- "register.d.ts",
86
- "tracing.js",
87
- "tracing.d.ts",
88
- "console-instrumentation.js",
89
- "nextjs.js",
90
- "nextjs.d.ts",
91
- "nextjs-auto-capture.js",
92
- "nextjs-auto-capture.d.ts",
93
- "nextjs-middleware.js",
94
- "nextjs-middleware.d.ts",
95
- "nextjs-wrapper.js",
96
- "nextjs-wrapper.d.ts",
97
- "nextjs-webpack-config.js",
98
- "cli.js",
99
- "postinstall.js",
100
- "register-vite.js",
101
- "web-vite.mjs",
102
- "examples/",
103
- "docs/ALL-FRAMEWORKS-QUICKSTART.md",
104
- "docs/ARCHITECTURE.md",
105
- "docs/AUTO-BODY-CAPTURE.md",
106
- "docs/CHANGELOG-NEXTJS.md",
107
- "docs/NEXTJS-WEBPACK-WARNINGS.md",
108
- "docs/AUTO-SETUP.md",
109
- "docs/AUTOMATIC-IP-CAPTURE.md",
110
- "docs/BODY-CAPTURE-QUICKSTART.md",
111
- "docs/CUSTOMER-GUIDE.md",
112
- "docs/EASIEST-SETUP.md",
113
- "docs/ENVIRONMENT-VARIABLES.md",
114
- "docs/EXPRESS-BODY-CAPTURE.md",
115
- "docs/EXPRESS-SETUP-GUIDE.md",
116
- "docs/INDEX.md",
117
- "docs/LOGGING-GUIDE.md",
118
- "docs/LOGGING-QUICKSTART.md",
119
- "docs/NEXTJS-BODY-CAPTURE.md",
120
- "docs/NEXTJS-GUIDE.md",
121
- "docs/NEXTJS-QUICKSTART.md",
122
- "docs/NEXTJS-WRAPPER-APPROACH.md",
123
- "docs/QUICKSTART-BODY-CAPTURE.md",
124
- "docs/REDACTION-EXAMPLES.md",
125
- "docs/REQUEST-BODY-CAPTURE.md",
126
- "docs/VERCEL-OTEL-MIGRATION.md",
127
- "README.md",
128
- "LICENSE"
129
- ],
130
- "dependencies": {
131
- "@opentelemetry/api": "1.7.0",
132
- "@opentelemetry/api-logs": "^0.47.0",
133
- "@opentelemetry/auto-instrumentations-node": "0.47.0",
134
- "@opentelemetry/exporter-logs-otlp-http": "^0.47.0",
135
- "@opentelemetry/exporter-trace-otlp-http": "0.47.0",
136
- "@opentelemetry/instrumentation": "0.47.0",
137
- "@opentelemetry/instrumentation-document-load": "0.47.0",
138
- "@opentelemetry/instrumentation-fetch": "0.47.0",
139
- "@opentelemetry/instrumentation-http": "^0.208.0",
140
- "@opentelemetry/instrumentation-user-interaction": "0.47.0",
141
- "@opentelemetry/instrumentation-xml-http-request": "0.47.0",
142
- "@opentelemetry/resources": "1.20.0",
143
- "@opentelemetry/sdk-logs": "^0.47.0",
144
- "@opentelemetry/sdk-node": "0.47.0",
145
- "@opentelemetry/sdk-trace-web": "1.20.0",
146
- "@opentelemetry/semantic-conventions": "1.20.0",
147
- "@vercel/otel": "^1.14.0",
148
- "dotenv": "^17.2.1",
149
- "uuid": "^9.0.0"
150
- },
151
- "peerDependencies": {
152
- "next": ">=13.0.0"
153
- },
154
- "peerDependenciesMeta": {
155
- "next": {
156
- "optional": true
157
- }
158
- },
159
- "overrides": {
160
- "@opentelemetry/api": "1.7.0"
161
- },
162
- "sideEffects": true,
163
- "license": "ISC"
164
- }
1
+ {
2
+ "name": "securenow",
3
+ "version": "7.0.0-anas",
4
+ "description": "OpenTelemetry instrumentation for Node.js, Next.js, and Nuxt - Send traces and logs to any OTLP-compatible backend",
5
+ "type": "commonjs",
6
+ "main": "register.js",
7
+ "types": "register.d.ts",
8
+ "bin": {
9
+ "securenow": "cli.js"
10
+ },
11
+ "scripts": {
12
+ "postinstall": "node postinstall.js || exit 0"
13
+ },
14
+ "keywords": [
15
+ "opentelemetry",
16
+ "otel",
17
+ "tracing",
18
+ "logging",
19
+ "logs",
20
+ "observability",
21
+ "apm",
22
+ "monitoring",
23
+ "cli",
24
+ "nextjs",
25
+ "next.js",
26
+ "instrumentation",
27
+ "telemetry",
28
+ "distributed-tracing",
29
+ "node",
30
+ "express",
31
+ "fastify",
32
+ "nestjs",
33
+ "nuxt",
34
+ "nuxt3",
35
+ "nitro",
36
+ "vue",
37
+ "firewall",
38
+ "ip-blocking",
39
+ "waf",
40
+ "security"
41
+ ],
42
+ "exports": {
43
+ ".": {
44
+ "types": "./register.d.ts",
45
+ "default": "./register.js"
46
+ },
47
+ "./register": {
48
+ "types": "./register.d.ts",
49
+ "default": "./register.js"
50
+ },
51
+ "./tracing": {
52
+ "types": "./tracing.d.ts",
53
+ "default": "./tracing.js"
54
+ },
55
+ "./console-instrumentation": {
56
+ "default": "./console-instrumentation.js"
57
+ },
58
+ "./nextjs": {
59
+ "types": "./nextjs.d.ts",
60
+ "default": "./nextjs.js"
61
+ },
62
+ "./nextjs-auto-capture": {
63
+ "types": "./nextjs-auto-capture.d.ts",
64
+ "default": "./nextjs-auto-capture.js"
65
+ },
66
+ "./nextjs-middleware": {
67
+ "types": "./nextjs-middleware.d.ts",
68
+ "default": "./nextjs-middleware.js"
69
+ },
70
+ "./nextjs-wrapper": {
71
+ "types": "./nextjs-wrapper.d.ts",
72
+ "default": "./nextjs-wrapper.js"
73
+ },
74
+ "./nextjs-webpack-config": "./nextjs-webpack-config.js",
75
+ "./package.json": "./package.json",
76
+ "./nuxt": {
77
+ "types": "./nuxt.d.ts",
78
+ "import": "./nuxt.mjs",
79
+ "default": "./nuxt.mjs"
80
+ },
81
+ "./firewall": {
82
+ "default": "./firewall.js"
83
+ },
84
+ "./firewall-only": {
85
+ "default": "./firewall-only.js"
86
+ },
87
+ "./cidr": {
88
+ "default": "./cidr.js"
89
+ },
90
+ "./resolve-ip": {
91
+ "default": "./resolve-ip.js"
92
+ },
93
+ "./register-vite": "./register-vite.js",
94
+ "./web-vite": {
95
+ "import": "./web-vite.mjs",
96
+ "default": "./web-vite.mjs"
97
+ },
98
+ "./app-config": {
99
+ "default": "./app-config.js"
100
+ }
101
+ },
102
+ "files": [
103
+ "register.js",
104
+ "register.d.ts",
105
+ "tracing.js",
106
+ "tracing.d.ts",
107
+ "console-instrumentation.js",
108
+ "nextjs.js",
109
+ "nextjs.d.ts",
110
+ "nextjs-auto-capture.js",
111
+ "nextjs-auto-capture.d.ts",
112
+ "nextjs-middleware.js",
113
+ "nextjs-middleware.d.ts",
114
+ "nextjs-wrapper.js",
115
+ "nextjs-wrapper.d.ts",
116
+ "nextjs-webpack-config.js",
117
+ "nuxt.mjs",
118
+ "nuxt.d.ts",
119
+ "nuxt-server-plugin.mjs",
120
+ "cli.js",
121
+ "cli/",
122
+ "free-trial-banner.js",
123
+ "resolve-ip.js",
124
+ "cidr.js",
125
+ "firewall.js",
126
+ "firewall-only.js",
127
+ "firewall-tcp.js",
128
+ "firewall-iptables.js",
129
+ "firewall-cloud.js",
130
+ "postinstall.js",
131
+ "register-vite.js",
132
+ "web-vite.mjs",
133
+ "app-config.js",
134
+ "examples/",
135
+ "docs/",
136
+ "README.md",
137
+ "NPM_README.md",
138
+ "CONSUMING-APPS-GUIDE.md",
139
+ "SKILL-CLI.md",
140
+ "SKILL-API.md"
141
+ ],
142
+ "dependencies": {
143
+ "@opentelemetry/api": "1.7.0",
144
+ "@opentelemetry/api-logs": "0.47.0",
145
+ "@opentelemetry/auto-instrumentations-node": "0.47.0",
146
+ "@opentelemetry/exporter-logs-otlp-http": "0.47.0",
147
+ "@opentelemetry/exporter-trace-otlp-http": "0.47.0",
148
+ "@opentelemetry/instrumentation": "0.47.0",
149
+ "@opentelemetry/instrumentation-document-load": "0.47.0",
150
+ "@opentelemetry/instrumentation-fetch": "0.47.0",
151
+ "@opentelemetry/instrumentation-http": "0.47.0",
152
+ "@opentelemetry/instrumentation-mongodb": "0.46.0",
153
+ "@opentelemetry/instrumentation-user-interaction": "0.47.0",
154
+ "@opentelemetry/instrumentation-xml-http-request": "0.47.0",
155
+ "@opentelemetry/resources": "1.20.0",
156
+ "@opentelemetry/sdk-logs": "0.47.0",
157
+ "@opentelemetry/sdk-node": "0.47.0",
158
+ "@opentelemetry/sdk-trace-web": "1.20.0",
159
+ "@opentelemetry/semantic-conventions": "1.20.0",
160
+ "dotenv": "^17.2.1",
161
+ "uuid": "^9.0.0"
162
+ },
163
+ "optionalDependencies": {
164
+ "@vercel/otel": "^1.14.0"
165
+ },
166
+ "overrides": {
167
+ "@opentelemetry/api": "1.7.0",
168
+ "@opentelemetry/api-logs": "0.47.0"
169
+ },
170
+ "sideEffects": true,
171
+ "license": "ISC"
172
+ }
package/postinstall.js CHANGED
@@ -11,6 +11,35 @@ const fs = require('fs');
11
11
  const path = require('path');
12
12
  const readline = require('readline');
13
13
 
14
+ // Make sure `.securenow/` is in the project's .gitignore so credentials never get committed.
15
+ function ensureGitignore() {
16
+ try {
17
+ // Skip if we're not in an npm install of a user project
18
+ // (e.g., securenow's own CI, or nested install under another node_modules).
19
+ const cwd = process.cwd();
20
+ if (!fs.existsSync(path.join(cwd, 'package.json'))) return;
21
+ if (cwd.includes(`${path.sep}node_modules${path.sep}`)) return;
22
+
23
+ const gitignorePath = path.join(cwd, '.gitignore');
24
+ const entry = '.securenow/';
25
+ const header = '# SecureNow local credentials';
26
+
27
+ if (fs.existsSync(gitignorePath)) {
28
+ const content = fs.readFileSync(gitignorePath, 'utf8');
29
+ const alreadyListed = content.split('\n').some((line) => line.trim() === entry);
30
+ if (!alreadyListed) {
31
+ const prefix = content.endsWith('\n') ? '' : '\n';
32
+ fs.appendFileSync(gitignorePath, `${prefix}\n${header}\n${entry}\n`);
33
+ }
34
+ } else if (fs.existsSync(path.join(cwd, '.git'))) {
35
+ // Only create a new .gitignore if this is actually a git repo.
36
+ fs.writeFileSync(gitignorePath, `${header}\n${entry}\n`);
37
+ }
38
+ } catch {
39
+ // Non-fatal
40
+ }
41
+ }
42
+
14
43
  // Check if we're in a Next.js project
15
44
  function isNextJsProject() {
16
45
  try {
@@ -53,7 +82,7 @@ export function register() {
53
82
  * SECURENOW_APPID=my-nextjs-app
54
83
  *
55
84
  * Optional:
56
- * SECURENOW_INSTANCE=http://your-signoz-server:4318
85
+ * SECURENOW_INSTANCE=http://your-otlp-backend:4318
57
86
  * OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-key"
58
87
  * OTEL_LOG_LEVEL=info
59
88
  */
@@ -77,13 +106,12 @@ export function register() {
77
106
  * SECURENOW_APPID=my-nextjs-app
78
107
  *
79
108
  * Optional:
80
- * SECURENOW_INSTANCE=http://your-signoz-server:4318
109
+ * SECURENOW_INSTANCE=http://your-otlp-backend:4318
81
110
  * OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-key"
82
111
  * OTEL_LOG_LEVEL=info
83
112
  *
84
- * Optional: Enable request body capture
85
- * SECURENOW_CAPTURE_BODY=1
86
- * (Also create middleware.ts to activate - run: npx securenow init)
113
+ * Optional: Disable request body capture (enabled by default)
114
+ * SECURENOW_CAPTURE_BODY=0
87
115
  */
88
116
  `;
89
117
 
@@ -150,9 +178,9 @@ function createEnvTemplate(targetPath) {
150
178
  # Required: Your application identifier
151
179
  SECURENOW_APPID=my-nextjs-app
152
180
 
153
- # Optional: Your SigNoz/OpenTelemetry collector endpoint
181
+ # Optional: Your OTLP-compatible backend / collector endpoint
154
182
  # Default: https://freetrial.securenow.ai:4318
155
- SECURENOW_INSTANCE=http://your-signoz-server:4318
183
+ SECURENOW_INSTANCE=http://your-otlp-backend:4318
156
184
 
157
185
  # Optional: API key or authentication headers
158
186
  # OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-api-key-here"
@@ -160,8 +188,8 @@ SECURENOW_INSTANCE=http://your-signoz-server:4318
160
188
  # Optional: Log level (debug|info|warn|error)
161
189
  # OTEL_LOG_LEVEL=info
162
190
 
163
- # Optional: Enable request body capture (requires middleware.ts)
164
- # SECURENOW_CAPTURE_BODY=1
191
+ # Optional: Disable request body capture (enabled by default)
192
+ # SECURENOW_CAPTURE_BODY=0
165
193
  # SECURENOW_MAX_BODY_SIZE=10240
166
194
  # SECURENOW_SENSITIVE_FIELDS=email,phone
167
195
  `;
@@ -176,6 +204,9 @@ function isTypeScriptProject() {
176
204
 
177
205
  // Main setup function
178
206
  async function setup() {
207
+ // Always make sure .securenow/ is gitignored (cheap, non-destructive).
208
+ ensureGitignore();
209
+
179
210
  // Skip if not in Next.js project
180
211
  if (!isNextJsProject()) {
181
212
  console.log('[securenow] Not a Next.js project, skipping auto-setup');
@@ -270,14 +301,11 @@ async function setup() {
270
301
  console.log('│ │');
271
302
  console.log('│ 1. Edit .env.local and set: │');
272
303
  console.log('│ SECURENOW_APPID=your-app-name │');
273
- console.log('│ SECURENOW_INSTANCE=http://signoz:4318 │');
274
- if (shouldCreateMiddleware) {
275
- console.log('│ SECURENOW_CAPTURE_BODY=1 │');
276
- }
304
+ console.log('│ SECURENOW_INSTANCE=http://your-otlp-backend:4318 │');
277
305
  console.log('│ │');
278
306
  console.log('│ 2. Run your app: npm run dev │');
279
307
  console.log('│ │');
280
- console.log('│ 3. Check SigNoz for traces! │');
308
+ console.log('│ 3. Check SecureNow for traces! │');
281
309
  console.log('│ │');
282
310
  if (shouldCreateMiddleware) {
283
311
  console.log('│ 📝 Body capture enabled with auto-redaction │');
package/register.d.ts CHANGED
@@ -56,7 +56,7 @@ export {};
56
56
  * node_args: '-r securenow/register',
57
57
  * env: {
58
58
  * SECURENOW_APPID: 'my-app',
59
- * SECURENOW_INSTANCE: 'http://signoz:4318',
59
+ * SECURENOW_INSTANCE: 'http://your-otlp-backend:4318',
60
60
  * SECURENOW_CAPTURE_BODY: '1',
61
61
  * }
62
62
  * }]
package/register.js CHANGED
@@ -1,14 +1,49 @@
1
- // securenow/preload.js
1
+ // securenow/register.js — the only preload customers need:
2
+ // node --require securenow/register app.js
3
+ //
4
+ // For ESM apps ("type": "module"), this file auto-registers the
5
+ // OpenTelemetry ESM loader hook via module.register() (Node >=20.6).
6
+ // On older Node versions it falls back to a warning.
2
7
  'use strict';
3
8
 
4
- // load .env into process.env before anything else
9
+ // 1. load .env before anything else
5
10
  try {
6
11
  require('dotenv').config();
7
12
  console.log('[securenow] dotenv loaded from', process.env.DOTENV_CONFIG_PATH || '.env');
8
13
  } catch (e) {
9
- // dotenv is optional — only warn if it’s missing
10
14
  console.warn('[securenow] dotenv not found or failed to load');
11
15
  }
12
16
 
13
- // then run the real tracer preload
17
+ // 2. Auto-register the ESM loader hook so customers never need --import
18
+ (() => {
19
+ try {
20
+ const fs = require('fs');
21
+ const path = require('path');
22
+ const pkgPath = path.resolve(process.cwd(), 'package.json');
23
+ if (!fs.existsSync(pkgPath)) return;
24
+
25
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
26
+ if (pkg.type !== 'module') return;
27
+
28
+ // Already registered via --import?
29
+ const execArgv = process.execArgv.join(' ');
30
+ if (execArgv.includes('hook.mjs') || execArgv.includes('import-in-the-middle')) return;
31
+
32
+ // Node >=20.6 exposes module.register() for programmatic ESM hooks
33
+ const mod = require('node:module');
34
+ if (typeof mod.register !== 'function') {
35
+ console.warn('[securenow] ESM app detected but Node %s lacks module.register().', process.version);
36
+ console.warn('[securenow] Upgrade to Node >=20.6 or add: --import @opentelemetry/instrumentation/hook.mjs');
37
+ return;
38
+ }
39
+
40
+ const { pathToFileURL } = require('node:url');
41
+ mod.register('@opentelemetry/instrumentation/hook.mjs', pathToFileURL(__filename));
42
+ console.log('[securenow] ESM loader hook auto-registered (module.register)');
43
+ } catch (_) {
44
+ // Non-fatal — tracing.js will show its own ESM warning if the hook is missing
45
+ }
46
+ })();
47
+
48
+ // 3. Run the OTel SDK setup
14
49
  require('./tracing');
package/resolve-ip.js ADDED
@@ -0,0 +1,77 @@
1
+ 'use strict';
2
+
3
+ const os = require('os');
4
+
5
+ const LOOPBACK_RE = /^(127\.|::1$|::ffff:127\.)/;
6
+ const PRIVATE_IP_RE = /^(127\.|::1$|::ffff:127\.|10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.|f[cd][0-9a-f]{2}:)/;
7
+
8
+ const trustedProxyCsv = (process.env.SECURENOW_TRUSTED_PROXIES || '').trim();
9
+ const trustedProxySet = trustedProxyCsv
10
+ ? new Set(trustedProxyCsv.split(',').map(s => s.trim()).filter(Boolean))
11
+ : null;
12
+
13
+ let _hostIp = null;
14
+ function getHostIp() {
15
+ if (_hostIp !== null) return _hostIp;
16
+ try {
17
+ const ifaces = os.networkInterfaces();
18
+ for (const name of Object.keys(ifaces)) {
19
+ for (const iface of ifaces[name]) {
20
+ if (!iface.internal && iface.family === 'IPv4') { _hostIp = iface.address; return _hostIp; }
21
+ }
22
+ }
23
+ } catch (_) {}
24
+ _hostIp = '';
25
+ return _hostIp;
26
+ }
27
+
28
+ function isFromTrustedProxy(socketIp) {
29
+ if (!socketIp) return false;
30
+ const normalized = socketIp.replace(/^::ffff:/, '');
31
+ if (trustedProxySet && trustedProxySet.has(normalized)) return true;
32
+ return PRIVATE_IP_RE.test(socketIp);
33
+ }
34
+
35
+ /**
36
+ * Resolve the real client IP from an HTTP request, respecting trusted proxies.
37
+ * Reads X-Forwarded-For / X-Real-IP only when the direct connection comes
38
+ * from a private/trusted proxy IP. Prevents client-side IP spoofing.
39
+ */
40
+ function resolveClientIp(request) {
41
+ const socketIp = request.socket?.remoteAddress || '';
42
+ if (!isFromTrustedProxy(socketIp)) return socketIp;
43
+
44
+ const fwd = request.headers['x-forwarded-for'];
45
+ if (fwd) {
46
+ const chain = String(fwd).split(',').map(s => s.trim()).filter(Boolean);
47
+ for (let i = chain.length - 1; i >= 0; i--) {
48
+ if (!isFromTrustedProxy(chain[i])) return chain[i];
49
+ }
50
+ return socketIp;
51
+ }
52
+ const headerIp = request.headers['x-real-ip'];
53
+ if (headerIp) return headerIp;
54
+
55
+ if (LOOPBACK_RE.test(socketIp)) {
56
+ const hostIp = getHostIp();
57
+ if (hostIp) return hostIp;
58
+ }
59
+ return socketIp;
60
+ }
61
+
62
+ /**
63
+ * Resolve IP from a raw TCP socket (no HTTP headers available).
64
+ * Normalizes IPv6-mapped IPv4 addresses.
65
+ */
66
+ function resolveSocketIp(socket) {
67
+ const raw = socket?.remoteAddress || '';
68
+ return raw.replace(/^::ffff:/, '');
69
+ }
70
+
71
+ module.exports = {
72
+ resolveClientIp,
73
+ resolveSocketIp,
74
+ isFromTrustedProxy,
75
+ LOOPBACK_RE,
76
+ PRIVATE_IP_RE,
77
+ };
package/tracing.d.ts CHANGED
@@ -112,7 +112,7 @@ export interface LoggerProvider {
112
112
  }
113
113
 
114
114
  /**
115
- * Get a logger instance for sending structured logs to SigNoz
115
+ * Get a logger instance for sending structured logs to any OTLP-compatible backend
116
116
  *
117
117
  * @param name - Logger name (e.g., 'my-service', 'auth-module')
118
118
  * @param version - Logger version (optional, defaults to '1.0.0')
@@ -178,5 +178,6 @@ export const loggerProvider: LoggerProvider | null;
178
178
  * - SECURENOW_DISABLE_INSTRUMENTATIONS=pkg1,pkg2
179
179
  * - OTEL_LOG_LEVEL=info|debug
180
180
  * - SECURENOW_TEST_SPAN=1
181
+ * - SECURENOW_TRUSTED_PROXIES=ip1,ip2 # Additional trusted proxy IPs for X-Forwarded-For
181
182
  * - OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=... # Override logs endpoint
182
183
  */