This release clears the entire August audit backlog — every remaining finding from the full-codebase review, plus everything three follow-up review rounds caught. Fourteen fixes spanning security, data safety, and long-standing paper cuts.
🛡️ Security & privacy
- Third-party image metadata is now escaped everywhere. Flickr photo titles and author/license URLs are uploader-controlled text; the Species Stats and Overview photo modals rendered them raw into the page. All pages now share one canonical escaping helper, so future hardening lands everywhere at once.
- Image Provider "None" now really means none. The image API and the Species page contacted Wikipedia even with images disabled, contradicting the Settings privacy text ("nothing leaves your network..."). Every image path now respects the setting.
- The spectrogram page no longer rewrites your config. A stale livestream stream selection used to trigger a config rewrite and root-level service restart from an unauthenticated page view — with a truncate-and-write that could corrupt
birdnet.confunder concurrent access. The page now shows an honest "Live audio is stopped" warning and repairs the setting through the authenticated save when you pick a stream.
🐛 Fixed
- Recordings can no longer be silently lost. If reporting fails mid-detection (full disk, database contention), the audio now moves to a
Failedfolder beside your recordings (capped at the newest 50) instead of being stranded in RAM or deleted. Move a file back toStreamDataand restart to retry — retries are safe and won't duplicate detections or notifications. Database write failures are surfaced instead of silently dropping detections. - "Open in new tab" links work. Every detection's open-in-new-tab icon — and the link in Apprise notifications — landed on the generic dashboard instead of that recording. They now open the recording page.
- The Kiosk view works again. A JavaScript error killed the detection timeline and auto-refresh the moment the page loaded.
- Insights accuracy: the PEAK NOW badge compares week numbers in one convention and in local time (it could light the wrong species for stretches of the year); "Expected Today" no longer goes blank from Dec 29 to Jan 3; and early-January no longer counts last week's birds as prior-year history.
- Species list management: species with apostrophes (Anna's Hummingbird, Cooper's Hawk...) no longer get duplicate entries on every submission, and a missing labels file renders an empty list instead of raw PHP warnings.
- Image caching heals itself: one failed Flickr license lookup used to permanently disable caching for that species, re-running every API call on every page load.
- Overview polish: the dashboard keeps refreshing when new detections are waiting on spectrograms mid-list, and the KPI strip no longer renders blank on a fresh browser session.
- Installer: aborted installs (root user, old OS, sudo problems) now exit with a failure code so scripts can detect them, and a dangling
weekly_report.phplink is no longer planted in the web root.
⚡ Performance
- Insights forecasting is dramatically lighter: historical peak weeks are computed in a single query instead of one query per species ever detected — hundreds of queries per page load on a mature station — and the health subview no longer runs that same workload just to discard the results.
- Backlog-mode dashboard refreshes are throttled to every 30 seconds instead of up to every 1–3 seconds for hours on an already-busy Pi.
Updating
cd ~/BirdNET-Pi
git fetch origin
git pull --ff-only origin main
sudo bash scripts/update_birdnet_snippets.sh
Then refresh your browser.
🤖 Generated with Claude Code