mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-21 20:18:06 +02:00
refactor(server, scan): introduce target management with active target switching, enhance DB pool handling, and integrate target-aware task routes for improved modularity
This commit is contained in:
parent
acdc71cd88
commit
635b213825
40 changed files with 1810 additions and 240 deletions
|
|
@ -9,6 +9,17 @@ Nyx ships four independent detector families. They run together in `--mode full`
|
|||
| [State model](detectors/state.md) | `state-*` | Per-function state lattice | Use-after-close, double-close, leaks, unauthenticated access |
|
||||
| [AST patterns](detectors/patterns.md) | `<lang>.<cat>.<name>` | Tree-sitter structural match | Banned APIs, weak crypto, dangerous constructs |
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Taint["Taint analysis<br/>cross-file source-to-sink"] --> Normalize["Normalize findings"]
|
||||
Cfg["CFG structural<br/>guards, exits, resource paths"] --> Normalize
|
||||
State["State model<br/>resource and auth lattice"] --> Normalize
|
||||
Ast["AST patterns<br/>tree-sitter structural match"] --> Normalize
|
||||
Normalize --> Dedupe["Deduplicate<br/>same site, rule, severity"]
|
||||
Dedupe --> Rank["Rank<br/>severity, evidence, context"]
|
||||
Rank --> Output["Console, JSON, SARIF, UI"]
|
||||
```
|
||||
|
||||
The taint family is split into cap-specific rule classes when a sink callee carries multiple vulnerability classes:
|
||||
|
||||
| Rule id | Cap | Surface |
|
||||
|
|
|
|||
|
|
@ -6,6 +6,21 @@ If you're going to act on a finding, it helps to know how the scanner got there.
|
|||
|
||||
A scan runs in two passes over the file tree, with an optional SQLite index that lets the second scan skip files whose content hash hasn't changed.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Walk["Walk file tree"] --> Pass1["Pass 1 per file<br/>tree-sitter parse, CFG, SSA"]
|
||||
Pass1 --> Summaries["Per-function summaries<br/>sources, sinks, sanitizers, returns, points-to"]
|
||||
Pass1 --> Hierarchy["Type hierarchy index<br/>extends, implements, impl-for, includes"]
|
||||
Summaries --> Global["GlobalSummaries map<br/>plus optional SQLite cache"]
|
||||
Hierarchy --> Global
|
||||
Global --> Pass2["Pass 2 per file<br/>cross-file context"]
|
||||
Pass2 --> Taint["Forward SSA taint worklist<br/>finite lattice, guaranteed convergence"]
|
||||
Pass2 --> Calls["Call precision<br/>k=1 inline, summaries, SCC fixed-point"]
|
||||
Taint --> Findings["Findings with evidence<br/>source, path, sink, engine notes"]
|
||||
Calls --> Findings
|
||||
Findings --> Emit["Rank, dedupe, emit<br/>console, JSON, SARIF, UI"]
|
||||
```
|
||||
|
||||
**Pass 1, per file.** Tree-sitter parses the file. Nyx builds an intra-procedural control-flow graph, lowers it to SSA, and extracts a summary per function describing what that function does at the boundary: which arguments flow to sinks, which sources it reads from, which sinks it calls, what taint it strips, what it returns. Summaries are persisted to SQLite ([`src/summary/`](https://github.com/elicpeter/nyx/tree/master/src/summary/), [`src/database.rs`](https://github.com/elicpeter/nyx/blob/master/src/database.rs)).
|
||||
|
||||
**Summary merge.** All per-file summaries get unioned into a global map keyed by qualified function name.
|
||||
|
|
|
|||
69
docs/mermaid-init.js
Normal file
69
docs/mermaid-init.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
(function () {
|
||||
const MERMAID_URL =
|
||||
"https://cdn.jsdelivr.net/npm/mermaid@10.9.3/dist/mermaid.esm.min.mjs";
|
||||
|
||||
async function renderMermaid() {
|
||||
const blocks = Array.from(
|
||||
document.querySelectorAll("pre > code.language-mermaid"),
|
||||
);
|
||||
if (blocks.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const mermaidModule = await import(MERMAID_URL);
|
||||
const mermaid = mermaidModule.default;
|
||||
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
securityLevel: "strict",
|
||||
theme: "base",
|
||||
themeVariables: {
|
||||
background: "transparent",
|
||||
fontFamily:
|
||||
"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif",
|
||||
primaryColor: "#0f172a",
|
||||
primaryTextColor: "#e5e7eb",
|
||||
primaryBorderColor: "#22d3ee",
|
||||
secondaryColor: "#134e4a",
|
||||
secondaryTextColor: "#e5e7eb",
|
||||
secondaryBorderColor: "#2dd4bf",
|
||||
tertiaryColor: "#1e293b",
|
||||
tertiaryTextColor: "#e5e7eb",
|
||||
tertiaryBorderColor: "#64748b",
|
||||
lineColor: "#94a3b8",
|
||||
edgeLabelBackground: "#0f172a",
|
||||
clusterBkg: "#111827",
|
||||
clusterBorder: "#475569",
|
||||
},
|
||||
});
|
||||
|
||||
for (const block of blocks) {
|
||||
const pre = block.parentElement;
|
||||
if (!pre) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.className = "nyx-mermaid";
|
||||
|
||||
const diagram = document.createElement("div");
|
||||
diagram.className = "mermaid";
|
||||
diagram.textContent = block.textContent.trim();
|
||||
|
||||
wrapper.appendChild(diagram);
|
||||
pre.replaceWith(wrapper);
|
||||
}
|
||||
|
||||
await mermaid.run({ querySelector: ".nyx-mermaid .mermaid" });
|
||||
} catch (error) {
|
||||
console.warn("Mermaid rendering failed", error);
|
||||
}
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", renderMermaid);
|
||||
} else {
|
||||
renderMermaid();
|
||||
}
|
||||
})();
|
||||
15
docs/mermaid.css
Normal file
15
docs/mermaid.css
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
.nyx-mermaid {
|
||||
margin: 1.5rem 0;
|
||||
padding: 1rem;
|
||||
overflow-x: auto;
|
||||
border: 1px solid rgba(148, 163, 184, 0.35);
|
||||
border-radius: 8px;
|
||||
background: rgba(15, 23, 42, 0.28);
|
||||
}
|
||||
|
||||
.nyx-mermaid svg {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
|
@ -11,6 +11,16 @@ nyx serve --no-browser # don't auto-open
|
|||
|
||||
Persistent settings live under `[server]` in `nyx.conf` / `nyx.local`.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Scan["nyx scan<br/>or UI-started scan"] --> Cache[".nyx findings<br/>plus SQLite project index"]
|
||||
Cache --> Serve["nyx serve<br/>loopback API and embedded React UI"]
|
||||
Serve --> Review["Review findings<br/>flow, evidence, history"]
|
||||
Review --> Triage["Update triage state<br/>investigate, suppress, accept, fix"]
|
||||
Triage --> Sync[".nyx/triage.json<br/>optional repo-synced state"]
|
||||
Sync --> Cache
|
||||
```
|
||||
|
||||
Starting a scan from the UI runs dynamic verification on `Confidence >= Medium`
|
||||
findings by default. Check "Skip dynamic verification" in the scan modal to get
|
||||
a fast static-only result. See [Dynamic verification](dynamic.md) for details.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue