pompelmi 0.35.5 → 1.1.0
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/.claude/settings.local.json +45 -0
- package/LICENSE +12 -18
- package/README.md +174 -181
- package/eslint.config.mjs +8 -0
- package/package.json +26 -251
- package/src/ClamAVDatabaseUpdater.js +48 -0
- package/src/ClamAVInstaller.js +49 -0
- package/src/ClamAVScanner.js +37 -0
- package/src/ClamdScanner.js +81 -0
- package/src/InstallerCommand.js +11 -0
- package/src/config.js +22 -0
- package/src/constants.js +3 -0
- package/src/favicon.ico +0 -0
- package/src/grapefruit.png +0 -0
- package/src/index.js +5 -0
- package/test_out.txt +74 -0
- package/CHANGELOG.md +0 -71
- package/dist/pompelmi.audit.cjs +0 -128
- package/dist/pompelmi.audit.cjs.map +0 -1
- package/dist/pompelmi.audit.esm.js +0 -107
- package/dist/pompelmi.audit.esm.js.map +0 -1
- package/dist/pompelmi.browser.cjs +0 -1549
- package/dist/pompelmi.browser.cjs.map +0 -1
- package/dist/pompelmi.browser.esm.js +0 -1523
- package/dist/pompelmi.browser.esm.js.map +0 -1
- package/dist/pompelmi.cjs +0 -2591
- package/dist/pompelmi.cjs.map +0 -1
- package/dist/pompelmi.esm.js +0 -2525
- package/dist/pompelmi.esm.js.map +0 -1
- package/dist/pompelmi.hooks.cjs +0 -75
- package/dist/pompelmi.hooks.cjs.map +0 -1
- package/dist/pompelmi.hooks.esm.js +0 -72
- package/dist/pompelmi.hooks.esm.js.map +0 -1
- package/dist/pompelmi.policy-packs.cjs +0 -240
- package/dist/pompelmi.policy-packs.cjs.map +0 -1
- package/dist/pompelmi.policy-packs.esm.js +0 -232
- package/dist/pompelmi.policy-packs.esm.js.map +0 -1
- package/dist/pompelmi.quarantine.cjs +0 -317
- package/dist/pompelmi.quarantine.cjs.map +0 -1
- package/dist/pompelmi.quarantine.esm.js +0 -293
- package/dist/pompelmi.quarantine.esm.js.map +0 -1
- package/dist/pompelmi.react.cjs +0 -1580
- package/dist/pompelmi.react.cjs.map +0 -1
- package/dist/pompelmi.react.esm.js +0 -1553
- package/dist/pompelmi.react.esm.js.map +0 -1
- package/dist/types/audit.d.ts +0 -84
- package/dist/types/browser-index.d.ts +0 -29
- package/dist/types/config.d.ts +0 -143
- package/dist/types/engines/dynamic-taint.d.ts +0 -102
- package/dist/types/engines/hybrid-orchestrator.d.ts +0 -65
- package/dist/types/engines/hybrid-taint-integration.d.ts +0 -129
- package/dist/types/engines/taint-policies.d.ts +0 -84
- package/dist/types/hipaa-compliance.d.ts +0 -110
- package/dist/types/hooks.d.ts +0 -89
- package/dist/types/index.d.ts +0 -29
- package/dist/types/magic.d.ts +0 -7
- package/dist/types/node/scanDir.d.ts +0 -30
- package/dist/types/policy-packs.d.ts +0 -98
- package/dist/types/policy.d.ts +0 -12
- package/dist/types/presets.d.ts +0 -72
- package/dist/types/quarantine/index.d.ts +0 -18
- package/dist/types/quarantine/storage.d.ts +0 -77
- package/dist/types/quarantine/types.d.ts +0 -78
- package/dist/types/quarantine/workflow.d.ts +0 -97
- package/dist/types/react-index.d.ts +0 -13
- package/dist/types/risk.d.ts +0 -18
- package/dist/types/scan/remote.d.ts +0 -12
- package/dist/types/scan.d.ts +0 -17
- package/dist/types/scanners/common-heuristics.d.ts +0 -14
- package/dist/types/scanners/zip-bomb-guard.d.ts +0 -9
- package/dist/types/scanners/zipTraversalGuard.d.ts +0 -19
- package/dist/types/src/audit.d.ts +0 -84
- package/dist/types/src/browser-index.d.ts +0 -29
- package/dist/types/src/config.d.ts +0 -143
- package/dist/types/src/engines/dynamic-taint.d.ts +0 -102
- package/dist/types/src/engines/hybrid-orchestrator.d.ts +0 -65
- package/dist/types/src/engines/hybrid-taint-integration.d.ts +0 -129
- package/dist/types/src/engines/taint-policies.d.ts +0 -84
- package/dist/types/src/hipaa-compliance.d.ts +0 -110
- package/dist/types/src/hooks.d.ts +0 -89
- package/dist/types/src/index.d.ts +0 -29
- package/dist/types/src/magic.d.ts +0 -7
- package/dist/types/src/node/scanDir.d.ts +0 -30
- package/dist/types/src/policy-packs.d.ts +0 -98
- package/dist/types/src/policy.d.ts +0 -12
- package/dist/types/src/presets.d.ts +0 -72
- package/dist/types/src/quarantine/index.d.ts +0 -18
- package/dist/types/src/quarantine/storage.d.ts +0 -77
- package/dist/types/src/quarantine/types.d.ts +0 -78
- package/dist/types/src/quarantine/workflow.d.ts +0 -97
- package/dist/types/src/react-index.d.ts +0 -13
- package/dist/types/src/risk.d.ts +0 -18
- package/dist/types/src/scan/remote.d.ts +0 -12
- package/dist/types/src/scan.d.ts +0 -17
- package/dist/types/src/scanners/common-heuristics.d.ts +0 -14
- package/dist/types/src/scanners/zip-bomb-guard.d.ts +0 -11
- package/dist/types/src/scanners/zipTraversalGuard.d.ts +0 -19
- package/dist/types/src/stream.d.ts +0 -10
- package/dist/types/src/types/decompilation.d.ts +0 -96
- package/dist/types/src/types/taint-tracking.d.ts +0 -495
- package/dist/types/src/types.d.ts +0 -48
- package/dist/types/src/useFileScanner.d.ts +0 -15
- package/dist/types/src/utils/advanced-detection.d.ts +0 -21
- package/dist/types/src/utils/batch-scanner.d.ts +0 -62
- package/dist/types/src/utils/cache-manager.d.ts +0 -95
- package/dist/types/src/utils/export.d.ts +0 -51
- package/dist/types/src/utils/performance-metrics.d.ts +0 -68
- package/dist/types/src/utils/threat-intelligence.d.ts +0 -96
- package/dist/types/src/validate.d.ts +0 -7
- package/dist/types/src/verdict.d.ts +0 -2
- package/dist/types/src/yara/browser.d.ts +0 -7
- package/dist/types/src/yara/index.d.ts +0 -17
- package/dist/types/src/yara/node.d.ts +0 -2
- package/dist/types/src/yara/remote.d.ts +0 -10
- package/dist/types/src/yara-bridge.d.ts +0 -3
- package/dist/types/src/zip.d.ts +0 -13
- package/dist/types/stream.d.ts +0 -10
- package/dist/types/types/decompilation.d.ts +0 -96
- package/dist/types/types/taint-tracking.d.ts +0 -495
- package/dist/types/types.d.ts +0 -48
- package/dist/types/useFileScanner.d.ts +0 -15
- package/dist/types/utils/advanced-detection.d.ts +0 -21
- package/dist/types/utils/batch-scanner.d.ts +0 -62
- package/dist/types/utils/cache-manager.d.ts +0 -95
- package/dist/types/utils/export.d.ts +0 -51
- package/dist/types/utils/performance-metrics.d.ts +0 -68
- package/dist/types/utils/threat-intelligence.d.ts +0 -96
- package/dist/types/validate.d.ts +0 -7
- package/dist/types/verdict.d.ts +0 -2
- package/dist/types/yara/browser.d.ts +0 -7
- package/dist/types/yara/index.d.ts +0 -17
- package/dist/types/yara/node.d.ts +0 -2
- package/dist/types/yara/remote.d.ts +0 -10
- package/dist/types/yara-bridge.d.ts +0 -3
- package/dist/types/zip.d.ts +0 -13
package/dist/types/presets.d.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import type { AnalysisDepth, ScanFn, Scanner, Verdict } from "./types";
|
|
2
|
-
export type PresetName = "basic" | "advanced" | "malware-analysis" | "decompilation-basic" | "decompilation-deep" | string;
|
|
3
|
-
export interface PresetOptions {
|
|
4
|
-
yaraRules?: string | string[];
|
|
5
|
-
yaraTimeout?: number;
|
|
6
|
-
enableDecompilation?: boolean;
|
|
7
|
-
decompilationEngine?: "binaryninja-hlil" | "ghidra-pcode" | "both";
|
|
8
|
-
decompilationDepth?: AnalysisDepth;
|
|
9
|
-
decompilationTimeout?: number;
|
|
10
|
-
binaryNinjaPath?: string;
|
|
11
|
-
pythonPath?: string;
|
|
12
|
-
ghidraPath?: string;
|
|
13
|
-
analyzeHeadless?: string;
|
|
14
|
-
timeout?: number;
|
|
15
|
-
[key: string]: unknown;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* A named scanner entry used with the array form of `composeScanners`.
|
|
19
|
-
* The first element is a display name for the scanner (used when
|
|
20
|
-
* `tagSourceName: true`), and the second element is the scanner itself.
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* const entry: NamedScanner = ['zipGuard', createZipBombGuard({ ... })];
|
|
24
|
-
*/
|
|
25
|
-
export type NamedScanner = [name: string, scanner: Scanner];
|
|
26
|
-
/**
|
|
27
|
-
* Options for `composeScanners` when using the named-scanner array form.
|
|
28
|
-
*/
|
|
29
|
-
export interface ComposeScannerOptions {
|
|
30
|
-
/**
|
|
31
|
-
* When `true` scanners run concurrently (Promise.all).
|
|
32
|
-
* When `false` (default) they run sequentially in order.
|
|
33
|
-
*/
|
|
34
|
-
parallel?: boolean;
|
|
35
|
-
/**
|
|
36
|
-
* Stop scanning as soon as a match at this severity level (or higher) is
|
|
37
|
-
* found. Severity order: `'malicious'` > `'suspicious'` > `'clean'`.
|
|
38
|
-
* Only effective when `parallel` is `false`.
|
|
39
|
-
*/
|
|
40
|
-
stopOn?: Verdict;
|
|
41
|
-
/** Maximum time in milliseconds to wait for each individual scanner. */
|
|
42
|
-
timeoutMsPerScanner?: number;
|
|
43
|
-
/**
|
|
44
|
-
* When `true`, each match is tagged with the scanner's display name via
|
|
45
|
-
* `match.meta._sourceName`. Useful for tracing which scanner produced a
|
|
46
|
-
* given result.
|
|
47
|
-
*/
|
|
48
|
-
tagSourceName?: boolean;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Compose multiple scanners into a single scanner.
|
|
52
|
-
*
|
|
53
|
-
* **Named-scanner array form** (recommended — matches the README examples):
|
|
54
|
-
* ```ts
|
|
55
|
-
* const scanner = composeScanners(
|
|
56
|
-
* [
|
|
57
|
-
* ['zipGuard', createZipBombGuard({ maxEntries: 512, maxCompressionRatio: 12 })],
|
|
58
|
-
* ['heuristics', CommonHeuristicsScanner],
|
|
59
|
-
* ],
|
|
60
|
-
* { parallel: false, stopOn: 'malicious', timeoutMsPerScanner: 5000, tagSourceName: true }
|
|
61
|
-
* );
|
|
62
|
-
* ```
|
|
63
|
-
*
|
|
64
|
-
* **Variadic form** (backward-compatible):
|
|
65
|
-
* ```ts
|
|
66
|
-
* const scanner = composeScanners(scannerA, scannerB, scannerC);
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
export declare function composeScanners(namedScanners: NamedScanner[], opts?: ComposeScannerOptions): ScanFn;
|
|
70
|
-
export declare function composeScanners(...scanners: Scanner[]): ScanFn;
|
|
71
|
-
export declare function createPresetScanner(preset: PresetName, opts?: PresetOptions): Scanner;
|
|
72
|
-
export declare const PRESET_CONFIGS: Record<string, PresetOptions>;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pompelmi Quarantine Module
|
|
3
|
-
*
|
|
4
|
-
* Provides a first-class quarantine workflow for secure upload pipelines:
|
|
5
|
-
* scan → flag → quarantine → review → promote | delete
|
|
6
|
-
*
|
|
7
|
-
* Entry points:
|
|
8
|
-
* import { QuarantineManager, FilesystemQuarantineStorage } from 'pompelmi/quarantine';
|
|
9
|
-
*
|
|
10
|
-
* The storage layer is pluggable via the `QuarantineStorage` interface.
|
|
11
|
-
* `FilesystemQuarantineStorage` is the reference implementation for local/on-premise use.
|
|
12
|
-
*
|
|
13
|
-
* This module is Node.js-only (uses fs/crypto/path).
|
|
14
|
-
* It is NOT included in the 'pompelmi/browser' or 'pompelmi/react' bundles.
|
|
15
|
-
*/
|
|
16
|
-
export { FilesystemQuarantineStorage, type FilesystemQuarantineStorageOptions, type QuarantineStorage, } from "./storage";
|
|
17
|
-
export type { QuarantineDecision, QuarantinedFileInfo, QuarantineEntry, QuarantineFilter, QuarantineReport, QuarantineReview, QuarantineStatus, } from "./types";
|
|
18
|
-
export { QuarantineManager, type QuarantineManagerOptions } from "./workflow";
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Quarantine storage adapter interface and filesystem reference implementation.
|
|
3
|
-
*
|
|
4
|
-
* The `QuarantineStorage` interface decouples the quarantine workflow from any
|
|
5
|
-
* specific persistence layer. You can implement it for S3, GCS, a database,
|
|
6
|
-
* or any other backend.
|
|
7
|
-
*
|
|
8
|
-
* The built-in `FilesystemQuarantineStorage` stores files and metadata as JSON
|
|
9
|
-
* in a local directory — suitable for development, self-hosted, and on-premise
|
|
10
|
-
* deployments where data must not leave the machine.
|
|
11
|
-
*
|
|
12
|
-
* @module quarantine/storage
|
|
13
|
-
*/
|
|
14
|
-
import type { QuarantineEntry, QuarantineFilter } from "./types";
|
|
15
|
-
/**
|
|
16
|
-
* Storage adapter for the quarantine workflow.
|
|
17
|
-
* Implement this interface to support any backend (S3, GCS, DB, etc.).
|
|
18
|
-
*/
|
|
19
|
-
export interface QuarantineStorage {
|
|
20
|
-
/**
|
|
21
|
-
* Persist the raw bytes of a quarantined file.
|
|
22
|
-
* Returns a `storageKey` that can later be used to retrieve or delete the bytes.
|
|
23
|
-
*/
|
|
24
|
-
saveFile(id: string, bytes: Uint8Array): Promise<string>;
|
|
25
|
-
/**
|
|
26
|
-
* Retrieve the raw bytes of a quarantined file.
|
|
27
|
-
* Returns `null` if the file is not found.
|
|
28
|
-
*/
|
|
29
|
-
getFile(storageKey: string): Promise<Uint8Array | null>;
|
|
30
|
-
/**
|
|
31
|
-
* Permanently remove the raw bytes of a quarantined file.
|
|
32
|
-
* No-op if already removed.
|
|
33
|
-
*/
|
|
34
|
-
deleteFile(storageKey: string): Promise<void>;
|
|
35
|
-
/** Persist a quarantine entry (metadata + scan report). */
|
|
36
|
-
saveEntry(entry: QuarantineEntry): Promise<void>;
|
|
37
|
-
/** Load a quarantine entry by id. Returns `null` if not found. */
|
|
38
|
-
getEntry(id: string): Promise<QuarantineEntry | null>;
|
|
39
|
-
/** Update an existing quarantine entry (partial update). */
|
|
40
|
-
updateEntry(id: string, patch: Partial<QuarantineEntry>): Promise<QuarantineEntry>;
|
|
41
|
-
/** List quarantine entries matching the given filter. */
|
|
42
|
-
listEntries(filter?: QuarantineFilter): Promise<QuarantineEntry[]>;
|
|
43
|
-
/** Return the total count of quarantine entries matching the filter. */
|
|
44
|
-
countEntries(filter?: QuarantineFilter): Promise<number>;
|
|
45
|
-
}
|
|
46
|
-
export interface FilesystemQuarantineStorageOptions {
|
|
47
|
-
/**
|
|
48
|
-
* Root directory for quarantine storage.
|
|
49
|
-
* Two subdirectories are created: `files/` (raw bytes) and `meta/` (JSON).
|
|
50
|
-
*/
|
|
51
|
-
dir: string;
|
|
52
|
-
/** Create the directory if it does not exist (default: true). */
|
|
53
|
-
createIfMissing?: boolean;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Reference implementation of `QuarantineStorage` backed by the local filesystem.
|
|
57
|
-
*
|
|
58
|
-
* File layout:
|
|
59
|
-
* <dir>/files/<storageKey> — raw file bytes
|
|
60
|
-
* <dir>/meta/<id>.json — QuarantineEntry JSON
|
|
61
|
-
*
|
|
62
|
-
* Suitable for single-process servers. For multi-process or distributed
|
|
63
|
-
* deployments, implement `QuarantineStorage` against a shared backend.
|
|
64
|
-
*/
|
|
65
|
-
export declare class FilesystemQuarantineStorage implements QuarantineStorage {
|
|
66
|
-
private readonly filesDir;
|
|
67
|
-
private readonly metaDir;
|
|
68
|
-
constructor(options: FilesystemQuarantineStorageOptions);
|
|
69
|
-
saveFile(id: string, bytes: Uint8Array): Promise<string>;
|
|
70
|
-
getFile(storageKey: string): Promise<Uint8Array | null>;
|
|
71
|
-
deleteFile(storageKey: string): Promise<void>;
|
|
72
|
-
saveEntry(entry: QuarantineEntry): Promise<void>;
|
|
73
|
-
getEntry(id: string): Promise<QuarantineEntry | null>;
|
|
74
|
-
updateEntry(id: string, patch: Partial<QuarantineEntry>): Promise<QuarantineEntry>;
|
|
75
|
-
listEntries(filter?: QuarantineFilter): Promise<QuarantineEntry[]>;
|
|
76
|
-
countEntries(filter?: QuarantineFilter): Promise<number>;
|
|
77
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Quarantine system types for Pompelmi.
|
|
3
|
-
*
|
|
4
|
-
* A quarantine entry represents a file that was flagged during scanning and is
|
|
5
|
-
* held for manual review before being accepted or permanently removed.
|
|
6
|
-
*
|
|
7
|
-
* The lifecycle of a quarantined entry:
|
|
8
|
-
*
|
|
9
|
-
* scan → flagged → quarantined → reviewed → promoted | deleted
|
|
10
|
-
*
|
|
11
|
-
* @module quarantine/types
|
|
12
|
-
*/
|
|
13
|
-
import type { ScanReport } from "../types";
|
|
14
|
-
/** The review status of a quarantined file. */
|
|
15
|
-
export type QuarantineStatus = "pending" | "reviewing" | "promoted" | "deleted";
|
|
16
|
-
/** Immutable metadata about the file at upload time. */
|
|
17
|
-
export interface QuarantinedFileInfo {
|
|
18
|
-
/** Original filename supplied by the uploader. */
|
|
19
|
-
originalName: string;
|
|
20
|
-
/** Detected MIME type (from magic bytes, not the Content-Type header). */
|
|
21
|
-
mimeType?: string;
|
|
22
|
-
/** File size in bytes. */
|
|
23
|
-
sizeBytes: number;
|
|
24
|
-
/** SHA-256 hex digest of the file content. */
|
|
25
|
-
sha256: string;
|
|
26
|
-
/** Uploader identity — opaque string (user id, session id, IP, etc.). */
|
|
27
|
-
uploadedBy?: string;
|
|
28
|
-
}
|
|
29
|
-
/** A quarantine entry created when a file is flagged. */
|
|
30
|
-
export interface QuarantineEntry {
|
|
31
|
-
/** Stable identifier for this quarantine entry (UUID). */
|
|
32
|
-
id: string;
|
|
33
|
-
/** Filename used to locate the quarantined bytes in storage. */
|
|
34
|
-
storageKey: string;
|
|
35
|
-
/** Metadata captured at upload time. */
|
|
36
|
-
file: QuarantinedFileInfo;
|
|
37
|
-
/** The scan report that triggered quarantine. */
|
|
38
|
-
scanReport: ScanReport;
|
|
39
|
-
/** ISO-8601 timestamp when the file was quarantined. */
|
|
40
|
-
quarantinedAt: string;
|
|
41
|
-
/** Current review status. */
|
|
42
|
-
status: QuarantineStatus;
|
|
43
|
-
/** ISO-8601 timestamp of the last status change. */
|
|
44
|
-
updatedAt: string;
|
|
45
|
-
/** Identity of the reviewer (operator id, etc.). Populated at review time. */
|
|
46
|
-
reviewedBy?: string;
|
|
47
|
-
/** Free-text review note from the operator. */
|
|
48
|
-
reviewNote?: string;
|
|
49
|
-
/** ISO-8601 timestamp when the final decision (promote/delete) was made. */
|
|
50
|
-
resolvedAt?: string;
|
|
51
|
-
/** Optional application-specific tags or labels. */
|
|
52
|
-
tags?: string[];
|
|
53
|
-
}
|
|
54
|
-
/** The outcome of a manual review. */
|
|
55
|
-
export type QuarantineDecision = "promote" | "delete";
|
|
56
|
-
/** Input required to resolve a quarantine entry. */
|
|
57
|
-
export interface QuarantineReview {
|
|
58
|
-
decision: QuarantineDecision;
|
|
59
|
-
reviewedBy?: string;
|
|
60
|
-
reviewNote?: string;
|
|
61
|
-
}
|
|
62
|
-
/** A structured JSON report of all quarantined entries (for audit/export). */
|
|
63
|
-
export interface QuarantineReport {
|
|
64
|
-
generatedAt: string;
|
|
65
|
-
totalEntries: number;
|
|
66
|
-
byStatus: Record<QuarantineStatus, number>;
|
|
67
|
-
entries: QuarantineEntry[];
|
|
68
|
-
}
|
|
69
|
-
/** Filter parameters for listing quarantine entries. */
|
|
70
|
-
export interface QuarantineFilter {
|
|
71
|
-
status?: QuarantineStatus | QuarantineStatus[];
|
|
72
|
-
/** Return only entries quarantined after this ISO-8601 timestamp. */
|
|
73
|
-
after?: string;
|
|
74
|
-
/** Return only entries quarantined before this ISO-8601 timestamp. */
|
|
75
|
-
before?: string;
|
|
76
|
-
/** Maximum number of results to return. */
|
|
77
|
-
limit?: number;
|
|
78
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Quarantine workflow — core API for the quarantine/review/resolve lifecycle.
|
|
3
|
-
*
|
|
4
|
-
* Usage (Node.js):
|
|
5
|
-
*
|
|
6
|
-
* ```ts
|
|
7
|
-
* import { scanBytes } from 'pompelmi';
|
|
8
|
-
* import { QuarantineManager, FilesystemQuarantineStorage } from 'pompelmi/quarantine';
|
|
9
|
-
*
|
|
10
|
-
* const quarantine = new QuarantineManager({
|
|
11
|
-
* storage: new FilesystemQuarantineStorage({ dir: './quarantine' }),
|
|
12
|
-
* });
|
|
13
|
-
*
|
|
14
|
-
* const report = await scanBytes(fileBytes, { ctx: { filename: file.name } });
|
|
15
|
-
*
|
|
16
|
-
* if (report.verdict !== 'clean') {
|
|
17
|
-
* const entry = await quarantine.quarantine(fileBytes, report, {
|
|
18
|
-
* originalName: file.name,
|
|
19
|
-
* sizeBytes: fileBytes.length,
|
|
20
|
-
* uploadedBy: req.user?.id,
|
|
21
|
-
* });
|
|
22
|
-
* console.log('Quarantined:', entry.id);
|
|
23
|
-
* }
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* @module quarantine/workflow
|
|
27
|
-
*/
|
|
28
|
-
import type { ScanReport } from "../types";
|
|
29
|
-
import type { QuarantineStorage } from "./storage";
|
|
30
|
-
import type { QuarantinedFileInfo, QuarantineEntry, QuarantineFilter, QuarantineReport, QuarantineReview } from "./types";
|
|
31
|
-
export interface QuarantineManagerOptions {
|
|
32
|
-
/** Storage adapter — use `FilesystemQuarantineStorage` for local deployments. */
|
|
33
|
-
storage: QuarantineStorage;
|
|
34
|
-
/**
|
|
35
|
-
* If true, files with a 'suspicious' verdict are also quarantined.
|
|
36
|
-
* Default: true.
|
|
37
|
-
*/
|
|
38
|
-
quarantineSuspicious?: boolean;
|
|
39
|
-
/**
|
|
40
|
-
* If true, files with a 'malicious' verdict are also quarantined.
|
|
41
|
-
* Default: true.
|
|
42
|
-
*/
|
|
43
|
-
quarantineMalicious?: boolean;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Manages the full lifecycle of quarantined files:
|
|
47
|
-
* scan → quarantine → review → promote | delete
|
|
48
|
-
*/
|
|
49
|
-
export declare class QuarantineManager {
|
|
50
|
-
private readonly storage;
|
|
51
|
-
private readonly quarantineSuspicious;
|
|
52
|
-
private readonly quarantineMalicious;
|
|
53
|
-
constructor(options: QuarantineManagerOptions);
|
|
54
|
-
/**
|
|
55
|
-
* Determine whether a scan report should trigger quarantine per the
|
|
56
|
-
* configured policy.
|
|
57
|
-
*/
|
|
58
|
-
shouldQuarantine(report: ScanReport): boolean;
|
|
59
|
-
/**
|
|
60
|
-
* Quarantine a file: save the bytes in storage, create the metadata entry,
|
|
61
|
-
* and return the entry.
|
|
62
|
-
*
|
|
63
|
-
* @param bytes Raw file bytes.
|
|
64
|
-
* @param report The scan report that triggered quarantine.
|
|
65
|
-
* @param fileInfo Partial metadata; `sha256` is derived from `bytes` if omitted.
|
|
66
|
-
*/
|
|
67
|
-
quarantine(bytes: Uint8Array, report: ScanReport, fileInfo: Omit<QuarantinedFileInfo, "sha256"> & {
|
|
68
|
-
sha256?: string;
|
|
69
|
-
}): Promise<QuarantineEntry>;
|
|
70
|
-
/**
|
|
71
|
-
* Mark an entry as being actively reviewed.
|
|
72
|
-
*/
|
|
73
|
-
startReview(id: string, reviewedBy?: string): Promise<QuarantineEntry>;
|
|
74
|
-
/**
|
|
75
|
-
* Resolve a quarantine entry with a final decision.
|
|
76
|
-
*
|
|
77
|
-
* - `promote`: the file is cleared — bytes remain in storage for the caller
|
|
78
|
-
* to move to its final destination.
|
|
79
|
-
* - `delete`: the bytes are permanently removed from quarantine storage.
|
|
80
|
-
*/
|
|
81
|
-
resolve(id: string, review: QuarantineReview): Promise<QuarantineEntry>;
|
|
82
|
-
/**
|
|
83
|
-
* Retrieve the raw bytes of a promoted file so the caller can move it to
|
|
84
|
-
* permanent storage. Returns `null` if the entry is not found or has been
|
|
85
|
-
* deleted.
|
|
86
|
-
*/
|
|
87
|
-
getFile(id: string): Promise<Uint8Array | null>;
|
|
88
|
-
getEntry(id: string): Promise<QuarantineEntry | null>;
|
|
89
|
-
listEntries(filter?: QuarantineFilter): Promise<QuarantineEntry[]>;
|
|
90
|
-
listPending(): Promise<QuarantineEntry[]>;
|
|
91
|
-
countEntries(filter?: QuarantineFilter): Promise<number>;
|
|
92
|
-
/**
|
|
93
|
-
* Generate a structured JSON report of all quarantine entries matching the
|
|
94
|
-
* filter — suitable for audit logs and dashboards.
|
|
95
|
-
*/
|
|
96
|
-
report(filter?: QuarantineFilter): Promise<QuarantineReport>;
|
|
97
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* src/react-index.ts — React entry point for Pompelmi.
|
|
3
|
-
*
|
|
4
|
-
* Re-exports the full browser-safe Pompelmi API plus the React hook.
|
|
5
|
-
* Import from 'pompelmi/react'.
|
|
6
|
-
*
|
|
7
|
-
* Peer dependency: react ^18 || ^19
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* import { useFileScanner } from 'pompelmi/react';
|
|
11
|
-
*/
|
|
12
|
-
export * from "./browser-index";
|
|
13
|
-
export { useFileScanner } from "./useFileScanner";
|
package/dist/types/risk.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export type Severity = "clean" | "suspicious" | "malicious";
|
|
2
|
-
export type Match = {
|
|
3
|
-
rule: string;
|
|
4
|
-
meta?: Record<string, any>;
|
|
5
|
-
};
|
|
6
|
-
export type Verdict = {
|
|
7
|
-
severity: Severity;
|
|
8
|
-
reasons: string[];
|
|
9
|
-
matches: Match[];
|
|
10
|
-
mime?: string;
|
|
11
|
-
};
|
|
12
|
-
export type Policy = {
|
|
13
|
-
includeExtensions: string[];
|
|
14
|
-
allowedMimeTypes: string[];
|
|
15
|
-
maxFileSizeBytes: number;
|
|
16
|
-
denyScriptableSvg?: boolean;
|
|
17
|
-
};
|
|
18
|
-
export declare function prefilter(bytes: Uint8Array, origName: string, policy: Policy): Verdict;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { YaraMatch } from "../yara/index";
|
|
2
|
-
import type { RemoteEngineOptions } from "../yara/remote";
|
|
3
|
-
export interface RemoteScanResult {
|
|
4
|
-
file: File;
|
|
5
|
-
matches: YaraMatch[];
|
|
6
|
-
error?: string;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Scansiona una lista di File nel browser usando il motore remoto via HTTP.
|
|
10
|
-
* Non richiede WASM né dipendenze native sul client.
|
|
11
|
-
*/
|
|
12
|
-
export declare function scanFilesWithRemoteYara(files: File[], rulesSource: string, remote: RemoteEngineOptions): Promise<RemoteScanResult[]>;
|
package/dist/types/scan.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { ScannerConfig } from "./config";
|
|
2
|
-
import { type PresetName } from "./presets";
|
|
3
|
-
import type { ScanContext, ScanReport } from "./types";
|
|
4
|
-
export type ScanOptions = {
|
|
5
|
-
preset?: PresetName;
|
|
6
|
-
ctx?: ScanContext;
|
|
7
|
-
enableAdvancedDetection?: boolean;
|
|
8
|
-
enablePerformanceTracking?: boolean;
|
|
9
|
-
enableCache?: boolean;
|
|
10
|
-
config?: Partial<ScannerConfig>;
|
|
11
|
-
};
|
|
12
|
-
/** Scan di bytes (browser/node) usando preset (default: zip-basic) */
|
|
13
|
-
export declare function scanBytes(input: Uint8Array, opts?: ScanOptions): Promise<ScanReport>;
|
|
14
|
-
/** Scan di un file su disco (Node). Import dinamico per non vincolare il bundle browser. */
|
|
15
|
-
export declare function scanFile(filePath: string, opts?: Omit<ScanOptions, "ctx">): Promise<ScanReport>;
|
|
16
|
-
/** Scan multipli File (browser) usando scanBytes + preset di default */
|
|
17
|
-
export declare function scanFiles(files: ArrayLike<File>, opts?: Omit<ScanOptions, "ctx">): Promise<ScanReport[]>;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CommonHeuristicsScanner
|
|
3
|
-
* Lightweight, no-deps heuristics for common risky file patterns.
|
|
4
|
-
* Returns matches as [{ rule, severity?, meta? }].
|
|
5
|
-
*/
|
|
6
|
-
export type HeuristicMatch = {
|
|
7
|
-
rule: string;
|
|
8
|
-
severity?: "info" | "low" | "medium" | "high" | "critical" | "suspicious" | "malicious";
|
|
9
|
-
meta?: Record<string, unknown>;
|
|
10
|
-
};
|
|
11
|
-
export interface SimpleScanner {
|
|
12
|
-
scan(bytes: Uint8Array): Promise<HeuristicMatch[]>;
|
|
13
|
-
}
|
|
14
|
-
export declare const CommonHeuristicsScanner: SimpleScanner;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Scanner } from "../types";
|
|
2
|
-
export type ZipBombGuardOptions = {
|
|
3
|
-
maxEntries?: number;
|
|
4
|
-
maxTotalUncompressedBytes?: number;
|
|
5
|
-
maxEntryNameLength?: number;
|
|
6
|
-
maxCompressionRatio?: number;
|
|
7
|
-
eocdSearchWindow?: number;
|
|
8
|
-
};
|
|
9
|
-
export declare function createZipBombGuard(opts?: ZipBombGuardOptions): Scanner;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* createZipTraversalGuard – guards against path traversal & header spoofing in ZIPs.
|
|
3
|
-
* EXPECTS: caller provides an iterator over entries with metadata (name, isSymlink, target?, from CEN & LFH).
|
|
4
|
-
* Return non-empty array to flag.
|
|
5
|
-
*/
|
|
6
|
-
export type EntryMeta = {
|
|
7
|
-
nameCEN: string;
|
|
8
|
-
nameLFH: string;
|
|
9
|
-
isSymlink?: boolean;
|
|
10
|
-
linkTarget?: string;
|
|
11
|
-
};
|
|
12
|
-
export declare function createZipTraversalGuard(): {
|
|
13
|
-
id: string;
|
|
14
|
-
scan(entries: AsyncIterable<EntryMeta>): Promise<{
|
|
15
|
-
rule: string;
|
|
16
|
-
severity: "suspicious";
|
|
17
|
-
msg: string;
|
|
18
|
-
}[]>;
|
|
19
|
-
};
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Audit trail for Pompelmi scan and quarantine events.
|
|
3
|
-
*
|
|
4
|
-
* Produces structured, append-only audit records suitable for:
|
|
5
|
-
* - compliance logging (HIPAA, SOC 2, ISO 27001)
|
|
6
|
-
* - SIEM ingestion
|
|
7
|
-
* - operational dashboards
|
|
8
|
-
* - incident response
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* ```ts
|
|
12
|
-
* import { AuditTrail } from 'pompelmi/audit';
|
|
13
|
-
*
|
|
14
|
-
* const audit = new AuditTrail({ dest: 'file', path: './audit.jsonl' });
|
|
15
|
-
* audit.logScanComplete({ filename: 'upload.zip', verdict: 'suspicious', ... });
|
|
16
|
-
* audit.logQuarantine({ entryId: '...', sha256: '...', ... });
|
|
17
|
-
* ```
|
|
18
|
-
*
|
|
19
|
-
* @module audit
|
|
20
|
-
*/
|
|
21
|
-
import type { QuarantineEntry } from "./quarantine/types";
|
|
22
|
-
import type { ScanReport } from "./types";
|
|
23
|
-
export type AuditEventType = "scan.complete" | "scan.error" | "threat.detected" | "quarantine.created" | "quarantine.resolved" | "quarantine.deleted";
|
|
24
|
-
interface BaseAuditRecord {
|
|
25
|
-
/** ISO-8601 timestamp. */
|
|
26
|
-
timestamp: string;
|
|
27
|
-
/** Event type for structured log routing. */
|
|
28
|
-
event: AuditEventType;
|
|
29
|
-
/** Application-assigned session or request id for correlation. */
|
|
30
|
-
correlationId?: string;
|
|
31
|
-
/** Uploader identity. */
|
|
32
|
-
uploadedBy?: string;
|
|
33
|
-
}
|
|
34
|
-
export interface ScanAuditRecord extends BaseAuditRecord {
|
|
35
|
-
event: "scan.complete" | "scan.error" | "threat.detected";
|
|
36
|
-
filename?: string;
|
|
37
|
-
mimeType?: string;
|
|
38
|
-
sizeBytes?: number;
|
|
39
|
-
sha256?: string;
|
|
40
|
-
verdict: ScanReport["verdict"];
|
|
41
|
-
matchCount: number;
|
|
42
|
-
durationMs?: number;
|
|
43
|
-
engine?: string;
|
|
44
|
-
error?: string;
|
|
45
|
-
}
|
|
46
|
-
export interface QuarantineAuditRecord extends BaseAuditRecord {
|
|
47
|
-
event: "quarantine.created" | "quarantine.resolved" | "quarantine.deleted";
|
|
48
|
-
quarantineId: string;
|
|
49
|
-
filename?: string;
|
|
50
|
-
sha256: string;
|
|
51
|
-
decision?: "promote" | "delete";
|
|
52
|
-
reviewedBy?: string;
|
|
53
|
-
reviewNote?: string;
|
|
54
|
-
}
|
|
55
|
-
export type AuditRecord = ScanAuditRecord | QuarantineAuditRecord;
|
|
56
|
-
export type AuditDest = {
|
|
57
|
-
dest: "console";
|
|
58
|
-
} | {
|
|
59
|
-
dest: "file";
|
|
60
|
-
path: string;
|
|
61
|
-
} | {
|
|
62
|
-
dest: "custom";
|
|
63
|
-
write: (record: AuditRecord) => void | Promise<void>;
|
|
64
|
-
};
|
|
65
|
-
export interface AuditTrailOptions {
|
|
66
|
-
/** Where to write audit records. Default: 'console'. */
|
|
67
|
-
output?: AuditDest;
|
|
68
|
-
/** If true, pretty-print JSON. Useful for debugging. Default: false. */
|
|
69
|
-
pretty?: boolean;
|
|
70
|
-
}
|
|
71
|
-
export declare class AuditTrail {
|
|
72
|
-
private readonly options;
|
|
73
|
-
constructor(options?: AuditTrailOptions);
|
|
74
|
-
/** Log a completed scan. */
|
|
75
|
-
logScanComplete(report: ScanReport, extra?: Pick<ScanAuditRecord, "filename" | "sizeBytes" | "sha256" | "correlationId" | "uploadedBy">): void;
|
|
76
|
-
/** Log a scan error. */
|
|
77
|
-
logScanError(error: unknown, extra?: Pick<ScanAuditRecord, "filename" | "correlationId" | "uploadedBy">): void;
|
|
78
|
-
/** Log a new quarantine entry. */
|
|
79
|
-
logQuarantine(entry: QuarantineEntry, correlationId?: string): void;
|
|
80
|
-
/** Log a quarantine resolution (promote or delete). */
|
|
81
|
-
logQuarantineResolved(entry: QuarantineEntry, correlationId?: string): void;
|
|
82
|
-
private write;
|
|
83
|
-
}
|
|
84
|
-
export {};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* src/browser-index.ts — Browser-safe entry point for Pompelmi.
|
|
3
|
-
*
|
|
4
|
-
* This bundle contains ONLY modules that are safe to use in a browser/bundler
|
|
5
|
-
* environment. It does NOT include:
|
|
6
|
-
* - HIPAA compliance module (uses Node.js crypto/os/path)
|
|
7
|
-
* - Cache manager (uses Node.js crypto for content hashing)
|
|
8
|
-
* - Threat intelligence (uses Node.js crypto)
|
|
9
|
-
* - ZIP streaming (uses unzipper, a Node.js stream library)
|
|
10
|
-
* - YARA native bindings
|
|
11
|
-
* - Batch scanner (Node.js-optimised concurrency)
|
|
12
|
-
*
|
|
13
|
-
* For the full Node.js API (all of the above included), import from 'pompelmi'
|
|
14
|
-
* or 'pompelmi/node'.
|
|
15
|
-
*
|
|
16
|
-
* For the React hook, import from 'pompelmi/react'.
|
|
17
|
-
*/
|
|
18
|
-
export { DEFAULT_POLICY, definePolicy } from "./policy";
|
|
19
|
-
export { ARCHIVES, CONSERVATIVE_DEFAULT, DOCUMENTS_ONLY, getPolicyPack, IMAGES_ONLY, POLICY_PACKS, type PolicyPackName, STRICT_PUBLIC_UPLOAD, } from "./policy-packs";
|
|
20
|
-
export { type ComposeScannerOptions, composeScanners, createPresetScanner, type NamedScanner, type PresetName, type PresetOptions, } from "./presets";
|
|
21
|
-
export { type ScanOptions, scanBytes, scanFile, scanFiles } from "./scan";
|
|
22
|
-
export { CommonHeuristicsScanner } from "./scanners/common-heuristics";
|
|
23
|
-
export { createZipBombGuard } from "./scanners/zip-bomb-guard";
|
|
24
|
-
export type { FileInfo, Match, ScanContext, ScanFn, Scanner, ScanReport, Uint8ArrayLike, Verdict, YaraMatch, } from "./types";
|
|
25
|
-
export { analyzeNestedArchives, detectObfuscatedScripts, detectPolyglot, } from "./utils/advanced-detection";
|
|
26
|
-
export { type ExportFormat, type ExportOptions, exportScanResults, ScanResultExporter, } from "./utils/export";
|
|
27
|
-
export { aggregateScanStats, type PerformanceMetrics, PerformanceTracker, type ScanStatistics, } from "./utils/performance-metrics";
|
|
28
|
-
export { validateFile } from "./validate";
|
|
29
|
-
export { mapMatchesToVerdict } from "./verdict";
|