# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [0.3.2] — 2026-07-31 > **Denial-of-service fix. Upgrade from 0.3.1.** The output gate could be made to > spend hours on a single call by crafted input it accepts by design. No > disposition changes for ordinary documents — the one measured exception is > listed under *Known behaviour changes* below. The v0.3.1 tag is not moved. ### Fixed — 19 quadratic regex runs on the output path `scan_output` claimed LLM10 self-safety on the grounds that its patterns contain no nested quantifiers. That is true and it is not the property that matters. A run in front of a **required** literal, reachable from a short anchor, is enough: crafted input repeats the anchor and never supplies the literal, so every start position rescans the tail. Quadratic, not exponential — and quadratic is sufficient here. Measured, not argued (Python 3.14, this machine): | Input | Time through `scan_output` | |---|---| | ``. ### Known behaviour changes Two, both measured against the v0.3.1 tag rather than reasoned about: - **A JWT used as a DB password, over 256 chars, is no longer CRITICAL.** The remaining detections (`entropy:base64-blob` HIGH, `egress:jwt-token` MEDIUM) top out below CRITICAL, so the any-tier block is lost: under `PRESET_TRUSTED_SOURCE` such a document moves from `fail_secure` to `quarantine_review`. Under `PRESET_USER_UPLOAD` it still `fail_secure`s, and a *generic* long password still trips `entropy:base64-blob` at CRITICAL with no change at all. The credential is never silently missed; on one preset it is held for review instead of halted. - **`hybrid-xss:script-tag` now fires on prose that merely mentions `