Skip to main content

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};