| name | sc-lang-rust |
| description | Rust-specific security deep scan |
| license | MIT |
| metadata | {"author":"ersinkoc","category":"security","version":"1.0.0"} |
SC: Rust Security Deep Scan
Purpose
Detects Rust-specific security anti-patterns focusing on unsafe code, FFI boundaries, concurrency pitfalls, and areas where Rust's safety guarantees can be circumvented. Despite Rust's strong type system, vulnerabilities exist in unsafe blocks, integer overflow behavior, and third-party crate misuse.
Activation
Activates when Rust is detected in security-report/architecture.md.
Checklist Reference
References references/rust-security-checklist.md.
Rust-Specific Vulnerability Patterns
Category 1: Unsafe Block Audit
unsafe {
let ptr = addr as *const u8;
let value = *ptr;
}
let x: u64 = unsafe { std::mem::transmute(user_input_f64) };
unsafe {
assert!(!ptr.is_null(), "null pointer");
let value = *ptr;
}
Category 2: FFI Boundary Validation
extern "C" fn process(input: *const c_char) {
let s = unsafe { CStr::from_ptr(input) };
extern "C" fn process(input: *const c_char) {
if input.is_null() { return; }
let s = unsafe { CStr::from_ptr(input) };
let s = s.to_str().unwrap_or_default();
}
Category 3: Command Injection
use std::process::Command;
Command::new("sh").arg("-c").arg(format!("echo {}", user_input)).output();
Command::new("echo").arg(user_input).output();
Category 4: Path Traversal
let path = PathBuf::from("/uploads").join(user_filename);
std::fs::read(path)?;
let base = PathBuf::from("/uploads").canonicalize()?;
let target = base.join(user_filename).canonicalize()?;
if !target.starts_with(&base) { return Err("path traversal"); }
Category 5: Integer Overflow
let x: u8 = 255;
let y = x + 1;
let y = x.checked_add(1).ok_or("overflow")?;
let y = x.saturating_add(1);
Category 6: panic!() in Library Code
pub fn parse(input: &str) -> Data {
let idx = input.find(':').unwrap();
}
pub fn parse(input: &str) -> Result<Data, ParseError> {
let idx = input.find(':').ok_or(ParseError::MissingDelimiter)?;
}
Category 7: Rc/Arc Reference Cycles
use std::rc::Rc;
use std::cell::RefCell;
let a = Rc::new(RefCell::new(Node { next: None }));
let b = Rc::new(RefCell::new(Node { next: Some(a.clone()) }));
a.borrow_mut().next = Some(b.clone());
use std::rc::Weak;
a.borrow_mut().parent = Rc::downgrade(&b);
Category 8: Send/Sync Trait Misuse
struct MyWrapper(*mut c_void);
unsafe impl Send for MyWrapper {}
Category 9: Interior Mutability Data Race
Category 10: Serde Deserialization Bombs
let data: Value = serde_json::from_str(&user_input)?;
let data: Vec<Vec<Vec<String>>> = serde_json::from_str(&input)?;
if user_input.len() > MAX_SIZE { return Err("too large"); }
Category 11: Actix-web/Axum Security
HttpServer::new(|| {
App::new()
.route("/admin", web::get().to(admin_handler))
})
App::new()
.service(
web::scope("/admin")
.wrap(AuthMiddleware)
.route("", web::get().to(admin_handler))
)
Category 12: Cargo Supply Chain
build.rs in dependencies can execute arbitrary code at compile time
- Proc macros run arbitrary code during compilation
- Check for typosquatted crate names
- Review
cargo audit for known vulnerabilities
- Verify
Cargo.lock is committed for applications
Category 13: Pin/Unpin Unsoundness
Category 14: MaybeUninit UB
let x: MaybeUninit<u64> = MaybeUninit::uninit();
let val = unsafe { x.assume_init() };
let mut x = MaybeUninit::uninit();
x.write(42);
let val = unsafe { x.assume_init() };
Category 15: Tokio Task Cancellation Safety
async fn transfer(from: &mut Account, to: &mut Account, amount: u64) {
from.balance -= amount;
db.save(from).await;
to.balance += amount;
db.save(to).await;
}
async fn transfer(from: &mut Account, to: &mut Account, amount: u64) {
let tx = db.begin().await?;
tx.commit().await?;
}
Category 16: .await in Drop
impl Drop for MyResource {
fn drop(&mut self) {
}
}
impl MyResource {
async fn cleanup(self) { }
}
Category 17: Regex DoS
let re = Regex::new(&user_pattern)?;
let re = RegexBuilder::new(&pattern).size_limit(1024 * 1024).build()?;
Category 18: Unsafe Trait Implementations
Category 19: Memory Leaks via Box::leak
let leaked: &'static str = Box::leak(user_string.into_boxed_str());
Category 20: Error Handling Information Disclosure
HttpResponse::InternalServerError().body(format!("Error: {err:?}"))
tracing::error!("Database error: {err:?}");
HttpResponse::InternalServerError().body("Internal server error")
Output Format
Finding: RS-{NNN}
- Title: Rust-specific vulnerability
- Severity: Critical | High | Medium | Low
- Confidence: 0-100
- File: file/path:line
- Vulnerability Type: CWE-XXX
- Description: What was found
- Remediation: Rust-idiomatic fix with code example
- References: CWE link, Rust security documentation