mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-06 19:35:13 +02:00
* 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
3.5 KiB
3.5 KiB
Ruby Rules
Nyx detects Ruby vulnerabilities through AST patterns and taint analysis, covering code execution, command injection, deserialization, reflection, SSRF, and weak crypto.
Taint Labels
Ruby has moderate taint label coverage. Sources, sinks, and sanitizers are defined in src/labels/ruby.rs.
Sources
| Matcher | Cap |
|---|---|
ENV, gets |
all |
params |
all |
Note: Ruby's
params[:cmd]subscript access is detected viaelement_referencenode handling in the CFG. Sinatra/Railsdo...endblocks are walked as function scopes.
Sanitizers
| Matcher | Cap |
|---|---|
CGI.escapeHTML, ERB::Util.html_escape |
HTML_ESCAPE |
Shellwords.escape, Shellwords.shellescape |
SHELL_ESCAPE |
Sinks
| Matcher | Cap |
|---|---|
system, exec |
SHELL_ESCAPE |
eval |
SHELL_ESCAPE |
puts, print |
HTML_ESCAPE |
AST Pattern Rules
Code Execution
| Rule ID | Severity | Tier | Description |
|---|---|---|---|
rb.code_exec.eval |
High | A | Kernel#eval — dynamic code execution |
rb.code_exec.instance_eval |
High | A | instance_eval — evaluates string in object context |
rb.code_exec.class_eval |
High | A | class_eval / module_eval — evaluates string in class context |
Command Execution
| Rule ID | Severity | Tier | Description |
|---|---|---|---|
rb.cmdi.backtick |
High | A | Backtick shell execution (`cmd`) |
rb.cmdi.system_interp |
High | A | system/exec call — command execution risk |
Deserialization
| Rule ID | Severity | Tier | Description |
|---|---|---|---|
rb.deser.yaml_load |
High | A | YAML.load — arbitrary object deserialization |
rb.deser.marshal_load |
High | A | Marshal.load — arbitrary Ruby object deserialization |
Reflection
| Rule ID | Severity | Tier | Description |
|---|---|---|---|
rb.reflection.send_dynamic |
Medium | B | send() with non-symbol argument — arbitrary method dispatch |
rb.reflection.constantize |
Medium | A | constantize / safe_constantize — dynamic class resolution |
SSRF
| Rule ID | Severity | Tier | Description |
|---|---|---|---|
rb.ssrf.open_uri |
Medium | A | Kernel#open with HTTP URL — SSRF via open-uri |
Weak Crypto
| Rule ID | Severity | Tier | Description |
|---|---|---|---|
rb.crypto.md5 |
Low | A | Digest::MD5 — weak hash algorithm |
Examples
rb.deser.yaml_load — Unsafe YAML deserialization
Vulnerable:
data = YAML.load(params[:config]) # Arbitrary object instantiation
Safe alternative:
data = YAML.safe_load(params[:config]) # Only basic Ruby types
rb.cmdi.backtick — Backtick shell execution
Vulnerable:
output = `ls #{user_dir}` # Command injection via interpolation
Safe alternative:
require 'open3'
output, status = Open3.capture2('ls', user_dir)
rb.reflection.send_dynamic — Dynamic method dispatch
Vulnerable:
obj.send(params[:method], params[:arg]) # Arbitrary method invocation
Safe alternative:
allowed = %w[name email phone]
if allowed.include?(params[:method])
obj.send(params[:method])
end
rb.deser.marshal_load — Marshal deserialization
Vulnerable:
obj = Marshal.load(request.body.read)
Safe alternative:
data = JSON.parse(request.body.read)