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 analysis;
75pub mod bridge;
76pub mod config;
77pub mod context;
78pub mod coverage;
79pub mod error;
80pub mod nested_wasm;
81pub mod observation;
82pub mod sandbox;
83pub mod streaming;
84pub mod taint;
85pub mod timer;
86pub mod vulnir_producer;
87
88pub use analysis::{AnalysisReport, BehavioralFinding, Category, Severity, TimelineEntry, analyze};
89pub use bridge::{Bridge, CompositeBridge, EmptyBridge, Hook, HookedBridge};
90pub use config::SandboxConfig;
91pub use context::{ContextId, ContextMessage, MessageBus};
92pub use error::{Error, Result};
93pub use observation::{
94 EvidenceDerivation, EvidenceFreshness, EvidenceProvenance, Exploitability, Maliciousness,
95 Observation, RuntimeEvidence, RuntimeEvidenceItem, TaintFlow, TaintLabel, TaintedValue, Value,
96 observations_to_contract_evidence, observations_to_runtime_evidence,
97};
98pub use sandbox::{CompiledModule, ExecutionResult};
99pub use taint::{
100 Severity as TaintSeverity, Sink, Source, TaintTracker, propagate_concat, propagate_json_parse,
101 propagate_json_stringify, propagate_replace, propagate_slice,
102};
103pub mod persistent;
104pub use coverage::{CoverageAccumulator, CoverageReport};
105pub use persistent::PersistentSandbox;
106pub use streaming::{BatchCollector, ControlFlow, CountingSink, EarlyStopSink, ObservationSink};
107pub use vulnir_producer::{JsdetProducer, ToVulnIR, to_vulnir_graph};