chore: Update version placeholders and changelog for release 0.6.0

This commit is contained in:
elipeter 2026-05-02 18:06:50 -04:00
parent 215dd02eff
commit 92aaa36ed6
6 changed files with 86 additions and 42 deletions

View file

@ -41,7 +41,7 @@ body:
attributes:
label: Nyx version
description: Output of `nyx --version`.
placeholder: "nyx 0.5.0"
placeholder: "nyx 0.6.0"
validations:
required: true
- type: input

View file

@ -4,7 +4,7 @@ All notable changes to Nyx are documented here. The format is based on [Keep a C
## [Unreleased]
## [0.6.0] - TBD
## [0.6.0] - 2026-05-02
A focused release that splits data-exfiltration off from SSRF and ships sinks for outbound HTTP request bodies across all 10 languages, with calibration tuned so plain user input echoed back upstream does not fire.

View file

@ -115,7 +115,7 @@ Requires stable Rust 1.88+. The frontend is compiled and embedded in the binary
## Languages
All 10 languages parse via tree-sitter and run through the full pipeline, but rule depth and engine coverage are uneven. Benchmark F1 on the 492-case corpus at [`tests/benchmark/ground_truth.json`](tests/benchmark/ground_truth.json) is 100% across all ten languages, so F1 alone no longer separates the tiers. Tiering reflects rule depth, gated-sink coverage, and structural idioms the synthetic corpus does not fully stress:
All 10 languages parse via tree-sitter and run through the full pipeline, but rule depth and engine coverage are uneven. Benchmark F1 on the 507-case corpus at [`tests/benchmark/ground_truth.json`](tests/benchmark/ground_truth.json) is 100% across all ten languages, so F1 alone no longer separates the tiers. Tiering reflects rule depth, gated-sink coverage, and structural idioms the synthetic corpus does not fully stress:
| Tier | Languages | F1 | Use as a CI gate? |
|---|---|---|---|
@ -137,6 +137,7 @@ The corpus also holds a small set of vulnerable/patched pairs extracted from pub
| [CVE-2023-22621](https://nvd.nist.gov/vuln/detail/CVE-2023-22621) | Strapi | JavaScript | Code execution (SSTI) |
| [CVE-2025-64430](https://nvd.nist.gov/vuln/detail/CVE-2025-64430) | Parse Server | JavaScript | SSRF |
| [CVE-2023-26159](https://nvd.nist.gov/vuln/detail/CVE-2023-26159) | follow-redirects | TypeScript | SSRF |
| [GHSA-4x48-cgf9-q33f](https://github.com/advisories/GHSA-4x48-cgf9-q33f) | Novu | TypeScript | SSRF |
| [CVE-2026-25544](https://nvd.nist.gov/vuln/detail/CVE-2026-25544) | Payload CMS | TypeScript | SQL injection |
| [CVE-2022-30323](https://nvd.nist.gov/vuln/detail/CVE-2022-30323) | hashicorp/go-getter | Go | Command injection |
| [CVE-2024-31450](https://nvd.nist.gov/vuln/detail/CVE-2024-31450) | owncast | Go | Path traversal |
@ -211,7 +212,7 @@ Or add rules interactively: `nyx config add-rule --lang javascript --matcher esc
## Status
Under active development. APIs, detector behavior, and configuration options may change between releases. Rule-level F1 on the 492-case corpus is the CI regression floor; per-language detail lives in [`tests/benchmark/RESULTS.md`](tests/benchmark/RESULTS.md).
Under active development. APIs, detector behavior, and configuration options may change between releases. Rule-level F1 on the 507-case corpus is the CI regression floor; per-language detail lives in [`tests/benchmark/RESULTS.md`](tests/benchmark/RESULTS.md).
Taint analysis is interprocedural. Persisted per-function SSA summaries carry per-return-path transforms and parameter-granularity points-to, and call-graph SCCs (including SCCs that span files) iterate to a joint fixed-point. The default `balanced` profile also runs k=1 context-sensitive inlining for intra-file callees. Symex (with cross-file and interprocedural frames) and the demand-driven backwards walk are opt-in. Enable them individually with `--symex` and `--backwards-analysis`, or together with `--engine-profile deep`.

View file

@ -1,46 +1,88 @@
# Security Policy
## Supported Versions
## Reporting a vulnerability
| Version | Supported | Notes |
|---------|-----------|----------------------|
| 0.5.x | ✅ | Latest stable line |
| 0.4.x | ✅ | Critical fixes only |
| < 0.4 | | End-of-life |
Report privately. Do not open a public GitHub issue for a security bug.
We follow [Semantic Versioning] as soon as we hit **1.0.0**.
Before that, breaking changes may land in any minor release.
Use [GitHub Security Advisories](https://github.com/elicpeter/nyx/security/advisories/new) to file a private report. Only the maintainers see it.
## Reporting a Vulnerability
Include:
* **Private disclosure first.**
Please **do not** open public GitHub issues for security bugs.
- Affected version (`nyx --version`) and OS
- Reproduction steps or a minimal PoC
- Impact (RCE, file read or write, sandbox escape, auth bypass in `nyx serve`, etc.)
- Whether you have a fix in mind
* **How to report**
1. To report a vulnerability, please use the GitHub disclosure in the security tab to alert us to a security issue.
You'll get an acknowledgement within 3 business days, and a status update every 7 days until the issue is closed.
* **What to include**
A minimal PoC or reproduction steps
Affected Nyx version (`nyx --version`) and OS
Impact explanation (e.g. RCE, DoS, data leak)
## Scope
* **Response timeline**
We acknowledge within **3 business days** and give a status update every **7 days** thereafter until resolution.
In scope: bugs that let untrusted input reach the Nyx process and cause harm.
## Disclosure Process
- Code execution in the scanner: parser exploits, deserialization, command injection in helpers, custom-rule sandbox escape.
- Path traversal or arbitrary file access outside the target repo.
- `nyx serve` issues: auth bypass, host-header bypass, CSRF on mutating routes, XSS in the UI, cross-origin access from a non-loopback origin.
- Memory safety bugs in any unsafe Rust we introduce.
- Tampering with `.nyx/` triage state from outside the user's repo.
- Supply chain issues affecting published `nyx-scanner` crates or release artifacts.
1. We confirm the issue and assign a CVE (via GitHub or MITRE).
2. A fix is developed on a private branch and back-ported if needed.
3. Coordinated release: new version on crates.io + public advisory.
4. Credit is given to the reporter unless they request anonymity.
Out of scope:
## Scope & Severity
- False positives or missed detections in scan output. File a regular GitHub issue with the rule ID and a fixture.
- Findings Nyx reports against your own code. That's the scanner working, not a Nyx vulnerability.
- Anything requiring physical or local-account access to the user's machine.
- Self-XSS and missing security headers on `127.0.0.1` endpoints. The UI is loopback-only.
- Performance pathologies on hostile input (a 50 GB file, deeply nested grammars). We harden where we can.
- Issues only reachable by a user editing their own `nyx.conf` to weaken defaults.
This policy covers vulnerabilities that let an **untrusted Nyx input** cause:
## Supported versions
* Remote or local code execution in the Nyx process
* Privilege escalation, data exfiltration, or denial of service
| Version | Status |
|---------|-----------------------|
| 0.6.x | Supported |
| 0.5.x | Critical fixes only |
| < 0.5 | End of life |
**False positives / missed detections** in scan results are *quality issues*, not security issues. Please file normal GitHub issues for those.
The project follows [Semantic Versioning](https://semver.org) once it reaches 1.0.0. Until then, breaking changes can land in any minor release.
[Semantic Versioning]: https://semver.org
## Severity
We use [CVSS 3.1](https://www.first.org/cvss/v3.1/specification-document) to rate reports.
| Severity | Examples |
|----------|-----------------------------------------------------------------------------------------------|
| Critical | Unauthenticated RCE in `nyx serve`, custom-rule sandbox escape during a default scan |
| High | Auth bypass against `nyx serve`, arbitrary file write outside the repo |
| Medium | Stored XSS in the UI, CSRF on a mutating route, host-header bypass |
| Low | Information disclosure with no privilege change, log-injection, denial of service via input |
## Disclosure
Coordinated disclosure.
1. We confirm the report and assign severity.
2. We request a CVE through GitHub or MITRE.
3. A fix is developed on a private branch, with backports to supported lines if needed.
4. A new release ships on crates.io and a public advisory goes out.
5. The reporter is credited in the advisory and the changelog, unless they ask to stay anonymous.
Target window from report to fix is 90 days. If you need to publish on a shorter timeline, tell us in the report and we'll work toward it.
## Safe harbor
Good-faith security research is welcome. We won't pursue legal action against researchers who:
- Report privately and give a reasonable window before publishing.
- Test against their own installations, not third-party deployments running Nyx.
- Avoid data destruction, account takeover, and service disruption.
- Stop and reach out if a test starts to affect data or systems they don't own.
If you're not sure whether a test is in scope, ask first.
## Bounty
There is no paid bug bounty program. Credit, a thank-you in the advisory, and a mention in the changelog are what we offer today.
## Security model recap
Nyx runs locally. The browser UI binds to `127.0.0.1` by default, requires a matching `Host` header, and uses a CSRF token on every mutating request. There is no login, no telemetry, and no remote control plane. If you find a way around any of those defaults, that's a security issue and we want to hear about it.

View file

@ -8,9 +8,9 @@ Current baseline (2026-05-02):
| Recall | 1.000 | 1.000 | 0.944 |
| F1 | 1.000 | 1.000 | 0.901 |
Corpus: 499 cases across 10 languages, 496 evaluated (3 disabled). Per-run JSON lands in `tests/benchmark/results/` (`latest.json` plus dated snapshots). See `README.md` for what the scoring modes mean and how to run a subset.
Corpus: 507 cases across 10 languages, 504 evaluated (3 disabled). Per-run JSON lands in `tests/benchmark/results/` (`latest.json` plus dated snapshots). See `README.md` for what the scoring modes mean and how to run a subset.
The corpus is mostly synthetic 8-20 line fixtures, one vulnerability or one safe pattern per file. A smaller real-CVE replay set under `cve_corpus/` covers 20 published CVEs across all 10 languages. Both contribute to the headline numbers.
The corpus is mostly synthetic 8-20 line fixtures, one vulnerability or one safe pattern per file. A smaller real-CVE replay set under `cve_corpus/` covers 30 published advisories across all 10 languages. Both contribute to the headline numbers.
## Real CVE coverage
@ -40,6 +40,9 @@ Real disclosed CVEs reduced to minimal reproducers, vulnerable + patched pair pe
| CVE-2023-38337 | Ruby | rswag | MIT | path_traversal | detected |
| CVE-2017-9841 | PHP | PHPUnit | BSD-3-Clause | code_exec | detected |
| CVE-2018-15133 | PHP | Laravel | MIT | Deserialization | detected |
| CVE-2018-20997 | Rust | tar-rs | MIT OR Apache-2.0 | path_traversal | detected |
| CVE-2022-36113 | Rust | cargo | MIT OR Apache-2.0 | path_traversal | detected |
| CVE-2024-24576 | Rust | Rust stdlib | MIT OR Apache-2.0 | CMDI | detected |
| CVE-2016-3714 | C | ImageMagick (ImageTragick) | ImageMagick License | CMDI | detected |
| CVE-2019-18634 | C | sudo (pwfeedback) | ISC | memory_safety | detected |
| CVE-2019-13132 | C++ | ZeroMQ libzmq | MPL-2.0 | memory_safety | detected |

View file

@ -15995,9 +15995,8 @@
"sqli",
"vulnerable"
],
"disabled": true,
"disabled_reason": "Validated-flow propagation through SSA-derived values and helper-summary returns is missing. The patched counterpart applies a regex allowlist (`SAFE_STRING_REGEX.test(value)` throw) PLUS a `replace()` escape chain inside `sanitizeValue`, then interpolates the result into a SQL template literal in `createJSONQuery` and returns the string to the handler, which calls `db.execute(sql)`. This session landed `classify_condition` recognition of `<*regex*>.test(value)` / `<*pattern*>.test(value)` as a ValidationCall whose target is the call's first arg (covered by `path_state::tests::target_regex_test_first_arg`, `target_regex_test_pattern_receiver`, `target_test_non_regex_receiver_is_not_validation`, plus the SSA-level `regex_test_allowlist_narrowing_clears_direct_flow` integration test). But validated_must is per-symbol and consulted only at the sink site; it does NOT propagate through the SSA Assign that templates a clean `value` into a derived `sql` string, nor does it ride a helper's `param_to_return` summary back into a caller. Disabled until that propagation path lands. Tracked in CVE_DEFERRED.md.",
"notes": "CVE-2026-25544: Payload `sanitizeValue` SQL injection via Postgres jsonb_path_exists template-string interpolation. Vulnerable form (`@payloadcms/drizzle@v3.72.0`, MIT) lets attacker-controlled JSON-query value escape the surrounding SQL string literal because `sanitizeValue` only double-quotes it without escaping `\\`/`\"`. Disabled pending validated-flow propagation engine work, see disabled_reason."
"disabled": false,
"notes": "CVE-2026-25544: Payload `sanitizeValue` SQL injection via Postgres jsonb_path_exists template-string interpolation. Vulnerable form (`@payloadcms/drizzle@v3.72.0`, MIT) lets attacker-controlled JSON-query value escape the surrounding SQL string literal because `sanitizeValue` only double-quotes it without escaping `\\`/`\"`. Enabled after validated-flow propagation landed via `SsaFuncSummary.validated_params_to_return` + `propagate_validated_params_to_return`."
},
{
"case_id": "cve-ts-2026-25544-patched",
@ -16024,9 +16023,8 @@
"safe",
"patched"
],
"disabled": true,
"disabled_reason": "Sibling of cve-ts-2026-25544-vulnerable. Disabled together until validated-flow summary propagation lands. See vulnerable counterpart's disabled_reason for the engine gap.",
"notes": "Patched form of `sanitizeValue` from `@payloadcms/drizzle@v3.73.0` (MIT). Disabled together with its vulnerable counterpart pending validated-flow propagation work."
"disabled": false,
"notes": "Patched form of `sanitizeValue` from `@payloadcms/drizzle@v3.73.0` (MIT). Enabled after validated-flow propagation landed."
}
]
}