stemedb/docs/demo/vulnbank/rust/src/auth.rs
jordan b3e8a9a058 feat: Multi-application expansion with chaos testing and community UI
Major additions:
- Community Next.js app (port 18187) for browsing claims with API docs
- stemedb-chaos crate: Fault injection, chaos testing, CRDT properties
- Latent ingestion system: Reddit/FDA ingesters with ADK-Go agents
- Disputed claims handling: Manual review workflows and validation
- Aphoria security scanner: New extractors (SQL injection, command
  injection, weak crypto, TLS version), policy-based ignores, UAT reports
- Docker infrastructure: Dockerfile, docker-compose.yml for full stack
- VulnBank demo: Intentionally vulnerable multi-language test corpus

SDK & API enhancements:
- Source registry handlers for tracking data provenance
- Metrics endpoint
- Skeptic filtering improvements

Code quality:
- Split 14 large files (>500 lines) into focused modules
- All files now under 500-line limit per project guidelines

Documentation:
- Chaos testing guide, circuit breakers, observability docs
- Phase 7 UAT documentation updates
- Martin Kleppmann technical writer agent

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 01:24:14 -07:00

76 lines
2.6 KiB
Rust

//! JWT Authentication - Contains intentional vulnerabilities
//!
//! Vulnerabilities:
//! - Audience validation disabled
//! - Algorithm::None allowed
//! - Insecure decode without verification
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
pub sub: String,
pub exp: usize,
pub aud: String,
}
/// VULNERABILITY: Audience validation disabled
/// RFC 7519 requires audience validation to prevent token misuse
pub fn verify_token_no_aud(token: &str, secret: &[u8]) -> Result<Claims, String> {
let mut validation = Validation::new(Algorithm::HS256);
// BLOCK: JWT audience validation disabled - tokens can be replayed across services
validation.validate_aud = false;
decode::<Claims>(token, &DecodingKey::from_secret(secret), &validation)
.map(|data| data.claims)
.map_err(|e| e.to_string())
}
/// VULNERABILITY: Algorithm::None allows unsigned tokens
/// Attackers can forge tokens without knowing the secret
pub fn verify_token_alg_none(token: &str) -> Result<Claims, String> {
// BLOCK: Algorithm::None allows forged tokens - critical authentication bypass
let validation = Validation::new(Algorithm::None);
decode::<Claims>(token, &DecodingKey::from_secret(&[]), &validation)
.map(|data| data.claims)
.map_err(|e| e.to_string())
}
/// VULNERABILITY: Dangerous insecure decode
/// Parses JWT without any signature verification
pub fn decode_without_verify(token: &str) -> Result<Claims, String> {
// BLOCK: dangerous_insecure_decode bypasses all security checks
let parts: Vec<&str> = token.split('.').collect();
if parts.len() != 3 {
return Err("Invalid token format".to_string());
}
// Decode payload without verifying signature - INSECURE
let payload = base64_decode(parts[1])?;
serde_json::from_slice(&payload).map_err(|e| e.to_string())
}
fn base64_decode(input: &str) -> Result<Vec<u8>, String> {
// Simplified base64 decode for demo
Ok(input.as_bytes().to_vec())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_insecure_patterns_exist() {
// These tests verify the vulnerable patterns are present for demo purposes
let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZXhwIjoxNjE2MjM5MDIyLCJhdWQiOiJ0ZXN0In0.signature";
// All these should be detected by Aphoria
let _ = verify_token_no_aud(token, b"secret");
let _ = verify_token_alg_none(token);
let _ = decode_without_verify(token);
}
}