pompelmi 0.14.0-dev.25 → 0.14.0-dev.26
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/README.md +119 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
<a href="#diagrams">Diagrams</a> ·
|
|
39
39
|
<a href="#configuration">Config</a> ·
|
|
40
40
|
<a href="#production-checklist">Production checklist</a> ·
|
|
41
|
+
<a href="#yara-getting-started">YARA</a> ·
|
|
41
42
|
<a href="#quick-test-eicar">Quick test</a> ·
|
|
42
43
|
<a href="#security-notes">Security</a> ·
|
|
43
44
|
<a href="#faq">FAQ</a>
|
|
@@ -401,6 +402,124 @@ failClosed: true,
|
|
|
401
402
|
|
|
402
403
|
---
|
|
403
404
|
|
|
405
|
+
## YARA Getting Started
|
|
406
|
+
|
|
407
|
+
YARA lets you detect suspicious or malicious content using pattern‑matching rules.
|
|
408
|
+
**pompelmi** treats YARA matches as signals that you can map to your own verdicts
|
|
409
|
+
(e.g., mark high‑confidence rules as `malicious`, heuristics as `suspicious`).
|
|
410
|
+
|
|
411
|
+
> **Status:** Optional. You can run without YARA. If you adopt it, keep your rules small, time‑bound, and tuned to your threat model.
|
|
412
|
+
|
|
413
|
+
### Starter rules
|
|
414
|
+
|
|
415
|
+
Below are three example rules you can adapt:
|
|
416
|
+
|
|
417
|
+
`rules/starter/eicar.yar`
|
|
418
|
+
```yar
|
|
419
|
+
rule EICAR_Test_File
|
|
420
|
+
{
|
|
421
|
+
meta:
|
|
422
|
+
description = "EICAR antivirus test string (safe)"
|
|
423
|
+
reference = "https://www.eicar.org"
|
|
424
|
+
confidence = "high"
|
|
425
|
+
verdict = "malicious"
|
|
426
|
+
strings:
|
|
427
|
+
$eicar = "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"
|
|
428
|
+
condition:
|
|
429
|
+
$eicar
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
`rules/starter/pdf_js.yar`
|
|
434
|
+
```yar
|
|
435
|
+
rule PDF_JavaScript_Embedded
|
|
436
|
+
{
|
|
437
|
+
meta:
|
|
438
|
+
description = "PDF contains embedded JavaScript (heuristic)"
|
|
439
|
+
confidence = "medium"
|
|
440
|
+
verdict = "suspicious"
|
|
441
|
+
strings:
|
|
442
|
+
$magic = { 25 50 44 46 } // "%PDF"
|
|
443
|
+
$js1 = "/JavaScript" ascii
|
|
444
|
+
$js2 = "/JS" ascii
|
|
445
|
+
$open = "/OpenAction" ascii
|
|
446
|
+
$aa = "/AA" ascii
|
|
447
|
+
condition:
|
|
448
|
+
uint32(0) == 0x25504446 and ( $js1 or $js2 ) and ( $open or $aa )
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
`rules/starter/office_macros.yar`
|
|
453
|
+
```yar
|
|
454
|
+
rule Office_Macro_Suspicious_Words
|
|
455
|
+
{
|
|
456
|
+
meta:
|
|
457
|
+
description = "Heuristic: suspicious VBA macro keywords"
|
|
458
|
+
confidence = "medium"
|
|
459
|
+
verdict = "suspicious"
|
|
460
|
+
strings:
|
|
461
|
+
$s1 = /Auto(Open|Close)/ nocase
|
|
462
|
+
$s2 = "Document_Open" nocase ascii
|
|
463
|
+
$s3 = "CreateObject(" nocase ascii
|
|
464
|
+
$s4 = "WScript.Shell" nocase ascii
|
|
465
|
+
$s5 = "Shell(" nocase ascii
|
|
466
|
+
$s6 = "Sub Workbook_Open()" nocase ascii
|
|
467
|
+
condition:
|
|
468
|
+
2 of ($s*)
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
> These are **examples**. Expect some false positives; tune to your app.
|
|
473
|
+
|
|
474
|
+
### Minimal integration (adapter contract)
|
|
475
|
+
|
|
476
|
+
If you use a YARA binding (e.g., `@automattic/yara`), wrap it behind the `scanner` contract:
|
|
477
|
+
|
|
478
|
+
```ts
|
|
479
|
+
// Example YARA scanner adapter (pseudo‑code)
|
|
480
|
+
import * as Y from '@automattic/yara';
|
|
481
|
+
|
|
482
|
+
// Compile your rules from disk at boot (recommended)
|
|
483
|
+
// const sources = await fs.readFile('rules/starter/*.yar', 'utf8');
|
|
484
|
+
// const compiled = await Y.compile(sources);
|
|
485
|
+
|
|
486
|
+
export const YourYaraScanner = {
|
|
487
|
+
async scan(bytes: Uint8Array) {
|
|
488
|
+
// const matches = await compiled.scan(bytes, { timeout: 1500 });
|
|
489
|
+
const matches = []; // plug your engine here
|
|
490
|
+
// Map to the structure your app expects; return [] when clean.
|
|
491
|
+
return matches.map((m: any) => ({
|
|
492
|
+
rule: m.rule,
|
|
493
|
+
meta: m.meta ?? {},
|
|
494
|
+
tags: m.tags ?? [],
|
|
495
|
+
}));
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
Then include it in your composed scanner:
|
|
501
|
+
|
|
502
|
+
```ts
|
|
503
|
+
import { composeScanners, CommonHeuristicsScanner } from 'pompelmi';
|
|
504
|
+
// import { YourYaraScanner } from './yara-scanner';
|
|
505
|
+
|
|
506
|
+
export const scanner = composeScanners(
|
|
507
|
+
[
|
|
508
|
+
['heuristics', CommonHeuristicsScanner],
|
|
509
|
+
// ['yara', YourYaraScanner],
|
|
510
|
+
],
|
|
511
|
+
{ parallel: false, stopOn: 'suspicious', timeoutMsPerScanner: 1500, tagSourceName: true }
|
|
512
|
+
);
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
### Policy suggestion (mapping matches → verdict)
|
|
516
|
+
|
|
517
|
+
- **malicious**: high‑confidence rules (e.g., `EICAR_Test_File`)
|
|
518
|
+
- **suspicious**: heuristic rules (e.g., PDF JavaScript, macro keywords)
|
|
519
|
+
- **clean**: no matches
|
|
520
|
+
|
|
521
|
+
Combine YARA with MIME sniffing, ZIP safety limits, and strict size/time caps.
|
|
522
|
+
|
|
404
523
|
## Quick test (no EICAR)
|
|
405
524
|
|
|
406
525
|
Use the examples above, then send a **minimal PDF** that contains risky tokens (this triggers the built‑in heuristics).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pompelmi",
|
|
3
|
-
"version": "0.14.0-dev.
|
|
3
|
+
"version": "0.14.0-dev.26",
|
|
4
4
|
"description": "RFI-safe file uploads for Node.js — Express/Koa/Next.js middleware with deep ZIP inspection, MIME/size checks, and optional YARA scanning.",
|
|
5
5
|
"main": "dist/pompelmi.cjs.js",
|
|
6
6
|
"module": "dist/pompelmi.esm.js",
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"dev:remote": "tsx examples/remote-yara-server.ts",
|
|
38
38
|
"docs:build": "hugo -s docs -D -d docs",
|
|
39
39
|
"predocs:deploy": "npm run docs:build",
|
|
40
|
-
"docs:deploy": "gh-pages -d docs -b gh-pages"
|
|
40
|
+
"docs:deploy": "gh-pages -d docs -b gh-pages",
|
|
41
|
+
"yara:check": "node scripts/yara-quick-check-cli.mjs"
|
|
41
42
|
},
|
|
42
43
|
"license": "MIT",
|
|
43
44
|
"devDependencies": {
|