# Kalamari
[](https://github.com/bountyyfi/kalamari/actions/workflows/ci.yml)
[](https://github.com/bountyyfi/kalamari/actions/workflows/release.yml)
[](https://crates.io/crates/kalamari)
[](https://docs.rs/kalamari)
[](LICENSE)
**Lightweight Headless Browser for Security Testing**
---
## What is Kalamari?
Kalamari is a pure Rust headless browser designed specifically for XSS scanning, web crawling, and security testing. Unlike traditional headless browsers that require Chrome/Chromium binaries (~200MB+), Kalamari is entirely self-contained with minimal dependencies.
Built as a drop-in replacement for Chrome headless in security scanners like [Lonkero](https://github.com/bountyyfi/lonkero).
## Features
### Core Browser
- **Lightweight** - ~10MB binary vs Chrome's 200MB+ footprint
- **Fast Startup** - No browser process to spawn, instant initialization
- **Full DOM API** - createElement, MutationObserver, localStorage, sessionStorage
- **Cookie Management** - Complete cookie jar with domain scoping and auth tokens
- **Network Interception** - CDP-like request/response capture with middleware chain
### Security Testing
- **XSS Detection** - Built-in alert/confirm/prompt/eval interception
- **Stored XSS Flow** - Complete stored XSS detection with form submission
- **CSP Analysis** - Parse Content-Security-Policy, identify bypasses
- **DOM Clobbering** - Detect clobbering vectors and form hijacking
- **SRI Checking** - Identify missing/weak subresource integrity
### Framework Support
- **SPA Route Detection** - Extract routes from Vue, React, Angular bundles
- **WebSocket Discovery** - Find WebSocket endpoints in JavaScript
- **Framework Detectors** - Identify v-html, dangerouslySetInnerHTML, ng-bind-html sinks
### Performance
- **Browser Pool** - Parallel scanning with page pooling
- **Metrics Collection** - Request latencies, page counts, XSS triggers
- **Real Timer Queue** - Production-grade setTimeout/setInterval with unique IDs, clearTimeout/clearInterval, and flush_timers() for async JS control
- **Console Capture** - Real console.log/error/warn/info/debug capture for debugging
## Lonkero Integration
Kalamari addresses all key integration requirements for Lonkero:
| Binary size | ~200MB | ~10MB |
| Memory/page | ~100-300MB | ~10-20MB |
| Startup time | 1-3s | Instant |
| XSS detection | External | Built-in |
| Request interception | CDP Fetch | `RequestInterceptor` trait |
| Iframe support | Native | Recursive processing |
| MutationObserver | Native | JS stub |
| PDF generation | Native | Feature-gated |
| Auth session | Manual | `AuthSession` extractor |
| SPA routes | Manual | `ScriptAnalyzer` |
| WebSocket discovery | Manual | `ScriptAnalyzer` |
| Timer control | Native | `TimerQueue` |
| CSP analysis | Manual | `CspAnalyzer` |
| Parallel scanning | Thread pool | `BrowserPool` |
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
kalamari = "0.1"
# With optional features
kalamari = { version = "0.1", features = ["pdf", "websocket"] }
```
Or install the CLI:
```bash
cargo install kalamari
```
## Quick Start
### Basic Usage
```rust
use kalamari::{Browser, BrowserConfig, PageConfig};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let browser = Browser::launch().await?;
let page = browser.new_page().await?;
page.navigate("https://example.com").await?;
println!("Title: {:?}", page.title());
for link in page.links() {
println!("Link: {}", link);
}
Ok(())
}
```
### XSS Scanning
```rust
use kalamari::{Browser, PageConfig, XssTriggerType};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let browser = Browser::for_security_scanning().await?;
let page = browser.new_page_with_config(PageConfig::for_xss_scanning()).await?;
page.navigate("https://target.com/search?q=<script>alert(1)</script>").await?;
let result = page.analyze_xss();
for trigger in result.triggers {
if trigger.is_confirmed() {
println!("CONFIRMED XSS: {:?} - {}", trigger.trigger_type, trigger.payload);
}
}
Ok(())
}
```
### Stored XSS Detection
```rust
use kalamari::{StoredXssTest, StoredXssTester};
let test = StoredXssTest::new("https://example.com/post", "<script>alert(1)</script>")
.field("comment")
.reflect_at("https://example.com/posts")
.reflect_at("https://example.com/profile");
let tester = StoredXssTester::new();
// Execute test via page methods
```
### CSP Analysis
```rust
use kalamari::{CspAnalyzer, CspBypass};
let analyzer = CspAnalyzer::new();
let csp = "default-src 'self'; script-src 'self' 'unsafe-inline'";
let analysis = analyzer.parse(csp);
println!("Security Score: {}/100", analysis.security_score);
println!("Blocks inline: {}", analysis.blocks_inline);
for bypass in &analysis.bypasses {
println!("Bypass: {:?} - {}", bypass, bypass.description());
}
```
### Parallel Scanning with Browser Pool
```rust
use kalamari::BrowserPool;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let pool = BrowserPool::new(8).await?; // 8 browsers
let urls = vec![
"https://example.com/page1".to_string(),
"https://example.com/page2".to_string(),
"https://example.com/page3".to_string(),
];
let results = pool.map(&urls, |page, url| async move {
page.navigate(&url).await?;
Ok(page.analyze_xss())
}).await;
for result in results {
if let Ok(xss) = result {
if xss.is_vulnerable() {
println!("XSS found!");
}
}
}
Ok(())
}
```
### Request Interception
```rust
use kalamari::{Browser, RequestInterceptor, InterceptAction, AuthHeaderInjector};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let browser = Browser::launch().await?;
// Use built-in auth injector
let auth = AuthHeaderInjector::new()
.bearer_token("your-jwt-token")
.header("x-api-key", "secret");
// Or set directly on browser
browser.set_auth_token("your-jwt-token");
Ok(())
}
```
### Auth Session Extraction
```rust
use kalamari::{Browser, AuthSession};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let browser = Browser::launch().await?;
let page = browser.new_page().await?;
page.navigate("https://example.com/login").await?;
// ... perform login ...
let session = page.extract_auth_session();
println!("Session ID: {:?}", session.session_id);
println!("Bearer Token: {:?}", session.bearer_token);
println!("CSRF Token: {:?}", session.csrf_token);
println!("Authenticated: {}", session.is_authenticated);
Ok(())
}
```
### SPA Route Detection
```rust
use kalamari::{ScriptAnalyzer, ScriptSource};
let analyzer = ScriptAnalyzer::new();
let scripts = page.get_script_sources();
for script in &scripts {
// Find routes
let routes = analyzer.find_routes(script);
for route in routes {
println!("Route: {} (auth: {})", route.path, route.requires_auth);
}
// Find WebSocket endpoints
let ws_endpoints = analyzer.find_websocket_endpoints(script);
for endpoint in ws_endpoints {
println!("WebSocket: {}", endpoint.url);
}
}
```
### Framework Detection
```rust
use kalamari::FrameworkDetector;
let detector = FrameworkDetector::new();
let html = page.content()?;
let scripts = page.get_script_sources();
let script_contents: Vec<String> = scripts.iter().map(|s| s.content.clone()).collect();
let frameworks = detector.detect_all(&html, &script_contents);
for fw in frameworks {
println!("Framework: {:?} {:?}", fw.framework, fw.version);
for sink in fw.sinks {
println!(" Sink: {} (risk: {})", sink.name, sink.risk);
}
}
```
## CLI Usage
```bash
# Fetch a URL and display info
kalamari fetch https://example.com
# Check for XSS vulnerabilities
kalamari xss "https://example.com/search?q=<script>alert(1)</script>"
# Crawl a website
kalamari crawl https://example.com
# Extract forms
kalamari forms https://example.com/login
```
## Architecture
```
┌──────────────────────────────────────────────────────────────┐
│ KALAMARI BROWSER │
├──────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ HTTP Layer │ │ DOM Engine │ │ JS Runtime │ │
│ │ (reqwest) │──│ (html5ever) │──│ (boa_engine) │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
│ │ │ │ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Interceptor │ │ Iframe │ │ XSS Detection │ │
│ │ Chain │ │ Handler │ │ (alert hooks) │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
│ │ │ │ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Cookie │ │ Form │ │ Security │ │
│ │ Jar │ │ Extractor │ │ (CSP, SRI) │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
└──────────────────────────────────────────────────────────────┘
```
## API Reference
### Browser Module
| `Browser` | Main browser instance |
| `Page` | Individual page/tab |
| `BrowserPool` | Pool for parallel scanning |
| `BrowserMetrics` | Performance metrics |
### Security Module
| `CspAnalyzer` | CSP parsing and bypass detection |
| `SriChecker` | Subresource integrity validation |
| `DomClobberDetector` | DOM clobbering detection |
### XSS Module
| `XssDetector` | XSS trigger detection |
| `StoredXssTest` | Stored XSS test configuration |
| `PayloadGenerator` | XSS payload generation |
### Network Module
| `RequestInterceptor` | Request/response middleware |
| `NetworkEvent` | Captured network events |
| `AuthHeaderInjector` | Auth header injection |
## Feature Flags
| `default` | Core functionality | None |
| `websocket` | WebSocket support | tokio-tungstenite |
| `pdf` | PDF generation (pure Rust) | printpdf |
| `full` | All features | All above |
## Dependencies
| `boa_engine` | JavaScript execution (pure Rust) |
| `html5ever` | HTML parsing (spec-compliant) |
| `reqwest` | HTTP client (rustls TLS) |
| `tokio` | Async runtime |
## Limitations
Kalamari is optimized for security testing, not full browser emulation:
- **No visual rendering** - CSS layout/painting not implemented
- **No WebGL/Canvas** - Graphics APIs not supported
- **Timer execution** - setTimeout/setInterval use real TimerQueue with unique IDs; use `flush_timers()` or `execute_ready_timers()` to execute
- **No plugins** - Flash, PDF viewer, etc. not supported
## License
Copyright (c) 2026 Bountyy Oy. All rights reserved.
This software is licensed under the Bountyy Oy Source-Available License. You may view, study, and use the software for personal, non-commercial purposes. Commercial use requires a separate license agreement.
See [LICENSE](LICENSE) for full terms. For licensing inquiries: info@bountyy.fi
## Links
- [Lonkero Security Scanner](https://github.com/bountyyfi/lonkero)
- [Bountyy](https://bountyy.fi)