v2.9.0
Features
- JSON reports now include supp[], the traits that matched but were suppressed or demoted by an unless:/downgrade: leg.
- Composites now carry uses[], the indices of the components they fired on.
- conf is always emitted, no longer omitted at 0.5.
- New cleave regex-cost subcommand checks patterns for lazy-DFA explosion.
- New regex-explosion validator rejects rules that blow up on bundle-shaped text.
- Decodes Unicode variation-selector steganography.
- Detects PyPI typosquats at edit distance 1 from high-value package names.
- Flags generator-produced identifiers such as DGA labels, maldoc authors, and bundle IDs.
- Reports how much of a VS Code extension pack the publisher actually owns.
- New references.security_hold_count counts dependencies pulled for security holds.
Fixes
- JAR analysis no longer truncates at 100 non-class members.
- A single huge JAR no longer monopolizes the thread pool
- Container-scope import checks no longer see zero imports under compact retention.
- UPX timeouts and missing binaries are no longer reported as hostile findings.
- Fixed traits_version attribution, Java predicates, directory refs, and the Windows memory guard.
Optimizations
- Regex pre-warming at startup drops a small Python wheel from ~640 ms to ~100 ms.
- Symbol matching uses cleave's thread-local regex scratch instead of the crate's shared pool.
- Duplicate archive members are analyzed once rather than per occurrence.
- Eager full-DFA construction is off by default, saving ~95 MiB on a 44k-pattern set.
- Archive fan-out backs off under host memory pressure.
- cgroup accounting no longer counts page cache as used, which had reported 15.6 GiB free where 55 GiB was.
- The LLM render draws one window per finding, cutting 11% of repeated evidence.