CVE-2026-71209
CVE-2026-71209 is a path traversal in audiobookshelf that exploits a semantic mismatch between how Express represents request paths at different pipeline stages. The prior fix for CVE-2025-25205 anchored the auth-exemption regex and switched to req.path for the check — a reasonable choice given Express's documented API. But Express decodes route parameters (:id) before your handler fires, while req.path remains URL-encoded. The auth exemption check evaluates a URL-encoded path against a literal pattern and finds no match, so it falls through. Meanwhile, CacheManager.handleCoverCache receives the already-decoded :id parameter and joins it directly into a filesystem path with no validation at that layer. The bypass isn't a logic error in the auth code — it's a desynchronization between the path state the auth check sees and the path state the vulnerable operation uses. The exploit is constrained: filenames must match the pattern *_<width>x<height>.<ext> (e.g., cover_500x500.jpg). This covers typical media files but limits direct credential extraction. However, if an attacker can stage files on the host — possible in deployments with writable upload directories — they can retrieve arbitrary files matching this pattern, including audiobook covers and associated metadata. For defenders, the immediate priority is to verify whether CacheManager.handleCoverCache validates the :id parameter before any path join operation. Adding filename-character validation at that sink would have blocked this CVE regardless of the upstream auth layer's state. More broadly, treat route parameters as untrusted input in any handler that touches the filesystem — don't assume Express's routing layer has validated them for your security context. The deeper lesson: Express applications routinely mix URL-encoded req.path with pre-decoded req.params in different middleware layers. This semantic divergence is documented but its security implications are not flagged. Audit your own Express handlers for the same pattern — auth logic on req.path operating alongside filesystem operations using req.params or decoded values. If you have multiple representations of the same request path in different pipeline stages, normalize them at a single entry point before any security decisions or path operations.
Reviewed through automated stages and approved by a human before publication.