mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-21 20:18:06 +02:00
Phase 1 (#33)
* chore: Exclude CLAUDE.md from Cargo.toml * feat: add callgraph module and integrate into main analysis flow * feat: enhance CLI with new severity filtering and analysis modes * feat: update CHANGELOG with recent enhancements and fixes to severity filtering and output handling * feat: implement state-model dataflow analysis for resource lifecycle and auth state * feat: enhance diagnostic output formatting and add evidence structure * feat: implement attack surface ranking for diagnostics with scoring and sorting * feat: add comprehensive documentation for installation, usage, and rules reference * feat: add multiple language support for command execution and evaluation endpoints * feat: implement inline suppression for findings using `nyx:ignore` comments * feat: add confidence levels to AST patterns and update output structure * feat: implement low-noise prioritization system with category filtering, rollup grouping, and configurable budgets * feat: bump version to 0.4.0 and update changelog with new features and improvements * feat: add dead code allowances to various functions in mod.rs and real_world_tests.rs
This commit is contained in:
parent
19b578c5c4
commit
1bbe4b1cfb
456 changed files with 25628 additions and 1228 deletions
105
docs/rules/rust.md
Normal file
105
docs/rules/rust.md
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# Rust Rules
|
||||
|
||||
Nyx detects Rust vulnerabilities through AST patterns (memory safety, code quality) and taint analysis (command injection via `env::var` → `Command::new`).
|
||||
|
||||
## Taint Sources
|
||||
|
||||
| Function | Capability | Source Kind |
|
||||
|----------|-----------|-------------|
|
||||
| `std::env::var`, `env::var` | `all` | EnvironmentConfig |
|
||||
|
||||
## Taint Sinks
|
||||
|
||||
| Function | Required Capability |
|
||||
|----------|-------------------|
|
||||
| `Command::new`, `Command::arg`, `Command::args` | `SHELL_ESCAPE` |
|
||||
| `Command::status`, `Command::output` | `SHELL_ESCAPE` |
|
||||
| `fs::read_to_string`, `fs::write`, `fs::read`, `File::open`, `File::create` | `FILE_IO` |
|
||||
|
||||
## Taint Sanitizers
|
||||
|
||||
| Function | Strips Capability |
|
||||
|----------|------------------|
|
||||
| `html_escape::encode_safe`, `sanitize_html` | `HTML_ESCAPE` |
|
||||
| `shell_escape::unix::escape`, `sanitize_shell` | `SHELL_ESCAPE` |
|
||||
|
||||
> **Note:** `fs::read_to_string` was moved from taint sources to sinks to support path traversal detection (`env::var` → `fs::read_to_string`).
|
||||
|
||||
---
|
||||
|
||||
## AST Pattern Rules
|
||||
|
||||
### Memory Safety
|
||||
|
||||
| Rule ID | Severity | Tier | Description |
|
||||
|---------|----------|------|-------------|
|
||||
| `rs.memory.transmute` | High | A | `std::mem::transmute` — unchecked type reinterpretation |
|
||||
| `rs.memory.copy_nonoverlapping` | High | A | `ptr::copy_nonoverlapping` — raw pointer memcpy |
|
||||
| `rs.memory.get_unchecked` | High | A | `get_unchecked` / `get_unchecked_mut` — unchecked indexing |
|
||||
| `rs.memory.mem_zeroed` | High | A | `std::mem::zeroed` — may be UB for non-POD types |
|
||||
| `rs.memory.ptr_read` | High | A | `ptr::read` / `ptr::read_volatile` — raw pointer dereference |
|
||||
| `rs.memory.narrow_cast` | Low | A | `as u8`/`i8`/`u16`/`i16` — possible truncation |
|
||||
| `rs.memory.mem_forget` | Low | A | `std::mem::forget` — may leak resources |
|
||||
|
||||
### Code Quality
|
||||
|
||||
| Rule ID | Severity | Tier | Description |
|
||||
|---------|----------|------|-------------|
|
||||
| `rs.quality.unsafe_block` | Medium | A | `unsafe { }` block — manual memory safety obligation |
|
||||
| `rs.quality.unsafe_fn` | Medium | A | `unsafe fn` declaration |
|
||||
| `rs.quality.unwrap` | Low | A | `.unwrap()` — panics on `None`/`Err` |
|
||||
| `rs.quality.expect` | Low | A | `.expect()` — panics on `None`/`Err` |
|
||||
| `rs.quality.panic_macro` | Low | A | `panic!()` macro invocation |
|
||||
| `rs.quality.todo` | Low | A | `todo!()` / `unimplemented!()` placeholder |
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### `rs.memory.transmute` — Unchecked type reinterpretation
|
||||
|
||||
**Vulnerable:**
|
||||
```rust
|
||||
let x: u32 = 42;
|
||||
let y: f32 = unsafe { std::mem::transmute(x) };
|
||||
```
|
||||
|
||||
**Safe alternative:**
|
||||
```rust
|
||||
let x: u32 = 42;
|
||||
let y: f32 = f32::from_bits(x);
|
||||
```
|
||||
|
||||
### `rs.quality.unsafe_block` — Unsafe block
|
||||
|
||||
**Flagged:**
|
||||
```rust
|
||||
unsafe {
|
||||
let ptr = &x as *const i32;
|
||||
println!("{}", *ptr);
|
||||
}
|
||||
```
|
||||
|
||||
**Safe alternative:**
|
||||
```rust
|
||||
// Use safe abstractions when possible
|
||||
println!("{}", x);
|
||||
```
|
||||
|
||||
### Taint: `env::var` → `Command::new`
|
||||
|
||||
**Vulnerable:**
|
||||
```rust
|
||||
let cmd = std::env::var("USER_CMD").unwrap();
|
||||
Command::new("sh").arg("-c").arg(&cmd).output()?;
|
||||
```
|
||||
|
||||
**Safe alternative:**
|
||||
```rust
|
||||
let cmd = std::env::var("USER_CMD").unwrap();
|
||||
// Validate against allowlist
|
||||
let allowed = ["ls", "whoami", "date"];
|
||||
if allowed.contains(&cmd.as_str()) {
|
||||
Command::new(&cmd).output()?;
|
||||
}
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue