muaddib-scanner 2.4.4 → 2.4.5

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.
@@ -1,223 +1,223 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const yaml = require('js-yaml');
4
-
5
- const IOCS_DIR = path.join(__dirname, '../../iocs');
6
-
7
- function loadYAMLIOCs() {
8
- const iocs = {
9
- packages: [],
10
- hashes: [],
11
- markers: [],
12
- files: []
13
- };
14
-
15
- // Dedup sets for O(1) lookup during loading
16
- const seenPkgs = new Set();
17
- const seenHashes = new Set();
18
- const seenMarkers = new Set();
19
- const seenFiles = new Set();
20
-
21
- // Charger packages.yaml
22
- loadPackagesYAML(path.join(IOCS_DIR, 'packages.yaml'), iocs, seenPkgs);
23
-
24
- // Charger builtin.yaml (fallback)
25
- loadBuiltinYAML(path.join(IOCS_DIR, 'builtin.yaml'), iocs, seenPkgs, seenHashes, seenMarkers, seenFiles);
26
-
27
- // Charger hashes.yaml
28
- loadHashesYAML(path.join(IOCS_DIR, 'hashes.yaml'), iocs, seenHashes, seenMarkers, seenFiles);
29
-
30
- return iocs;
31
- }
32
-
33
- function loadPackagesYAML(filePath, iocs, seenPkgs) {
34
- if (!fs.existsSync(filePath)) return;
35
-
36
- try {
37
- const data = yaml.load(fs.readFileSync(filePath, 'utf8'), { schema: yaml.JSON_SCHEMA });
38
- if (data && data.packages) {
39
- for (const p of data.packages) {
40
- if (!p.name || typeof p.name !== 'string') continue;
41
- const key = p.name + '@' + p.version;
42
- if (!seenPkgs.has(key)) {
43
- seenPkgs.add(key);
44
- iocs.packages.push({
45
- id: p.id,
46
- name: p.name,
47
- version: p.version,
48
- severity: p.severity || 'critical',
49
- confidence: p.confidence || 'high',
50
- source: p.source,
51
- description: p.description,
52
- references: p.references || [],
53
- mitre: p.mitre || 'T1195.002'
54
- });
55
- }
56
- }
57
- }
58
- } catch (e) {
59
- console.error('[WARN] Erreur parsing packages.yaml:', e.message);
60
- }
61
- }
62
-
63
- function loadBuiltinYAML(filePath, iocs, seenPkgs, seenHashes, seenMarkers, seenFiles) {
64
- if (!fs.existsSync(filePath)) return;
65
-
66
- try {
67
- const data = yaml.load(fs.readFileSync(filePath, 'utf8'), { schema: yaml.JSON_SCHEMA });
68
-
69
- // Packages
70
- if (data && data.packages) {
71
- for (const p of data.packages) {
72
- if (!p.name || typeof p.name !== 'string') continue;
73
- const key = p.name + '@' + p.version;
74
- if (!seenPkgs.has(key)) {
75
- seenPkgs.add(key);
76
- iocs.packages.push({
77
- id: `BUILTIN-${p.name}`,
78
- name: p.name,
79
- version: p.version,
80
- severity: p.severity || 'critical',
81
- confidence: p.confidence || 'high',
82
- source: p.source,
83
- description: p.description || `Malicious package: ${p.name}`,
84
- references: p.references || [],
85
- mitre: p.mitre || 'T1195.002'
86
- });
87
- }
88
- }
89
- }
90
-
91
- // Files
92
- if (data && data.files) {
93
- for (const f of data.files) {
94
- const fileName = typeof f === 'string' ? f : f.name;
95
- if (!seenFiles.has(fileName)) {
96
- seenFiles.add(fileName);
97
- iocs.files.push({
98
- id: `BUILTIN-FILE-${fileName}`,
99
- name: fileName,
100
- severity: 'critical',
101
- confidence: 'high',
102
- source: 'builtin',
103
- description: `Suspicious file: ${fileName}`
104
- });
105
- }
106
- }
107
- }
108
-
109
- // Hashes
110
- if (data && data.hashes) {
111
- for (const h of data.hashes) {
112
- const hash = typeof h === 'string' ? h : h.sha256;
113
- if (!seenHashes.has(hash)) {
114
- seenHashes.add(hash);
115
- iocs.hashes.push({
116
- id: `BUILTIN-HASH-${hash.slice(0, 12)}`,
117
- sha256: hash,
118
- severity: 'critical',
119
- confidence: 'high',
120
- source: 'builtin',
121
- description: 'Known malicious hash'
122
- });
123
- }
124
- }
125
- }
126
-
127
- // Markers
128
- if (data && data.markers) {
129
- for (const m of data.markers) {
130
- const pattern = typeof m === 'string' ? m : m.pattern;
131
- if (!seenMarkers.has(pattern)) {
132
- seenMarkers.add(pattern);
133
- iocs.markers.push({
134
- id: `BUILTIN-MARKER-${pattern.slice(0, 10)}`,
135
- pattern: pattern,
136
- severity: 'critical',
137
- confidence: 'high',
138
- source: 'builtin',
139
- description: `Malware marker: ${pattern}`
140
- });
141
- }
142
- }
143
- }
144
- } catch (e) {
145
- console.error('[WARN] Erreur parsing builtin.yaml:', e.message);
146
- }
147
- }
148
-
149
- function loadHashesYAML(filePath, iocs, seenHashes, seenMarkers, seenFiles) {
150
- if (!fs.existsSync(filePath)) return;
151
-
152
- try {
153
- const data = yaml.load(fs.readFileSync(filePath, 'utf8'), { schema: yaml.JSON_SCHEMA });
154
-
155
- if (data && data.hashes) {
156
- for (const h of data.hashes) {
157
- if (!seenHashes.has(h.sha256)) {
158
- seenHashes.add(h.sha256);
159
- iocs.hashes.push({
160
- id: h.id,
161
- sha256: h.sha256,
162
- file: h.file,
163
- severity: h.severity || 'critical',
164
- confidence: h.confidence || 'high',
165
- source: h.source,
166
- description: h.description,
167
- references: h.references || []
168
- });
169
- }
170
- }
171
- }
172
-
173
- if (data && data.markers) {
174
- for (const m of data.markers) {
175
- if (!seenMarkers.has(m.pattern)) {
176
- seenMarkers.add(m.pattern);
177
- iocs.markers.push({
178
- id: m.id,
179
- pattern: m.pattern,
180
- severity: m.severity || 'critical',
181
- confidence: m.confidence || 'high',
182
- source: m.source,
183
- description: m.description
184
- });
185
- }
186
- }
187
- }
188
-
189
- if (data && data.files) {
190
- for (const f of data.files) {
191
- if (!seenFiles.has(f.name)) {
192
- seenFiles.add(f.name);
193
- iocs.files.push({
194
- id: f.id,
195
- name: f.name,
196
- severity: f.severity || 'critical',
197
- confidence: f.confidence || 'high',
198
- source: f.source,
199
- description: f.description
200
- });
201
- }
202
- }
203
- }
204
- } catch (e) {
205
- console.error('[WARN] Erreur parsing hashes.yaml:', e.message);
206
- }
207
- }
208
-
209
- let _cachedIOCStats = null;
210
-
211
- function getIOCStats() {
212
- if (_cachedIOCStats) return _cachedIOCStats;
213
- const iocs = loadYAMLIOCs();
214
- _cachedIOCStats = {
215
- packages: iocs.packages.length,
216
- hashes: iocs.hashes.length,
217
- markers: iocs.markers.length,
218
- files: iocs.files.length
219
- };
220
- return _cachedIOCStats;
221
- }
222
-
223
- module.exports = { loadYAMLIOCs, getIOCStats };
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const yaml = require('js-yaml');
4
+
5
+ const IOCS_DIR = path.join(__dirname, '../../iocs');
6
+
7
+ function loadYAMLIOCs() {
8
+ const iocs = {
9
+ packages: [],
10
+ hashes: [],
11
+ markers: [],
12
+ files: []
13
+ };
14
+
15
+ // Dedup sets for O(1) lookup during loading
16
+ const seenPkgs = new Set();
17
+ const seenHashes = new Set();
18
+ const seenMarkers = new Set();
19
+ const seenFiles = new Set();
20
+
21
+ // Charger packages.yaml
22
+ loadPackagesYAML(path.join(IOCS_DIR, 'packages.yaml'), iocs, seenPkgs);
23
+
24
+ // Charger builtin.yaml (fallback)
25
+ loadBuiltinYAML(path.join(IOCS_DIR, 'builtin.yaml'), iocs, seenPkgs, seenHashes, seenMarkers, seenFiles);
26
+
27
+ // Charger hashes.yaml
28
+ loadHashesYAML(path.join(IOCS_DIR, 'hashes.yaml'), iocs, seenHashes, seenMarkers, seenFiles);
29
+
30
+ return iocs;
31
+ }
32
+
33
+ function loadPackagesYAML(filePath, iocs, seenPkgs) {
34
+ if (!fs.existsSync(filePath)) return;
35
+
36
+ try {
37
+ const data = yaml.load(fs.readFileSync(filePath, 'utf8'), { schema: yaml.JSON_SCHEMA });
38
+ if (data && data.packages) {
39
+ for (const p of data.packages) {
40
+ if (!p.name || typeof p.name !== 'string') continue;
41
+ const key = p.name + '@' + p.version;
42
+ if (!seenPkgs.has(key)) {
43
+ seenPkgs.add(key);
44
+ iocs.packages.push({
45
+ id: p.id,
46
+ name: p.name,
47
+ version: p.version,
48
+ severity: p.severity || 'critical',
49
+ confidence: p.confidence || 'high',
50
+ source: p.source,
51
+ description: p.description,
52
+ references: p.references || [],
53
+ mitre: p.mitre || 'T1195.002'
54
+ });
55
+ }
56
+ }
57
+ }
58
+ } catch (e) {
59
+ console.error('[WARN] Erreur parsing packages.yaml:', e.message);
60
+ }
61
+ }
62
+
63
+ function loadBuiltinYAML(filePath, iocs, seenPkgs, seenHashes, seenMarkers, seenFiles) {
64
+ if (!fs.existsSync(filePath)) return;
65
+
66
+ try {
67
+ const data = yaml.load(fs.readFileSync(filePath, 'utf8'), { schema: yaml.JSON_SCHEMA });
68
+
69
+ // Packages
70
+ if (data && data.packages) {
71
+ for (const p of data.packages) {
72
+ if (!p.name || typeof p.name !== 'string') continue;
73
+ const key = p.name + '@' + p.version;
74
+ if (!seenPkgs.has(key)) {
75
+ seenPkgs.add(key);
76
+ iocs.packages.push({
77
+ id: `BUILTIN-${p.name}`,
78
+ name: p.name,
79
+ version: p.version,
80
+ severity: p.severity || 'critical',
81
+ confidence: p.confidence || 'high',
82
+ source: p.source,
83
+ description: p.description || `Malicious package: ${p.name}`,
84
+ references: p.references || [],
85
+ mitre: p.mitre || 'T1195.002'
86
+ });
87
+ }
88
+ }
89
+ }
90
+
91
+ // Files
92
+ if (data && data.files) {
93
+ for (const f of data.files) {
94
+ const fileName = typeof f === 'string' ? f : f.name;
95
+ if (!seenFiles.has(fileName)) {
96
+ seenFiles.add(fileName);
97
+ iocs.files.push({
98
+ id: `BUILTIN-FILE-${fileName}`,
99
+ name: fileName,
100
+ severity: 'critical',
101
+ confidence: 'high',
102
+ source: 'builtin',
103
+ description: `Suspicious file: ${fileName}`
104
+ });
105
+ }
106
+ }
107
+ }
108
+
109
+ // Hashes
110
+ if (data && data.hashes) {
111
+ for (const h of data.hashes) {
112
+ const hash = typeof h === 'string' ? h : h.sha256;
113
+ if (!seenHashes.has(hash)) {
114
+ seenHashes.add(hash);
115
+ iocs.hashes.push({
116
+ id: `BUILTIN-HASH-${hash.slice(0, 12)}`,
117
+ sha256: hash,
118
+ severity: 'critical',
119
+ confidence: 'high',
120
+ source: 'builtin',
121
+ description: 'Known malicious hash'
122
+ });
123
+ }
124
+ }
125
+ }
126
+
127
+ // Markers
128
+ if (data && data.markers) {
129
+ for (const m of data.markers) {
130
+ const pattern = typeof m === 'string' ? m : m.pattern;
131
+ if (!seenMarkers.has(pattern)) {
132
+ seenMarkers.add(pattern);
133
+ iocs.markers.push({
134
+ id: `BUILTIN-MARKER-${pattern.slice(0, 10)}`,
135
+ pattern: pattern,
136
+ severity: 'critical',
137
+ confidence: 'high',
138
+ source: 'builtin',
139
+ description: `Malware marker: ${pattern}`
140
+ });
141
+ }
142
+ }
143
+ }
144
+ } catch (e) {
145
+ console.error('[WARN] Erreur parsing builtin.yaml:', e.message);
146
+ }
147
+ }
148
+
149
+ function loadHashesYAML(filePath, iocs, seenHashes, seenMarkers, seenFiles) {
150
+ if (!fs.existsSync(filePath)) return;
151
+
152
+ try {
153
+ const data = yaml.load(fs.readFileSync(filePath, 'utf8'), { schema: yaml.JSON_SCHEMA });
154
+
155
+ if (data && data.hashes) {
156
+ for (const h of data.hashes) {
157
+ if (!seenHashes.has(h.sha256)) {
158
+ seenHashes.add(h.sha256);
159
+ iocs.hashes.push({
160
+ id: h.id,
161
+ sha256: h.sha256,
162
+ file: h.file,
163
+ severity: h.severity || 'critical',
164
+ confidence: h.confidence || 'high',
165
+ source: h.source,
166
+ description: h.description,
167
+ references: h.references || []
168
+ });
169
+ }
170
+ }
171
+ }
172
+
173
+ if (data && data.markers) {
174
+ for (const m of data.markers) {
175
+ if (!seenMarkers.has(m.pattern)) {
176
+ seenMarkers.add(m.pattern);
177
+ iocs.markers.push({
178
+ id: m.id,
179
+ pattern: m.pattern,
180
+ severity: m.severity || 'critical',
181
+ confidence: m.confidence || 'high',
182
+ source: m.source,
183
+ description: m.description
184
+ });
185
+ }
186
+ }
187
+ }
188
+
189
+ if (data && data.files) {
190
+ for (const f of data.files) {
191
+ if (!seenFiles.has(f.name)) {
192
+ seenFiles.add(f.name);
193
+ iocs.files.push({
194
+ id: f.id,
195
+ name: f.name,
196
+ severity: f.severity || 'critical',
197
+ confidence: f.confidence || 'high',
198
+ source: f.source,
199
+ description: f.description
200
+ });
201
+ }
202
+ }
203
+ }
204
+ } catch (e) {
205
+ console.error('[WARN] Erreur parsing hashes.yaml:', e.message);
206
+ }
207
+ }
208
+
209
+ let _cachedIOCStats = null;
210
+
211
+ function getIOCStats() {
212
+ if (_cachedIOCStats) return _cachedIOCStats;
213
+ const iocs = loadYAMLIOCs();
214
+ _cachedIOCStats = {
215
+ packages: iocs.packages.length,
216
+ hashes: iocs.hashes.length,
217
+ markers: iocs.markers.length,
218
+ files: iocs.files.length
219
+ };
220
+ return _cachedIOCStats;
221
+ }
222
+
223
+ module.exports = { loadYAMLIOCs, getIOCStats };