@mlvscan/wasm-core 1.1.8 → 1.1.9
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
CHANGED
|
@@ -1,19 +1,190 @@
|
|
|
1
1
|
# @mlvscan/wasm-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@mlvscan/wasm-core)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
WebAssembly scanning engine for [MLVScan](https://github.com/ifBars/MLVScan). Runs the full [MLVScan.Core](https://github.com/ifBars/MLVScan.Core) malware detection engine entirely in the browser — no server, no uploads, no tracking.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
```bash
|
|
9
|
-
dotnet publish -c Release
|
|
10
|
-
```
|
|
11
|
-
2. Copy the built `_framework` into this package’s `dist` so the package is self-contained:
|
|
12
|
-
```bash
|
|
13
|
-
npm run copy:framework
|
|
14
|
-
```
|
|
15
|
-
3. Consuming projects (e.g. MLVScan.Web.v2) can depend on this package via `"file:../MLVScan.Core/MLVScan.WASM/npm"` and run `npm install`. The web app will serve and copy `_framework` from `node_modules/@mlvscan/wasm-core/dist/_framework`.
|
|
7
|
+
## Installation
|
|
16
8
|
|
|
17
|
-
|
|
9
|
+
```bash
|
|
10
|
+
npm install @mlvscan/wasm-core
|
|
11
|
+
```
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
## Serving the Framework Files
|
|
14
|
+
|
|
15
|
+
The package ships with a `dist/_framework` directory containing the .NET WASM runtime. **Your build tool must serve these files at runtime.** With Vite, use `vite-plugin-static-copy`:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// vite.config.ts
|
|
19
|
+
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
plugins: [
|
|
23
|
+
viteStaticCopy({
|
|
24
|
+
targets: [{
|
|
25
|
+
src: 'node_modules/@mlvscan/wasm-core/dist/_framework',
|
|
26
|
+
dest: '.'
|
|
27
|
+
}]
|
|
28
|
+
})
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Then initialize with `baseUrl: '/'` (the default).
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { initScanner, scanAssembly } from '@mlvscan/wasm-core'
|
|
39
|
+
|
|
40
|
+
// Initialize once at app startup
|
|
41
|
+
await initScanner({ baseUrl: '/' })
|
|
42
|
+
|
|
43
|
+
// Scan a DLL from a file input
|
|
44
|
+
const file = event.target.files[0]
|
|
45
|
+
const bytes = new Uint8Array(await file.arrayBuffer())
|
|
46
|
+
const result = await scanAssembly(bytes, file.name)
|
|
47
|
+
|
|
48
|
+
console.log(`Found ${result.summary.totalFindings} issue(s)`)
|
|
49
|
+
for (const finding of result.findings) {
|
|
50
|
+
console.log(`[${finding.severity}] ${finding.description} @ ${finding.location}`)
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## API Reference
|
|
55
|
+
|
|
56
|
+
### `initScanner(options?)`
|
|
57
|
+
|
|
58
|
+
Loads the .NET WASM runtime. Call once at app startup before scanning. Safe to call multiple times — subsequent calls are no-ops if already initialized.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
await initScanner({
|
|
62
|
+
baseUrl: '/', // Where _framework is served. Defaults to '/'.
|
|
63
|
+
useMock: false, // Force mock mode (useful for testing). Defaults to false.
|
|
64
|
+
throwOnInitFailure: false // Throw instead of falling back to mock on load failure.
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
If `throwOnInitFailure` is not set and WASM fails to load, the scanner silently falls back to mock mode (returning zero findings). Use `getScannerStatus()` to detect this.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### `scanAssembly(fileBytes, fileName)`
|
|
73
|
+
|
|
74
|
+
Scans a .NET assembly and returns a [`ScanResult`](#scanresult). Auto-initializes if `initScanner` was not called first.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const result = await scanAssembly(bytes, 'MyMod.dll')
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### `scanAssemblyWithConfig(fileBytes, fileName, config)`
|
|
83
|
+
|
|
84
|
+
Scans with explicit options for deeper analysis (call chains, data flows, developer guidance).
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
const result = await scanAssemblyWithConfig(bytes, 'MyMod.dll', {
|
|
88
|
+
developerMode: true,
|
|
89
|
+
enableCrossMethodAnalysis: true,
|
|
90
|
+
deepAnalysis: {
|
|
91
|
+
enableDeepAnalysis: true,
|
|
92
|
+
enableNetworkToExecutionCorrelation: true,
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
### Status & Utility
|
|
100
|
+
|
|
101
|
+
| Function | Returns | Description |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `isScannerReady()` | `boolean` | True when init has completed (real or mock). Use to gate the scan button. |
|
|
104
|
+
| `isMockScanner()` | `boolean` | True when running in mock mode. |
|
|
105
|
+
| `getScannerStatus()` | `ScannerStatus` | Full status snapshot — ready, mock, explicit mock, and init error. |
|
|
106
|
+
| `getScannerVersion()` | `Promise<string>` | Scanner engine version (e.g. `"1.1.7"`). Returns `"1.0.0-mock"` in mock mode. |
|
|
107
|
+
| `getSchemaVersion()` | `Promise<string>` | Result schema version (e.g. `"1.0.0"`). |
|
|
108
|
+
| `getInitError()` | `Error \| null` | The error that caused WASM fallback, or null if healthy. |
|
|
109
|
+
|
|
110
|
+
## Scan Modes
|
|
111
|
+
|
|
112
|
+
The `scanMode` in [`ScanConfigInput`](#scanassemblywithconfig) controls the depth of analysis and what is included in the result:
|
|
113
|
+
|
|
114
|
+
| Mode | Description |
|
|
115
|
+
|---|---|
|
|
116
|
+
| `summary` (default) | Fast scan. Returns findings with severity and location. |
|
|
117
|
+
| `detailed` | Includes `callChains` — the execution path from entry point to suspicious code. |
|
|
118
|
+
| `developer` | Includes `dataFlows` and `developerGuidance` with remediation suggestions. |
|
|
119
|
+
|
|
120
|
+
## Handling WASM Load Failures
|
|
121
|
+
|
|
122
|
+
If the WASM runtime fails to load (e.g. COOP/COEP headers not set, browser incompatibility), the scanner falls back to mock mode automatically. Check the status after init to show an appropriate message:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
await initScanner({ baseUrl: '/' })
|
|
126
|
+
|
|
127
|
+
const status = getScannerStatus()
|
|
128
|
+
if (status.initError) {
|
|
129
|
+
console.warn('Scanner unavailable, results will be empty:', status.initError.message)
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
To throw instead of falling back silently:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
await initScanner({ baseUrl: '/', throwOnInitFailure: true })
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Type Reference
|
|
140
|
+
|
|
141
|
+
### `ScanResult`
|
|
142
|
+
|
|
143
|
+
The root object returned by all scan functions.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
interface ScanResult {
|
|
147
|
+
schemaVersion: string
|
|
148
|
+
metadata: ScanMetadata // Scanner version, timestamp, scan mode, platform
|
|
149
|
+
input: ScanInput // File name, size, optional SHA-256
|
|
150
|
+
summary: ScanSummary // Total findings and counts by severity
|
|
151
|
+
findings: Finding[] // Individual security findings
|
|
152
|
+
callChains?: CallChain[] // Detailed mode: execution paths
|
|
153
|
+
dataFlows?: DataFlowChain[] // Developer mode: source-to-sink data flows
|
|
154
|
+
developerGuidance?: DeveloperGuidance[] // Developer mode: remediation suggestions
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `Finding`
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
interface Finding {
|
|
162
|
+
ruleId?: string
|
|
163
|
+
description: string
|
|
164
|
+
severity: 'Low' | 'Medium' | 'High' | 'Critical'
|
|
165
|
+
location: string // Type/method name or file:line
|
|
166
|
+
codeSnippet?: string
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### `ScannerStatus`
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
interface ScannerStatus {
|
|
174
|
+
ready: boolean
|
|
175
|
+
isMock: boolean
|
|
176
|
+
mockRequestedExplicitly: boolean
|
|
177
|
+
initError: Error | null
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
For the full type definitions, see [`types.ts`](https://github.com/ifBars/MLVScan.Core/blob/main/MLVScan.WASM/npm/src/types.ts).
|
|
182
|
+
|
|
183
|
+
## Related
|
|
184
|
+
|
|
185
|
+
* [MLVScan.Core](https://github.com/ifBars/MLVScan.Core) — The detection engine (NuGet package, CLI, WASM source)
|
|
186
|
+
* [MLVScan.Web](https://github.com/ifBars/MLVScan.Web) — React web app built on this package
|
|
187
|
+
* [MLVScan](https://github.com/ifBars/MLVScan) — MelonLoader/BepInEx plugin
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
*Licensed under GPL-3.0*
|
|
Binary file
|
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mainAssemblyName": "MLVScan.WASM.dll",
|
|
3
3
|
"resources": {
|
|
4
|
-
"hash": "sha256-
|
|
4
|
+
"hash": "sha256-kQ8yXgo/2m62IeBvqmE2y/Rv5qnIhJ76+Mb2sd2UHtk=",
|
|
5
5
|
"jsModuleNative": {
|
|
6
6
|
"dotnet.native.js": "sha256-clxzGaAFwcQ6QWhwQ7dzpD9ktR/87yTache3B45gqoQ="
|
|
7
7
|
},
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"icudt_no_CJK.dat": "sha256-L7sV7NEYP37/Qr2FPCePo5cJqRgTXRwGHuwF5Q+0Nfs="
|
|
21
21
|
},
|
|
22
22
|
"assembly": {
|
|
23
|
-
"MLVScan.Core.wasm": "sha256-
|
|
24
|
-
"MLVScan.WASM.wasm": "sha256-
|
|
23
|
+
"MLVScan.Core.wasm": "sha256-n14Dpe9qxFK9DoeqYdYn3XdOfGlQ8tUR1214rLiCwgc=",
|
|
24
|
+
"MLVScan.WASM.wasm": "sha256-RPRKDzyd235JwUgdRljPx8P2308Dy8hid3msbRu1Azc=",
|
|
25
25
|
"Mono.Cecil.wasm": "sha256-+26bn77S22+aVO+7xKl2WP74xQjSYR0S8GP6mRWf9C8=",
|
|
26
26
|
"System.Collections.Concurrent.wasm": "sha256-pFhCmskR6dmKt18zv1jrGGR184LyXdz408BBMX4BBhg=",
|
|
27
27
|
"System.Collections.wasm": "sha256-TRwwb/PWxTAKfplBNqMkn14z5rNLvuy459MunrnseDo=",
|