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/package.json
CHANGED
|
@@ -1,164 +1,186 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "securenow",
|
|
3
|
-
"version": "6.0
|
|
4
|
-
"description": "OpenTelemetry instrumentation for Node.js
|
|
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
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"./
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
"
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"register
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
"
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"
|
|
126
|
-
"
|
|
127
|
-
"
|
|
128
|
-
"
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
"@opentelemetry/
|
|
140
|
-
"@opentelemetry/
|
|
141
|
-
"@opentelemetry/
|
|
142
|
-
"@opentelemetry/
|
|
143
|
-
"@opentelemetry/
|
|
144
|
-
"@opentelemetry/
|
|
145
|
-
"@opentelemetry/
|
|
146
|
-
"@opentelemetry/
|
|
147
|
-
"@
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
"
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
"
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "securenow",
|
|
3
|
+
"version": "6.1.0",
|
|
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
|
+
},
|
|
99
|
+
"files": [
|
|
100
|
+
"register.js",
|
|
101
|
+
"register.d.ts",
|
|
102
|
+
"tracing.js",
|
|
103
|
+
"tracing.d.ts",
|
|
104
|
+
"console-instrumentation.js",
|
|
105
|
+
"nextjs.js",
|
|
106
|
+
"nextjs.d.ts",
|
|
107
|
+
"nextjs-auto-capture.js",
|
|
108
|
+
"nextjs-auto-capture.d.ts",
|
|
109
|
+
"nextjs-middleware.js",
|
|
110
|
+
"nextjs-middleware.d.ts",
|
|
111
|
+
"nextjs-wrapper.js",
|
|
112
|
+
"nextjs-wrapper.d.ts",
|
|
113
|
+
"nextjs-webpack-config.js",
|
|
114
|
+
"nuxt.mjs",
|
|
115
|
+
"nuxt.d.ts",
|
|
116
|
+
"nuxt-server-plugin.mjs",
|
|
117
|
+
"cli.js",
|
|
118
|
+
"cli/",
|
|
119
|
+
"free-trial-banner.js",
|
|
120
|
+
"resolve-ip.js",
|
|
121
|
+
"cidr.js",
|
|
122
|
+
"firewall.js",
|
|
123
|
+
"firewall-only.js",
|
|
124
|
+
"firewall-tcp.js",
|
|
125
|
+
"firewall-iptables.js",
|
|
126
|
+
"firewall-cloud.js",
|
|
127
|
+
"postinstall.js",
|
|
128
|
+
"register-vite.js",
|
|
129
|
+
"web-vite.mjs",
|
|
130
|
+
"examples/",
|
|
131
|
+
"docs/",
|
|
132
|
+
"README.md",
|
|
133
|
+
"NPM_README.md",
|
|
134
|
+
"CONSUMING-APPS-GUIDE.md",
|
|
135
|
+
"SKILL-CLI.md",
|
|
136
|
+
"SKILL-API.md"
|
|
137
|
+
],
|
|
138
|
+
"dependencies": {
|
|
139
|
+
"@opentelemetry/api": "1.7.0",
|
|
140
|
+
"@opentelemetry/api-logs": "0.47.0",
|
|
141
|
+
"@opentelemetry/auto-instrumentations-node": "0.47.0",
|
|
142
|
+
"@opentelemetry/exporter-logs-otlp-http": "0.47.0",
|
|
143
|
+
"@opentelemetry/exporter-trace-otlp-http": "0.47.0",
|
|
144
|
+
"@opentelemetry/instrumentation": "0.47.0",
|
|
145
|
+
"@opentelemetry/instrumentation-document-load": "0.47.0",
|
|
146
|
+
"@opentelemetry/instrumentation-fetch": "0.47.0",
|
|
147
|
+
"@opentelemetry/instrumentation-http": "0.47.0",
|
|
148
|
+
"@opentelemetry/instrumentation-mongodb": "0.46.0",
|
|
149
|
+
"@opentelemetry/instrumentation-user-interaction": "0.47.0",
|
|
150
|
+
"@opentelemetry/instrumentation-xml-http-request": "0.47.0",
|
|
151
|
+
"@opentelemetry/resources": "1.20.0",
|
|
152
|
+
"@opentelemetry/sdk-logs": "0.47.0",
|
|
153
|
+
"@opentelemetry/sdk-node": "0.47.0",
|
|
154
|
+
"@opentelemetry/sdk-trace-web": "1.20.0",
|
|
155
|
+
"@opentelemetry/semantic-conventions": "1.20.0",
|
|
156
|
+
"@vercel/otel": "^1.14.0",
|
|
157
|
+
"dotenv": "^17.2.1",
|
|
158
|
+
"uuid": "^9.0.0"
|
|
159
|
+
},
|
|
160
|
+
"peerDependencies": {
|
|
161
|
+
"next": ">=13.0.0",
|
|
162
|
+
"nuxt": ">=3.0.0",
|
|
163
|
+
"@aws-sdk/client-wafv2": ">=3.0.0",
|
|
164
|
+
"@google-cloud/compute": ">=4.0.0"
|
|
165
|
+
},
|
|
166
|
+
"peerDependenciesMeta": {
|
|
167
|
+
"next": {
|
|
168
|
+
"optional": true
|
|
169
|
+
},
|
|
170
|
+
"nuxt": {
|
|
171
|
+
"optional": true
|
|
172
|
+
},
|
|
173
|
+
"@aws-sdk/client-wafv2": {
|
|
174
|
+
"optional": true
|
|
175
|
+
},
|
|
176
|
+
"@google-cloud/compute": {
|
|
177
|
+
"optional": true
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
"overrides": {
|
|
181
|
+
"@opentelemetry/api": "1.7.0",
|
|
182
|
+
"@opentelemetry/api-logs": "0.47.0"
|
|
183
|
+
},
|
|
184
|
+
"sideEffects": true,
|
|
185
|
+
"license": "ISC"
|
|
186
|
+
}
|
package/postinstall.js
CHANGED
|
@@ -53,7 +53,7 @@ export function register() {
|
|
|
53
53
|
* SECURENOW_APPID=my-nextjs-app
|
|
54
54
|
*
|
|
55
55
|
* Optional:
|
|
56
|
-
* SECURENOW_INSTANCE=http://your-
|
|
56
|
+
* SECURENOW_INSTANCE=http://your-otlp-backend:4318
|
|
57
57
|
* OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-key"
|
|
58
58
|
* OTEL_LOG_LEVEL=info
|
|
59
59
|
*/
|
|
@@ -77,7 +77,7 @@ export function register() {
|
|
|
77
77
|
* SECURENOW_APPID=my-nextjs-app
|
|
78
78
|
*
|
|
79
79
|
* Optional:
|
|
80
|
-
* SECURENOW_INSTANCE=http://your-
|
|
80
|
+
* SECURENOW_INSTANCE=http://your-otlp-backend:4318
|
|
81
81
|
* OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-key"
|
|
82
82
|
* OTEL_LOG_LEVEL=info
|
|
83
83
|
*
|
|
@@ -150,9 +150,9 @@ function createEnvTemplate(targetPath) {
|
|
|
150
150
|
# Required: Your application identifier
|
|
151
151
|
SECURENOW_APPID=my-nextjs-app
|
|
152
152
|
|
|
153
|
-
# Optional: Your
|
|
153
|
+
# Optional: Your OTLP-compatible backend / collector endpoint
|
|
154
154
|
# Default: https://freetrial.securenow.ai:4318
|
|
155
|
-
SECURENOW_INSTANCE=http://your-
|
|
155
|
+
SECURENOW_INSTANCE=http://your-otlp-backend:4318
|
|
156
156
|
|
|
157
157
|
# Optional: API key or authentication headers
|
|
158
158
|
# OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-api-key-here"
|
|
@@ -270,14 +270,14 @@ async function setup() {
|
|
|
270
270
|
console.log('│ │');
|
|
271
271
|
console.log('│ 1. Edit .env.local and set: │');
|
|
272
272
|
console.log('│ SECURENOW_APPID=your-app-name │');
|
|
273
|
-
console.log('│ SECURENOW_INSTANCE=http://
|
|
273
|
+
console.log('│ SECURENOW_INSTANCE=http://your-otlp-backend:4318 │');
|
|
274
274
|
if (shouldCreateMiddleware) {
|
|
275
275
|
console.log('│ SECURENOW_CAPTURE_BODY=1 │');
|
|
276
276
|
}
|
|
277
277
|
console.log('│ │');
|
|
278
278
|
console.log('│ 2. Run your app: npm run dev │');
|
|
279
279
|
console.log('│ │');
|
|
280
|
-
console.log('│ 3. Check
|
|
280
|
+
console.log('│ 3. Check SecureNow for traces! │');
|
|
281
281
|
console.log('│ │');
|
|
282
282
|
if (shouldCreateMiddleware) {
|
|
283
283
|
console.log('│ 📝 Body capture enabled with auto-redaction │');
|
package/register.d.ts
CHANGED
package/register.js
CHANGED
|
@@ -1,14 +1,49 @@
|
|
|
1
|
-
// securenow/
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
|
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
|
*/
|