1
0
Fork 0
mirror of https://github.com/imjasonh/rustvulncheck synced 2026-07-16 20:43:49 +00:00

Add syn-based type tracking and golden codebase integration tests

Type tracking (type_tracker.rs):
- Uses syn AST parsing to resolve variable types from function parameters,
  let bindings with annotations, constructor calls (Type::new()), struct
  literals, builder patterns, and closure parameters
- Integrated into scanner to promote method-call matches from Medium to
  High confidence when the receiver's type is known

Golden integration tests:
- vulnerable_project: 4 vulnerable deps, 3 with reachable calls across
  multiple files (qualified calls, typed method calls, constructor-inferred
  types). Verifies regex dep is listed but Compiler::compile is NOT reachable.
- safe_project: patched deps (hyper, smallvec) excluded, vulnerable deps
  (tokio, regex) listed but no symbols reachable. Reports POSSIBLY SAFE.
- clean_project: no vulnerable deps at all. Reports CLEAN.

37 tests total (33 unit + 4 integration), all passing.

https://claude.ai/code/session_011sdj18ZvQYbDVwEKqrWDj1
This commit is contained in:
Claude 2026-03-25 12:44:13 +00:00
parent b148c8d4b8
commit a2db0d4d15
No known key found for this signature in database
14 changed files with 1013 additions and 83 deletions

70
tests/fixtures/golden_vuln_db.json vendored Normal file
View file

@ -0,0 +1,70 @@
{
"generated_at": "unix:1700000000",
"entries": [
{
"advisory_id": "RUSTSEC-2024-0001",
"package": "hyper",
"title": "Lenient HTTP header parsing allows request smuggling",
"date": "2024-01-15",
"patched_versions": [">= 1.0.0"],
"commit_sha": "abc123",
"vulnerable_symbols": [
{
"file": "src/proto/h1/role.rs",
"function": "hyper::proto::h1::role::Client::encode",
"change_type": "Modified"
},
{
"file": "src/proto/h1/decode.rs",
"function": "hyper::proto::h1::decode::Decoder::decode",
"change_type": "Modified"
}
]
},
{
"advisory_id": "RUSTSEC-2024-0010",
"package": "smallvec",
"title": "Buffer overflow in SmallVec::insert_many",
"date": "2024-02-20",
"patched_versions": [">= 1.11.0"],
"commit_sha": "def456",
"vulnerable_symbols": [
{
"file": "src/lib.rs",
"function": "smallvec::SmallVec::insert_many",
"change_type": "Modified"
}
]
},
{
"advisory_id": "RUSTSEC-2024-0020",
"package": "tokio",
"title": "Race condition in task abort",
"date": "2024-03-01",
"patched_versions": [">= 1.38.0"],
"commit_sha": "ghi789",
"vulnerable_symbols": [
{
"file": "src/runtime/task/mod.rs",
"function": "tokio::runtime::task::JoinHandle::abort",
"change_type": "Modified"
}
]
},
{
"advisory_id": "RUSTSEC-2024-0030",
"package": "regex",
"title": "ReDoS in regex compilation",
"date": "2024-04-01",
"patched_versions": [">= 1.10.0"],
"commit_sha": "jkl012",
"vulnerable_symbols": [
{
"file": "src/compile.rs",
"function": "regex::compile::Compiler::compile",
"change_type": "Modified"
}
]
}
]
}

27
tests/fixtures/safe_project/Cargo.lock generated vendored Normal file
View file

@ -0,0 +1,27 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "my-safe-app"
version = "0.1.0"
[[package]]
name = "hyper"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "tokio"
version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "regex"
version = "1.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"

View file

@ -0,0 +1,24 @@
//! Handler module.
//!
//! Uses tokio and regex, but does NOT call the vulnerable symbols.
//! - tokio is at a vulnerable version but abort() is never called
//! - regex is at a vulnerable version but Compiler::compile is internal and not called
//! - hyper is at a PATCHED version (1.2.0 >= 1.0.0)
//! - smallvec is at a PATCHED version (1.11.0 >= 1.11.0)
use tokio::runtime::task::JoinHandle;
use regex::Regex;
pub fn run() {
// Uses regex but NOT the vulnerable Compiler::compile — just the public API
let re = Regex::new(r"\d+").unwrap();
let matched = re.is_match("hello 123");
println!("Matched: {}", matched);
// References JoinHandle type but never calls .abort()
let handles: Vec<JoinHandle> = Vec::new();
for handle in handles {
// Just awaits, doesn't abort
println!("waiting on handle");
}
}

View file

@ -0,0 +1,5 @@
mod handler;
fn main() {
handler::run();
}

27
tests/fixtures/vulnerable_project/Cargo.lock generated vendored Normal file
View file

@ -0,0 +1,27 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "my-vulnerable-app"
version = "0.1.0"
[[package]]
name = "hyper"
version = "0.14.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "tokio"
version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "regex"
version = "1.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"

View file

@ -0,0 +1,6 @@
mod server;
mod utils;
fn main() {
server::run_server();
}

View file

@ -0,0 +1,15 @@
//! Server module that uses hyper for HTTP handling.
use hyper::proto::h1::role::Client;
use hyper::proto::h1::decode::Decoder;
pub fn run_server() {
// Case 1: Qualified associated-function call (HIGH confidence expected)
let client = Client::encode(raw_request);
// Case 2: Method call on typed variable (HIGH confidence with type tracking)
let decoder: Decoder = Decoder::new();
let result = decoder.decode(buf);
println!("Server running: {:?} {:?}", client, result);
}

View file

@ -0,0 +1,21 @@
//! Utility module with additional vulnerable calls.
use smallvec::SmallVec;
use tokio::runtime::task::JoinHandle;
pub fn process_data(items: &[u8]) {
// Case 3: Method call on constructor-inferred type (HIGH with type tracking)
let mut vec = SmallVec::new();
vec.insert_many(0, items.iter().copied());
// Case 4: Method call on typed parameter (HIGH with type tracking)
cancel_task(get_handle());
}
fn cancel_task(handle: JoinHandle) {
handle.abort();
}
fn get_handle() -> JoinHandle {
todo!()
}