windows-exe-decompiler-mcp-server 0.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/CODEX_INSTALLATION.md +69 -0
- package/COPILOT_INSTALLATION.md +77 -0
- package/LICENSE +21 -0
- package/README.md +314 -0
- package/bin/windows-exe-decompiler-mcp-server.js +3 -0
- package/dist/analysis-provenance.d.ts +184 -0
- package/dist/analysis-provenance.js +74 -0
- package/dist/analysis-task-runner.d.ts +31 -0
- package/dist/analysis-task-runner.js +160 -0
- package/dist/artifact-inventory.d.ts +23 -0
- package/dist/artifact-inventory.js +175 -0
- package/dist/cache-manager.d.ts +128 -0
- package/dist/cache-manager.js +454 -0
- package/dist/confidence-semantics.d.ts +66 -0
- package/dist/confidence-semantics.js +122 -0
- package/dist/config.d.ts +335 -0
- package/dist/config.js +193 -0
- package/dist/database.d.ts +227 -0
- package/dist/database.js +601 -0
- package/dist/decompiler-worker.d.ts +441 -0
- package/dist/decompiler-worker.js +1962 -0
- package/dist/dynamic-trace.d.ts +95 -0
- package/dist/dynamic-trace.js +629 -0
- package/dist/env-validator.d.ts +15 -0
- package/dist/env-validator.js +249 -0
- package/dist/error-handler.d.ts +28 -0
- package/dist/error-handler.example.d.ts +22 -0
- package/dist/error-handler.example.js +141 -0
- package/dist/error-handler.js +139 -0
- package/dist/ghidra-analysis-status.d.ts +49 -0
- package/dist/ghidra-analysis-status.js +178 -0
- package/dist/ghidra-config.d.ts +134 -0
- package/dist/ghidra-config.js +464 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +200 -0
- package/dist/job-queue.d.ts +169 -0
- package/dist/job-queue.js +407 -0
- package/dist/logger.d.ts +106 -0
- package/dist/logger.js +176 -0
- package/dist/policy-guard.d.ts +115 -0
- package/dist/policy-guard.js +243 -0
- package/dist/process-output.d.ts +15 -0
- package/dist/process-output.js +90 -0
- package/dist/prompts/function-explanation-review.d.ts +5 -0
- package/dist/prompts/function-explanation-review.js +64 -0
- package/dist/prompts/semantic-name-review.d.ts +5 -0
- package/dist/prompts/semantic-name-review.js +63 -0
- package/dist/runtime-correlation.d.ts +34 -0
- package/dist/runtime-correlation.js +279 -0
- package/dist/runtime-paths.d.ts +3 -0
- package/dist/runtime-paths.js +11 -0
- package/dist/selection-diff.d.ts +667 -0
- package/dist/selection-diff.js +53 -0
- package/dist/semantic-name-suggestion-artifacts.d.ts +116 -0
- package/dist/semantic-name-suggestion-artifacts.js +314 -0
- package/dist/server.d.ts +129 -0
- package/dist/server.js +578 -0
- package/dist/tools/artifact-read.d.ts +235 -0
- package/dist/tools/artifact-read.js +317 -0
- package/dist/tools/artifacts-diff.d.ts +728 -0
- package/dist/tools/artifacts-diff.js +304 -0
- package/dist/tools/artifacts-list.d.ts +515 -0
- package/dist/tools/artifacts-list.js +389 -0
- package/dist/tools/attack-map.d.ts +290 -0
- package/dist/tools/attack-map.js +519 -0
- package/dist/tools/cache-observability.d.ts +4 -0
- package/dist/tools/cache-observability.js +36 -0
- package/dist/tools/code-function-cfg.d.ts +50 -0
- package/dist/tools/code-function-cfg.js +102 -0
- package/dist/tools/code-function-decompile.d.ts +55 -0
- package/dist/tools/code-function-decompile.js +103 -0
- package/dist/tools/code-function-disassemble.d.ts +43 -0
- package/dist/tools/code-function-disassemble.js +185 -0
- package/dist/tools/code-function-explain-apply.d.ts +255 -0
- package/dist/tools/code-function-explain-apply.js +225 -0
- package/dist/tools/code-function-explain-prepare.d.ts +535 -0
- package/dist/tools/code-function-explain-prepare.js +276 -0
- package/dist/tools/code-function-explain-review.d.ts +397 -0
- package/dist/tools/code-function-explain-review.js +589 -0
- package/dist/tools/code-function-rename-apply.d.ts +248 -0
- package/dist/tools/code-function-rename-apply.js +220 -0
- package/dist/tools/code-function-rename-prepare.d.ts +506 -0
- package/dist/tools/code-function-rename-prepare.js +279 -0
- package/dist/tools/code-function-rename-review.d.ts +574 -0
- package/dist/tools/code-function-rename-review.js +761 -0
- package/dist/tools/code-functions-list.d.ts +37 -0
- package/dist/tools/code-functions-list.js +91 -0
- package/dist/tools/code-functions-rank.d.ts +34 -0
- package/dist/tools/code-functions-rank.js +90 -0
- package/dist/tools/code-functions-reconstruct.d.ts +2725 -0
- package/dist/tools/code-functions-reconstruct.js +2807 -0
- package/dist/tools/code-functions-search.d.ts +39 -0
- package/dist/tools/code-functions-search.js +90 -0
- package/dist/tools/code-reconstruct-export.d.ts +1212 -0
- package/dist/tools/code-reconstruct-export.js +4002 -0
- package/dist/tools/code-reconstruct-plan.d.ts +274 -0
- package/dist/tools/code-reconstruct-plan.js +342 -0
- package/dist/tools/dotnet-metadata-extract.d.ts +541 -0
- package/dist/tools/dotnet-metadata-extract.js +355 -0
- package/dist/tools/dotnet-reconstruct-export.d.ts +567 -0
- package/dist/tools/dotnet-reconstruct-export.js +1151 -0
- package/dist/tools/dotnet-types-list.d.ts +325 -0
- package/dist/tools/dotnet-types-list.js +201 -0
- package/dist/tools/dynamic-dependencies.d.ts +115 -0
- package/dist/tools/dynamic-dependencies.js +213 -0
- package/dist/tools/dynamic-memory-import.d.ts +10 -0
- package/dist/tools/dynamic-memory-import.js +567 -0
- package/dist/tools/dynamic-trace-import.d.ts +10 -0
- package/dist/tools/dynamic-trace-import.js +235 -0
- package/dist/tools/entrypoint-fallback-disasm.d.ts +30 -0
- package/dist/tools/entrypoint-fallback-disasm.js +89 -0
- package/dist/tools/ghidra-analyze.d.ts +88 -0
- package/dist/tools/ghidra-analyze.js +208 -0
- package/dist/tools/ghidra-health.d.ts +37 -0
- package/dist/tools/ghidra-health.js +212 -0
- package/dist/tools/ioc-export.d.ts +209 -0
- package/dist/tools/ioc-export.js +542 -0
- package/dist/tools/packer-detect.d.ts +165 -0
- package/dist/tools/packer-detect.js +284 -0
- package/dist/tools/pe-exports-extract.d.ts +175 -0
- package/dist/tools/pe-exports-extract.js +253 -0
- package/dist/tools/pe-fingerprint.d.ts +234 -0
- package/dist/tools/pe-fingerprint.js +269 -0
- package/dist/tools/pe-imports-extract.d.ts +105 -0
- package/dist/tools/pe-imports-extract.js +245 -0
- package/dist/tools/report-generate.d.ts +157 -0
- package/dist/tools/report-generate.js +457 -0
- package/dist/tools/report-summarize.d.ts +2131 -0
- package/dist/tools/report-summarize.js +596 -0
- package/dist/tools/runtime-detect.d.ts +135 -0
- package/dist/tools/runtime-detect.js +247 -0
- package/dist/tools/sample-ingest.d.ts +94 -0
- package/dist/tools/sample-ingest.js +327 -0
- package/dist/tools/sample-profile-get.d.ts +183 -0
- package/dist/tools/sample-profile-get.js +121 -0
- package/dist/tools/sandbox-execute.d.ts +441 -0
- package/dist/tools/sandbox-execute.js +392 -0
- package/dist/tools/strings-extract.d.ts +375 -0
- package/dist/tools/strings-extract.js +314 -0
- package/dist/tools/strings-floss-decode.d.ts +143 -0
- package/dist/tools/strings-floss-decode.js +259 -0
- package/dist/tools/system-health.d.ts +434 -0
- package/dist/tools/system-health.js +446 -0
- package/dist/tools/task-cancel.d.ts +21 -0
- package/dist/tools/task-cancel.js +70 -0
- package/dist/tools/task-status.d.ts +27 -0
- package/dist/tools/task-status.js +106 -0
- package/dist/tools/task-sweep.d.ts +22 -0
- package/dist/tools/task-sweep.js +77 -0
- package/dist/tools/tool-help.d.ts +340 -0
- package/dist/tools/tool-help.js +261 -0
- package/dist/tools/yara-scan.d.ts +554 -0
- package/dist/tools/yara-scan.js +313 -0
- package/dist/types.d.ts +266 -0
- package/dist/types.js +41 -0
- package/dist/worker-pool.d.ts +204 -0
- package/dist/worker-pool.js +650 -0
- package/dist/workflows/deep-static.d.ts +104 -0
- package/dist/workflows/deep-static.js +276 -0
- package/dist/workflows/function-explanation-review.d.ts +655 -0
- package/dist/workflows/function-explanation-review.js +440 -0
- package/dist/workflows/reconstruct.d.ts +2053 -0
- package/dist/workflows/reconstruct.js +666 -0
- package/dist/workflows/semantic-name-review.d.ts +2418 -0
- package/dist/workflows/semantic-name-review.js +521 -0
- package/dist/workflows/triage.d.ts +659 -0
- package/dist/workflows/triage.js +1374 -0
- package/dist/workspace-manager.d.ts +150 -0
- package/dist/workspace-manager.js +411 -0
- package/ghidra_scripts/DecompileFunction.java +487 -0
- package/ghidra_scripts/DecompileFunction.py +150 -0
- package/ghidra_scripts/ExtractCFG.java +256 -0
- package/ghidra_scripts/ExtractCFG.py +233 -0
- package/ghidra_scripts/ExtractFunctions.java +442 -0
- package/ghidra_scripts/ExtractFunctions.py +101 -0
- package/ghidra_scripts/README.md +125 -0
- package/ghidra_scripts/SearchFunctionReferences.java +380 -0
- package/helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj +9 -0
- package/helpers/DotNetMetadataProbe/Program.cs +566 -0
- package/install-to-codex.ps1 +178 -0
- package/install-to-copilot.ps1 +303 -0
- package/package.json +101 -0
- package/requirements.txt +9 -0
- package/workers/requirements-dynamic.txt +11 -0
- package/workers/requirements.txt +8 -0
- package/workers/speakeasy_compat.py +175 -0
- package/workers/static_worker.py +5183 -0
- package/workers/yara_rules/default.yar +33 -0
- package/workers/yara_rules/malware_families.yar +93 -0
- package/workers/yara_rules/packers.yar +80 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sandbox.execute tool
|
|
3
|
+
* Dynamic-analysis execution entrypoint supporting simulation-first and Speakeasy user-mode emulation.
|
|
4
|
+
*/
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
import fs from 'fs/promises';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { createHash, randomUUID } from 'crypto';
|
|
9
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { normalizeDynamicTraceArtifactPayload } from '../dynamic-trace.js';
|
|
12
|
+
import { resolvePackagePath } from '../runtime-paths.js';
|
|
13
|
+
const TOOL_NAME = 'sandbox.execute';
|
|
14
|
+
const TOOL_VERSION = '0.1.0';
|
|
15
|
+
export const SandboxExecuteInputSchema = z.object({
|
|
16
|
+
sample_id: z.string().describe('Sample ID (format: sha256:<hex>)'),
|
|
17
|
+
mode: z
|
|
18
|
+
.enum(['safe_simulation', 'memory_guided', 'speakeasy', 'live_local'])
|
|
19
|
+
.optional()
|
|
20
|
+
.default('safe_simulation')
|
|
21
|
+
.describe('Dynamic analysis backend mode'),
|
|
22
|
+
timeout_sec: z.number().int().min(5).max(180).optional().default(20),
|
|
23
|
+
network: z
|
|
24
|
+
.enum(['disabled', 'fake', 'enabled'])
|
|
25
|
+
.optional()
|
|
26
|
+
.default('disabled')
|
|
27
|
+
.describe('Network policy for dynamic run'),
|
|
28
|
+
max_scan_bytes: z
|
|
29
|
+
.number()
|
|
30
|
+
.int()
|
|
31
|
+
.min(256 * 1024)
|
|
32
|
+
.max(20 * 1024 * 1024)
|
|
33
|
+
.optional()
|
|
34
|
+
.default(5 * 1024 * 1024)
|
|
35
|
+
.describe('Simulation scan window for fast behavioral extraction'),
|
|
36
|
+
approved: z
|
|
37
|
+
.boolean()
|
|
38
|
+
.optional()
|
|
39
|
+
.default(false)
|
|
40
|
+
.describe('Explicit approval flag required by PolicyGuard'),
|
|
41
|
+
require_user_approval: z
|
|
42
|
+
.boolean()
|
|
43
|
+
.optional()
|
|
44
|
+
.default(false)
|
|
45
|
+
.describe('Compatibility approval flag accepted by PolicyGuard'),
|
|
46
|
+
persist_artifact: z
|
|
47
|
+
.boolean()
|
|
48
|
+
.optional()
|
|
49
|
+
.default(true)
|
|
50
|
+
.describe('Persist sandbox run result as report artifact'),
|
|
51
|
+
});
|
|
52
|
+
const TimelineEventSchema = z.object({
|
|
53
|
+
event_type: z.string(),
|
|
54
|
+
category: z.string(),
|
|
55
|
+
indicator: z.string(),
|
|
56
|
+
confidence: z.number(),
|
|
57
|
+
});
|
|
58
|
+
const CapabilitySchema = z.object({
|
|
59
|
+
name: z.string(),
|
|
60
|
+
evidence_count: z.number(),
|
|
61
|
+
confidence: z.number(),
|
|
62
|
+
});
|
|
63
|
+
const MemoryRegionSchema = z.object({
|
|
64
|
+
region_type: z.string(),
|
|
65
|
+
purpose: z.string(),
|
|
66
|
+
source: z.string(),
|
|
67
|
+
confidence: z.number(),
|
|
68
|
+
start_offset: z.number().int().nonnegative().optional(),
|
|
69
|
+
end_offset: z.number().int().nonnegative().optional(),
|
|
70
|
+
indicators: z.array(z.string()),
|
|
71
|
+
});
|
|
72
|
+
const APIResolutionSchema = z.object({
|
|
73
|
+
api: z.string(),
|
|
74
|
+
provenance: z.string(),
|
|
75
|
+
confidence: z.number(),
|
|
76
|
+
sources: z.array(z.string()),
|
|
77
|
+
});
|
|
78
|
+
const ExecutionHypothesisSchema = z.object({
|
|
79
|
+
stage: z.string(),
|
|
80
|
+
description: z.string(),
|
|
81
|
+
source: z.string(),
|
|
82
|
+
confidence: z.number(),
|
|
83
|
+
indicators: z.array(z.string()),
|
|
84
|
+
});
|
|
85
|
+
export const SandboxExecuteOutputSchema = z.object({
|
|
86
|
+
ok: z.boolean(),
|
|
87
|
+
data: z
|
|
88
|
+
.object({
|
|
89
|
+
run_id: z.string(),
|
|
90
|
+
status: z.enum(['completed', 'failed', 'timeout', 'denied']),
|
|
91
|
+
mode: z.string(),
|
|
92
|
+
backend: z.string(),
|
|
93
|
+
simulated: z.boolean(),
|
|
94
|
+
timeout_sec: z.number(),
|
|
95
|
+
event_count: z.number(),
|
|
96
|
+
timeline: z.array(TimelineEventSchema),
|
|
97
|
+
iocs: z.record(z.array(z.string())),
|
|
98
|
+
capabilities: z.array(CapabilitySchema),
|
|
99
|
+
memory_regions: z.array(MemoryRegionSchema).optional(),
|
|
100
|
+
api_resolution: z.array(APIResolutionSchema).optional(),
|
|
101
|
+
execution_hypotheses: z.array(ExecutionHypothesisSchema).optional(),
|
|
102
|
+
risk: z.object({
|
|
103
|
+
score: z.number(),
|
|
104
|
+
level: z.enum(['clean', 'low', 'medium', 'high']),
|
|
105
|
+
confidence: z.number(),
|
|
106
|
+
}),
|
|
107
|
+
environment: z.object({
|
|
108
|
+
network_policy: z.string(),
|
|
109
|
+
executed: z.boolean(),
|
|
110
|
+
isolation: z.string(),
|
|
111
|
+
}),
|
|
112
|
+
evidence: z.record(z.any()),
|
|
113
|
+
inference: z.object({
|
|
114
|
+
classification: z.string(),
|
|
115
|
+
summary: z.string(),
|
|
116
|
+
}),
|
|
117
|
+
})
|
|
118
|
+
.optional(),
|
|
119
|
+
warnings: z.array(z.string()).optional(),
|
|
120
|
+
errors: z.array(z.string()).optional(),
|
|
121
|
+
artifacts: z.array(z.any()).optional(),
|
|
122
|
+
metrics: z
|
|
123
|
+
.object({
|
|
124
|
+
elapsed_ms: z.number(),
|
|
125
|
+
tool: z.string(),
|
|
126
|
+
})
|
|
127
|
+
.optional(),
|
|
128
|
+
});
|
|
129
|
+
export const sandboxExecuteToolDefinition = {
|
|
130
|
+
name: TOOL_NAME,
|
|
131
|
+
description: 'Execute dynamic-analysis workflow in safe simulation mode (default), memory-guided mode, or Speakeasy user-mode emulation and return timeline/IOC/risk outputs.',
|
|
132
|
+
inputSchema: SandboxExecuteInputSchema,
|
|
133
|
+
outputSchema: SandboxExecuteOutputSchema,
|
|
134
|
+
};
|
|
135
|
+
async function callStaticWorker(request) {
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
const workerPath = resolvePackagePath('workers', 'static_worker.py');
|
|
138
|
+
const pythonCommand = process.platform === 'win32' ? 'python' : 'python3';
|
|
139
|
+
const child = spawn(pythonCommand, [workerPath], {
|
|
140
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
141
|
+
});
|
|
142
|
+
let stdout = '';
|
|
143
|
+
let stderr = '';
|
|
144
|
+
child.stdout.on('data', (data) => {
|
|
145
|
+
stdout += data.toString();
|
|
146
|
+
});
|
|
147
|
+
child.stderr.on('data', (data) => {
|
|
148
|
+
stderr += data.toString();
|
|
149
|
+
});
|
|
150
|
+
child.on('error', (error) => {
|
|
151
|
+
reject(new Error(`Failed to spawn Python worker: ${error.message}`));
|
|
152
|
+
});
|
|
153
|
+
child.on('close', (code) => {
|
|
154
|
+
if (code !== 0) {
|
|
155
|
+
reject(new Error(`Python worker exited with code ${code}. stderr: ${stderr}`));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const lines = stdout.trim().split('\n');
|
|
160
|
+
const lastLine = lines[lines.length - 1];
|
|
161
|
+
resolve(JSON.parse(lastLine));
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
reject(new Error(`Failed to parse worker response: ${error.message}. stdout: ${stdout}`));
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
try {
|
|
168
|
+
child.stdin.write(JSON.stringify(request) + '\n');
|
|
169
|
+
child.stdin.end();
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
reject(new Error(`Failed to write to worker stdin: ${error.message}`));
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function mergeWarnings(...warningLists) {
|
|
177
|
+
const merged = warningLists.flatMap((list) => list || []);
|
|
178
|
+
if (merged.length === 0) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
return Array.from(new Set(merged));
|
|
182
|
+
}
|
|
183
|
+
export function createSandboxExecuteHandler(workspaceManager, database, policyGuard) {
|
|
184
|
+
return async (args) => {
|
|
185
|
+
const startTime = Date.now();
|
|
186
|
+
try {
|
|
187
|
+
const input = SandboxExecuteInputSchema.parse(args);
|
|
188
|
+
const sample = database.findSample(input.sample_id);
|
|
189
|
+
if (!sample) {
|
|
190
|
+
return {
|
|
191
|
+
ok: false,
|
|
192
|
+
errors: [`Sample not found: ${input.sample_id}`],
|
|
193
|
+
metrics: {
|
|
194
|
+
elapsed_ms: Date.now() - startTime,
|
|
195
|
+
tool: TOOL_NAME,
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const policyDecision = await policyGuard.checkPermission({
|
|
200
|
+
type: 'dynamic_execution',
|
|
201
|
+
tool: TOOL_NAME,
|
|
202
|
+
args: {
|
|
203
|
+
mode: input.mode,
|
|
204
|
+
network: input.network,
|
|
205
|
+
approved: input.approved,
|
|
206
|
+
require_user_approval: input.require_user_approval,
|
|
207
|
+
},
|
|
208
|
+
}, {
|
|
209
|
+
sampleId: input.sample_id,
|
|
210
|
+
timestamp: new Date().toISOString(),
|
|
211
|
+
});
|
|
212
|
+
await policyGuard.auditLog({
|
|
213
|
+
timestamp: new Date().toISOString(),
|
|
214
|
+
operation: TOOL_NAME,
|
|
215
|
+
sampleId: input.sample_id,
|
|
216
|
+
decision: policyDecision.allowed ? 'allow' : 'deny',
|
|
217
|
+
reason: policyDecision.reason,
|
|
218
|
+
metadata: {
|
|
219
|
+
mode: input.mode,
|
|
220
|
+
network: input.network,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
if (!policyDecision.allowed) {
|
|
224
|
+
const approvalHint = policyDecision.requiresApproval
|
|
225
|
+
? 'Set `approved=true` (and run only in isolated environment) to continue.'
|
|
226
|
+
: undefined;
|
|
227
|
+
return {
|
|
228
|
+
ok: false,
|
|
229
|
+
errors: [policyDecision.reason || 'Dynamic execution denied by policy guard.'],
|
|
230
|
+
warnings: approvalHint ? [approvalHint] : undefined,
|
|
231
|
+
metrics: {
|
|
232
|
+
elapsed_ms: Date.now() - startTime,
|
|
233
|
+
tool: TOOL_NAME,
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
const workspace = await workspaceManager.getWorkspace(input.sample_id);
|
|
238
|
+
const files = await fs.readdir(workspace.original);
|
|
239
|
+
if (files.length === 0) {
|
|
240
|
+
return {
|
|
241
|
+
ok: false,
|
|
242
|
+
errors: ['Sample file not found in workspace/original'],
|
|
243
|
+
metrics: {
|
|
244
|
+
elapsed_ms: Date.now() - startTime,
|
|
245
|
+
tool: TOOL_NAME,
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
const samplePath = path.join(workspace.original, files[0]);
|
|
250
|
+
const request = {
|
|
251
|
+
job_id: uuidv4(),
|
|
252
|
+
tool: TOOL_NAME,
|
|
253
|
+
sample: {
|
|
254
|
+
sample_id: input.sample_id,
|
|
255
|
+
path: samplePath,
|
|
256
|
+
},
|
|
257
|
+
args: {
|
|
258
|
+
mode: input.mode,
|
|
259
|
+
timeout_sec: input.timeout_sec,
|
|
260
|
+
network: input.network,
|
|
261
|
+
max_scan_bytes: input.max_scan_bytes,
|
|
262
|
+
},
|
|
263
|
+
context: {
|
|
264
|
+
request_time_utc: new Date().toISOString(),
|
|
265
|
+
policy: {
|
|
266
|
+
allow_dynamic: true,
|
|
267
|
+
allow_network: input.network !== 'disabled',
|
|
268
|
+
},
|
|
269
|
+
versions: {
|
|
270
|
+
tool_version: TOOL_VERSION,
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
const workerResponse = await callStaticWorker(request);
|
|
275
|
+
if (!workerResponse.ok) {
|
|
276
|
+
return {
|
|
277
|
+
ok: false,
|
|
278
|
+
errors: workerResponse.errors,
|
|
279
|
+
warnings: workerResponse.warnings,
|
|
280
|
+
metrics: {
|
|
281
|
+
...workerResponse.metrics,
|
|
282
|
+
elapsed_ms: Date.now() - startTime,
|
|
283
|
+
tool: TOOL_NAME,
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
const payload = workerResponse.data;
|
|
288
|
+
const artifacts = workerResponse.artifacts;
|
|
289
|
+
const persistedArtifacts = [];
|
|
290
|
+
if (input.persist_artifact) {
|
|
291
|
+
const reportDir = path.join(workspace.reports, 'dynamic');
|
|
292
|
+
await fs.mkdir(reportDir, { recursive: true });
|
|
293
|
+
const persistTimestamp = Date.now();
|
|
294
|
+
const fileName = `sandbox_${persistTimestamp}.json`;
|
|
295
|
+
const absPath = path.join(reportDir, fileName);
|
|
296
|
+
const serialized = JSON.stringify(payload, null, 2);
|
|
297
|
+
await fs.writeFile(absPath, serialized, 'utf-8');
|
|
298
|
+
const artifactId = randomUUID();
|
|
299
|
+
const artifactSha256 = createHash('sha256').update(serialized).digest('hex');
|
|
300
|
+
const relativePath = `reports/dynamic/${fileName}`;
|
|
301
|
+
database.insertArtifact({
|
|
302
|
+
id: artifactId,
|
|
303
|
+
sample_id: input.sample_id,
|
|
304
|
+
type: 'sandbox_trace_json',
|
|
305
|
+
path: relativePath,
|
|
306
|
+
sha256: artifactSha256,
|
|
307
|
+
mime: 'application/json',
|
|
308
|
+
created_at: new Date().toISOString(),
|
|
309
|
+
});
|
|
310
|
+
const persistedArtifact = {
|
|
311
|
+
id: artifactId,
|
|
312
|
+
type: 'sandbox_trace_json',
|
|
313
|
+
path: relativePath,
|
|
314
|
+
sha256: artifactSha256,
|
|
315
|
+
mime: 'application/json',
|
|
316
|
+
};
|
|
317
|
+
persistedArtifacts.push(persistedArtifact);
|
|
318
|
+
artifacts.push(persistedArtifact);
|
|
319
|
+
const normalizedTrace = normalizeDynamicTraceArtifactPayload(payload);
|
|
320
|
+
if (normalizedTrace) {
|
|
321
|
+
const normalizedFileName = `dynamic_trace_${persistTimestamp}.json`;
|
|
322
|
+
const normalizedAbsPath = path.join(reportDir, normalizedFileName);
|
|
323
|
+
const normalizedSerialized = JSON.stringify(normalizedTrace, null, 2);
|
|
324
|
+
await fs.writeFile(normalizedAbsPath, normalizedSerialized, 'utf-8');
|
|
325
|
+
const normalizedArtifactId = randomUUID();
|
|
326
|
+
const normalizedSha256 = createHash('sha256').update(normalizedSerialized).digest('hex');
|
|
327
|
+
const normalizedRelativePath = `reports/dynamic/${normalizedFileName}`;
|
|
328
|
+
database.insertArtifact({
|
|
329
|
+
id: normalizedArtifactId,
|
|
330
|
+
sample_id: input.sample_id,
|
|
331
|
+
type: 'dynamic_trace_json',
|
|
332
|
+
path: normalizedRelativePath,
|
|
333
|
+
sha256: normalizedSha256,
|
|
334
|
+
mime: 'application/json',
|
|
335
|
+
created_at: new Date().toISOString(),
|
|
336
|
+
});
|
|
337
|
+
const normalizedArtifact = {
|
|
338
|
+
id: normalizedArtifactId,
|
|
339
|
+
type: 'dynamic_trace_json',
|
|
340
|
+
path: normalizedRelativePath,
|
|
341
|
+
sha256: normalizedSha256,
|
|
342
|
+
mime: 'application/json',
|
|
343
|
+
};
|
|
344
|
+
persistedArtifacts.push(normalizedArtifact);
|
|
345
|
+
artifacts.push(normalizedArtifact);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const warnings = mergeWarnings(workerResponse.warnings, payload.warnings);
|
|
349
|
+
if (persistedArtifacts.length > 0) {
|
|
350
|
+
const persistedWarning = `Sandbox trace persisted as artifact(s) ${persistedArtifacts
|
|
351
|
+
.map((item) => `${item.type}:${item.id}`)
|
|
352
|
+
.join(', ')}`;
|
|
353
|
+
const merged = warnings ? [...warnings, persistedWarning] : [persistedWarning];
|
|
354
|
+
return {
|
|
355
|
+
ok: true,
|
|
356
|
+
data: payload,
|
|
357
|
+
warnings: Array.from(new Set(merged)),
|
|
358
|
+
artifacts,
|
|
359
|
+
metrics: {
|
|
360
|
+
...workerResponse.metrics,
|
|
361
|
+
...(payload.metrics || {}),
|
|
362
|
+
elapsed_ms: Date.now() - startTime,
|
|
363
|
+
tool: TOOL_NAME,
|
|
364
|
+
},
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
ok: true,
|
|
369
|
+
data: payload,
|
|
370
|
+
warnings,
|
|
371
|
+
artifacts,
|
|
372
|
+
metrics: {
|
|
373
|
+
...workerResponse.metrics,
|
|
374
|
+
...(payload.metrics || {}),
|
|
375
|
+
elapsed_ms: Date.now() - startTime,
|
|
376
|
+
tool: TOOL_NAME,
|
|
377
|
+
},
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
return {
|
|
382
|
+
ok: false,
|
|
383
|
+
errors: [error.message],
|
|
384
|
+
metrics: {
|
|
385
|
+
elapsed_ms: Date.now() - startTime,
|
|
386
|
+
tool: TOOL_NAME,
|
|
387
|
+
},
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=sandbox-execute.js.map
|