jsdet_core/lib.rs
1//! # jsdet — JavaScript Detonation Engine
2//!
3//! Sandboxed JavaScript execution for security analysis.
4//!
5//! ## What it does
6//!
7//! Executes JavaScript in a `QuickJS` engine compiled to WebAssembly,
8//! running inside wasmtime. Every API call is intercepted, observed,
9//! and controllable. Nothing escapes.
10//!
11//! ## How to use it
12//!
13//! ```rust,no_run
14//! use std::sync::Arc;
15//! use jsdet_core::{CompiledModule, SandboxConfig, EmptyBridge};
16//!
17//! let module = CompiledModule::new().unwrap();
18//! let result = module.execute(
19//! &["console.log('hello')".into()],
20//! Arc::new(EmptyBridge),
21//! &SandboxConfig::default(),
22//! ).unwrap();
23//!
24//! for obs in &result.observations {
25//! println!("{obs:?}");
26//! }
27//! ```
28//!
29//! ## Consumers
30//!
31//! - **Sear** (URL detonation): uses `jsdet-browser` bridges for document/window/fetch
32//! - **Soleno** (extension analysis): uses `jsdet-chrome-ext` bridges for chrome.* APIs
33//! - **Your tool**: implement the `Bridge` trait to provide any API surface
34//!
35//! ## Architecture
36//!
37//! ```text
38//! ┌─────────────────────────────────────────────┐
39//! │ Your Rust application │
40//! │ │
41//! │ CompiledModule::execute(scripts, bridge) │
42//! │ │ │
43//! │ ▼ │
44//! │ ┌─────────────────────────────────┐ │
45//! │ │ wasmtime instance │ │
46//! │ │ ┌───────────────────────┐ │ │
47//! │ │ │ QuickJS (WASM) │ │ │
48//! │ │ │ │ │ │
49//! │ │ │ JS calls fetch() ─────┼──────┼──► Bridge::call("fetch", args)
50//! │ │ │ ◄────┼──────┼─── returns fake response
51//! │ │ │ │ │ │
52//! │ │ │ JS calls eval() ──────┼──────┼──► Observation::DynamicCodeExec
53//! │ │ │ │ │ │
54//! │ │ └───────────────────────┘ │ │
55//! │ │ Linear memory: isolated │ │
56//! │ │ Fuel metering: bounded │ │
57//! │ │ Syscalls: zero │ │
58//! │ └─────────────────────────────────┘ │
59//! │ │
60//! │ Vec<Observation> ← what the code DID │
61//! └─────────────────────────────────────────────┘
62//! ```
63
64#![allow(
65 clippy::missing_errors_doc,
66 clippy::must_use_candidate,
67 clippy::cast_possible_truncation,
68 clippy::cast_possible_wrap,
69 clippy::cast_sign_loss,
70 clippy::match_same_arms,
71 clippy::doc_markdown
72)]
73
74pub mod bridge;
75pub mod config;
76pub mod context;
77pub mod coverage;
78pub mod error;
79pub mod nested_wasm;
80pub mod observation;
81pub mod sandbox;
82pub mod streaming;
83pub mod taint;
84pub mod timer;
85pub mod vulnir_producer;
86
87pub use bridge::{Bridge, CompositeBridge, EmptyBridge, Hook, HookedBridge};
88pub use config::SandboxConfig;
89pub use context::{ContextId, ContextMessage, MessageBus};
90pub use error::{Error, Result};
91pub use observation::{Observation, TaintFlow, TaintLabel, TaintedValue, Value};
92pub use sandbox::{CompiledModule, ExecutionResult};
93pub use taint::{
94 Severity, Sink, Source, TaintTracker, propagate_concat, propagate_json_parse,
95 propagate_json_stringify, propagate_replace, propagate_slice,
96};
97pub mod persistent;
98pub use coverage::{CoverageAccumulator, CoverageReport};
99pub use persistent::PersistentSandbox;
100pub use streaming::{BatchCollector, ControlFlow, CountingSink, EarlyStopSink, ObservationSink};
101pub use vulnir_producer::{JsdetProducer, ToVulnIR, to_vulnir_graph};