jsdet_core/config.rs
1/// Configuration for a single sandbox execution.
2///
3/// Sensible defaults are provided. Zero config for consumers who just want
4/// `execute(scripts)`. Full control for experts.
5#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
6pub struct SandboxConfig {
7 /// Maximum wall-clock execution time in milliseconds.
8 /// Default: 200ms. Enough for most phishing kits.
9 /// Set to 5000ms for complex extension analysis.
10 pub timeout_ms: u64,
11
12 /// Maximum WASM linear memory in bytes.
13 /// Default: 16MB. `QuickJS` needs ~4MB for bootstrap.
14 pub max_memory_bytes: usize,
15
16 /// Maximum fuel (WASM instruction count).
17 /// Default: `100_000_000` (~100ms of execution on modern hardware).
18 /// 0 = unlimited (use timeout only).
19 pub max_fuel: u64,
20
21 /// Maximum observations before the sandbox stops recording.
22 /// Prevents memory exhaustion from observation floods.
23 /// Default: `10_000`.
24 pub max_observations: usize,
25
26 /// Maximum number of scripts to execute per sandbox run.
27 /// Default: 100.
28 pub max_scripts: usize,
29
30 /// Maximum size of a single script in bytes.
31 /// Default: 1MB.
32 pub max_script_bytes: usize,
33
34 /// Maximum combined size of all scripts in bytes.
35 /// Default: 5MB.
36 pub max_total_script_bytes: usize,
37
38 /// Whether to immediately drain all pending timers after script execution.
39 /// When true, setTimeout/setInterval callbacks fire synchronously.
40 /// Default: true (for detonation — you want to trigger delayed payloads).
41 pub drain_timers: bool,
42
43 /// Maximum timer callbacks to drain per execution.
44 /// Default: 50.
45 pub max_timer_drains: usize,
46
47 /// Whether to allow nested WASM instantiation.
48 /// When true, JS `new WebAssembly.Module()` creates a real nested WASM instance.
49 /// When false, it returns a stub that records the attempt but doesn't execute.
50 /// Default: true.
51 pub allow_nested_wasm: bool,
52
53 /// Maximum linear memory for nested WASM instances in bytes.
54 /// Default: 4MB.
55 pub nested_wasm_max_memory: usize,
56
57 /// Maximum fuel for nested WASM instances.
58 /// Default: `10_000_000`.
59 pub nested_wasm_max_fuel: u64,
60}
61
62impl Default for SandboxConfig {
63 fn default() -> Self {
64 Self {
65 timeout_ms: 200,
66 max_memory_bytes: 16 * 1024 * 1024,
67 max_fuel: 100_000_000,
68 max_observations: 10_000,
69 max_scripts: 100,
70 max_script_bytes: 1024 * 1024,
71 max_total_script_bytes: 5 * 1024 * 1024,
72 drain_timers: true,
73 max_timer_drains: 50,
74 // Secure by default — nested WASM disabled. Enable explicitly for extension analysis.
75 allow_nested_wasm: false,
76 nested_wasm_max_memory: 4 * 1024 * 1024,
77 nested_wasm_max_fuel: 10_000_000,
78 }
79 }
80}
81
82impl SandboxConfig {
83 /// Config tuned for fast URL detonation (Sear).
84 /// Low timeouts, drain timers, nested WASM disabled.
85 #[must_use]
86 pub fn detonation() -> Self {
87 Self {
88 timeout_ms: 200,
89 max_fuel: 50_000_000,
90 drain_timers: true,
91 allow_nested_wasm: false,
92 ..Self::default()
93 }
94 }
95
96 /// Config tuned for deep extension analysis (Soleno).
97 /// Higher timeouts, nested WASM enabled, more observations.
98 #[must_use]
99 pub fn extension_analysis() -> Self {
100 Self {
101 timeout_ms: 5000,
102 max_fuel: 500_000_000,
103 max_observations: 50_000,
104 max_scripts: 500,
105 drain_timers: true,
106 allow_nested_wasm: true,
107 ..Self::default()
108 }
109 }
110
111 /// Config for interactive research.
112 /// No fuel limit, high timeouts, everything enabled.
113 #[must_use]
114 pub fn research() -> Self {
115 Self {
116 timeout_ms: 30_000,
117 max_fuel: 0, // unlimited
118 max_observations: 1_000_000,
119 max_scripts: 10_000,
120 max_memory_bytes: 256 * 1024 * 1024,
121 drain_timers: false, // researcher controls timer advancement
122 allow_nested_wasm: true,
123 nested_wasm_max_memory: 64 * 1024 * 1024,
124 nested_wasm_max_fuel: 100_000_000,
125 ..Self::default()
126 }
127 }
128}