pompelmi 0.14.0-dev.26 → 0.15.0-dev.27
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.
- package/dist/pompelmi.cjs.js +37 -10
- package/dist/pompelmi.cjs.js.map +1 -1
- package/dist/pompelmi.esm.js +36 -11
- package/dist/pompelmi.esm.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/package.json +3 -2
package/dist/pompelmi.cjs.js
CHANGED
|
@@ -3193,7 +3193,8 @@ function isZipLike(buf) {
|
|
|
3193
3193
|
function lastIndexOfEOCD(buf, window) {
|
|
3194
3194
|
const sig = Buffer.from([0x50, 0x4b, 0x05, 0x06]);
|
|
3195
3195
|
const start = Math.max(0, buf.length - window);
|
|
3196
|
-
|
|
3196
|
+
const idx = buf.lastIndexOf(sig, Math.min(buf.length - sig.length, buf.length - 1));
|
|
3197
|
+
return idx >= start ? idx : -1;
|
|
3197
3198
|
}
|
|
3198
3199
|
function hasTraversal(name) {
|
|
3199
3200
|
return name.includes('../') || name.includes('..\\') || name.startsWith('/') || /^[A-Za-z]:/.test(name);
|
|
@@ -3210,7 +3211,7 @@ function createZipBombGuard(opts = {}) {
|
|
|
3210
3211
|
const eocdPos = lastIndexOfEOCD(buf, cfg.eocdSearchWindow);
|
|
3211
3212
|
if (eocdPos < 0 || eocdPos + 22 > buf.length) {
|
|
3212
3213
|
// ZIP but no EOCD — malformed or polyglot → suspicious
|
|
3213
|
-
matches.push({ rule: 'zip_eocd_not_found', severity: '
|
|
3214
|
+
matches.push({ rule: 'zip_eocd_not_found', severity: 'medium' });
|
|
3214
3215
|
return matches;
|
|
3215
3216
|
}
|
|
3216
3217
|
const totalEntries = r16(buf, eocdPos + 10);
|
|
@@ -3218,7 +3219,7 @@ function createZipBombGuard(opts = {}) {
|
|
|
3218
3219
|
const cdOffset = r32(buf, eocdPos + 16);
|
|
3219
3220
|
// Bounds check
|
|
3220
3221
|
if (cdOffset + cdSize > buf.length) {
|
|
3221
|
-
matches.push({ rule: 'zip_cd_out_of_bounds', severity: '
|
|
3222
|
+
matches.push({ rule: 'zip_cd_out_of_bounds', severity: 'medium' });
|
|
3222
3223
|
return matches;
|
|
3223
3224
|
}
|
|
3224
3225
|
// Iterate central directory entries
|
|
@@ -3244,36 +3245,36 @@ function createZipBombGuard(opts = {}) {
|
|
|
3244
3245
|
sumUnc += uncSize;
|
|
3245
3246
|
seen++;
|
|
3246
3247
|
if (name.length > cfg.maxEntryNameLength) {
|
|
3247
|
-
matches.push({ rule: 'zip_entry_name_too_long', severity: '
|
|
3248
|
+
matches.push({ rule: 'zip_entry_name_too_long', severity: 'medium', meta: { name, length: name.length } });
|
|
3248
3249
|
}
|
|
3249
3250
|
if (hasTraversal(name)) {
|
|
3250
|
-
matches.push({ rule: 'zip_path_traversal_entry', severity: '
|
|
3251
|
+
matches.push({ rule: 'zip_path_traversal_entry', severity: 'medium', meta: { name } });
|
|
3251
3252
|
}
|
|
3252
3253
|
// move to next entry
|
|
3253
3254
|
ptr = nameEnd + exLen + cmLen;
|
|
3254
3255
|
}
|
|
3255
3256
|
if (seen !== totalEntries) {
|
|
3256
3257
|
// central dir truncated/odd, still report what we found
|
|
3257
|
-
matches.push({ rule: 'zip_cd_truncated', severity: '
|
|
3258
|
+
matches.push({ rule: 'zip_cd_truncated', severity: 'medium', meta: { seen, totalEntries } });
|
|
3258
3259
|
}
|
|
3259
3260
|
// Heuristics thresholds
|
|
3260
3261
|
if (seen > cfg.maxEntries) {
|
|
3261
|
-
matches.push({ rule: 'zip_too_many_entries', severity: '
|
|
3262
|
+
matches.push({ rule: 'zip_too_many_entries', severity: 'medium', meta: { seen, limit: cfg.maxEntries } });
|
|
3262
3263
|
}
|
|
3263
3264
|
if (sumUnc > cfg.maxTotalUncompressedBytes) {
|
|
3264
3265
|
matches.push({
|
|
3265
3266
|
rule: 'zip_total_uncompressed_too_large',
|
|
3266
|
-
severity: '
|
|
3267
|
+
severity: 'medium',
|
|
3267
3268
|
meta: { totalUncompressed: sumUnc, limit: cfg.maxTotalUncompressedBytes }
|
|
3268
3269
|
});
|
|
3269
3270
|
}
|
|
3270
3271
|
if (sumComp === 0 && sumUnc > 0) {
|
|
3271
|
-
matches.push({ rule: 'zip_suspicious_ratio', severity: '
|
|
3272
|
+
matches.push({ rule: 'zip_suspicious_ratio', severity: 'medium', meta: { ratio: Infinity } });
|
|
3272
3273
|
}
|
|
3273
3274
|
else if (sumComp > 0) {
|
|
3274
3275
|
const ratio = sumUnc / Math.max(1, sumComp);
|
|
3275
3276
|
if (ratio >= cfg.maxCompressionRatio) {
|
|
3276
|
-
matches.push({ rule: 'zip_suspicious_ratio', severity: '
|
|
3277
|
+
matches.push({ rule: 'zip_suspicious_ratio', severity: 'medium', meta: { ratio, limit: cfg.maxCompressionRatio } });
|
|
3277
3278
|
}
|
|
3278
3279
|
}
|
|
3279
3280
|
return matches;
|
|
@@ -3281,8 +3282,34 @@ function createZipBombGuard(opts = {}) {
|
|
|
3281
3282
|
};
|
|
3282
3283
|
}
|
|
3283
3284
|
|
|
3285
|
+
const MB = 1024 * 1024;
|
|
3286
|
+
const DEFAULT_POLICY = {
|
|
3287
|
+
includeExtensions: ['zip', 'png', 'jpg', 'jpeg', 'pdf'],
|
|
3288
|
+
allowedMimeTypes: ['application/zip', 'image/png', 'image/jpeg', 'application/pdf', 'text/plain'],
|
|
3289
|
+
maxFileSizeBytes: 20 * MB,
|
|
3290
|
+
timeoutMs: 5000,
|
|
3291
|
+
concurrency: 4,
|
|
3292
|
+
failClosed: true
|
|
3293
|
+
};
|
|
3294
|
+
function definePolicy(input = {}) {
|
|
3295
|
+
const p = { ...DEFAULT_POLICY, ...input };
|
|
3296
|
+
if (!Array.isArray(p.includeExtensions))
|
|
3297
|
+
throw new TypeError('includeExtensions must be string[]');
|
|
3298
|
+
if (!Array.isArray(p.allowedMimeTypes))
|
|
3299
|
+
throw new TypeError('allowedMimeTypes must be string[]');
|
|
3300
|
+
if (!(Number.isFinite(p.maxFileSizeBytes) && p.maxFileSizeBytes > 0))
|
|
3301
|
+
throw new TypeError('maxFileSizeBytes must be > 0');
|
|
3302
|
+
if (!(Number.isFinite(p.timeoutMs) && p.timeoutMs > 0))
|
|
3303
|
+
throw new TypeError('timeoutMs must be > 0');
|
|
3304
|
+
if (!(Number.isInteger(p.concurrency) && p.concurrency > 0))
|
|
3305
|
+
throw new TypeError('concurrency must be > 0');
|
|
3306
|
+
return p;
|
|
3307
|
+
}
|
|
3308
|
+
|
|
3284
3309
|
exports.CommonHeuristicsScanner = CommonHeuristicsScanner;
|
|
3310
|
+
exports.DEFAULT_POLICY = DEFAULT_POLICY;
|
|
3285
3311
|
exports.createZipBombGuard = createZipBombGuard;
|
|
3312
|
+
exports.definePolicy = definePolicy;
|
|
3286
3313
|
exports.mapMatchesToVerdict = mapMatchesToVerdict;
|
|
3287
3314
|
exports.prefilterBrowser = prefilterBrowser;
|
|
3288
3315
|
exports.scanFiles = scanFiles;
|