- /files dashboard backed by per-sample _summary_cache.json with mtime-validated source set; ~8x on a single sample, scales linearly
- path_manager.find_file_by_hash keeps a per-folder hash->dirname index validated against folder mtime; ~10x on warm lookups
- BYOVD route reads compile_time from file_info.json instead of re-parsing the PE
- CHANGELOG entries for the perf cluster
Fibratus EDR profile (kind: fibratus). Pull-from-event-log model, same
shape DetonatorAgent's FibratusEdrPlugin.cs uses: operator configures
Fibratus on the EDR VM with alertsenders.eventlog: {enabled: true,
format: json}; rule matches land in the Application log. Whiskers gains
GET /api/alerts/fibratus/since which wevtutil-queries the log,
extracts <TimeCreated SystemTime> + <EventID> + <Data>, ships the raw
JSON blobs back. The new FibratusEdrAnalyzer mirrors Elastic's
two-phase shape — Phase 1 exec, Phase 2 polls Whiskers — and normalizes
Fibratus's actual schema (events[].proc.{name,exe,cmdline,parent_name,
parent_cmdline,ancestors} + bare tactic.id/technique.id/subtechnique.id
labels) into the saved-view renderer's dict.
Whiskers /api/info now reports telemetry_sources: ['fibratus'] when
fibratus.exe is at C:\Program Files\Fibratus\Bin\, so the
orchestrator can preflight before dispatching. wevtutil's single-quoted
attribute output is parsed correctly.
Dashboard reachability cache (services.edr_health). 30s TTL +
background poller every 15s. Per-probe timeouts dropped 4s/5s -> 2s.
First load post-boot waits at most one probe cycle; every subsequent
load <5ms (cache hit).
GrumpyCats package split: 1085-line monolith into:
grumpycat.py — orchestrator (14 lines)
cli/ — parser, handlers, runner
litterbox_client/ — base + per-domain mixins (files, analysis,
doppelganger, results, edr, reports, system)
composed into LitterBoxClient.
LitterBoxMCP.py rewires its one import. New CLI subcommand
fibratus-alerts and matching MCP tool fibratus_alerts_since pull
Fibratus alerts via a LitterBox passthrough endpoint
(/api/edr/fibratus/<profile>/alerts/since) for wire-checking the agent
without dispatching a payload.
CHANGELOG updated.
- New system dashboard at / (live scanner availability + EDR agent
reachability, refreshes every minute). Drop-zone moved to /upload.
- New GET /api/system/scanners endpoint inventories static + dynamic +
holygrail analyzers and reports whether each tool's binary exists.
- Whiskers --install / --uninstall register an ONLOGON Windows
scheduled task so the agent auto-starts at user logon (no UAC, runs
as the invoking user). Forwards non-default flags into the task.
- Whiskers --samples-dir; default drop path is now <exe_dir>/samples/
(auto-created) instead of C:\Users\Public\Downloads\.
- GrumpyCats client + MCP tools picked up the new EDR endpoints
(analyze_edr, get_edr_results/index, list_edr_profiles,
get_edr_agents_status) plus get_scanners_status; new CLI
subcommands edr-run / edr-results / edr-profiles / edr-status /
scanners.
- 'New Analysis' / 'Upload New' buttons in summary + results pages
point at /upload now that / is the dashboard.
- CHANGELOG + Whiskers/README updated for the new flags + auto-start.
When the analysed sample is a `.sys` driver and HolyGrail has been run,
the downloaded report now leads with a HolyGrail BYOVD section instead
of burying it after the dynamic-scan stuff that doesn't apply to
drivers.
- helpers._load_file_data also loads byovd_results.json (when present)
and threads it through `data['byovd_results']` into the report.
- generate_html_report computes a HolyGrail score Python-side (port of
holygrail/core.js's calculateScore) and exposes is_driver_report,
byovd_score, byovd_label, byovd_class, av_killer_imports to the
template.
- For driver reports the hero "Risk Assessment" card swaps to "BYOVD
Potential" with the HolyGrail score and pill, and the chip row
swaps the YARA/PE-Sieve/Moneta/Patriot/HSB counts (all zero on
drivers — they don't run dynamic scans) for LOLDrivers / Win10 /
Win11 / Critical Imports.
- The HolyGrail BYOVD section moves above File Information / Risk
Factors so it's the first thing a defender sees in the report.
- Non-driver reports are unchanged.
Full visual redesign onto a dense terminal/IDE layout: breadcrumb titlebar,
iconed sidebar, optional tab row, IDE-style status bar, JetBrains Mono
throughout, semantic severity palette, and a calm-red rule that reserves
bright red for severity tags, destructive buttons, and the brand dot.
Splits the 1,598-line tools.js into a 66-line registry plus one module per
scanner under app/static/js/results/tools/ (yara, checkplz, stringnalyzer,
pe_sieve, moneta, patriot, hsb, rededr, summary), with shared rendering
helpers in tools/_shared.js. Each module exports
{id, elementId, statsElementId?, render(results, ctx)}, and the registry
does lazy DOM lookups so a module loaded on a page that doesn't have its
tab silently no-ops.
Switches Tailwind from the precompiled v2.2.19 file (~2.8MB) to a v4 build
generated locally by the standalone CLI binary (~284KB). End-user setup is
unchanged: the committed tailwind.min.css ships ready to use; only the
maintainer needs the binary, which lives outside the repo.
Fixes:
- ModalHandler crash on dynamic results pages (null-deref against the old
.bg-gray-900 selector)
- AnalysisCore.updateStageToComplete null-deref against removed
stage-indicator markup
- summary.render silently skipped because elementId pointed at the
removed summaryWrapper div — points at scannerResultsBody now
- Per-tool render failures no longer suppress the rest of the rendering
- Drag-and-drop highlight no longer null-derefs against the removed
.upload-icon selector
- Upload "Unsupported file type" false positive — extensions now sourced
from window.serverConfig instead of DOM scraping
- XSS hardening at user-data interpolation sites in results renderers
Visual unification:
- New :root design tokens + .lb-* component classes in style.css
(cards, buttons, badges, section headers, hash display, empty
state, animated grid backdrop, critical-state pulse).
- holygrail.html and byovd_info.html lose their cyber-themed inline
<style> blocks (567 + 164 lines) and the cyber-card / cyber-chip /
cyber-button / verdict-* classes; both pages now draw from the
shared lb-* vocabulary. The cyber-glow accent is preserved but
applied only on critical/severe states instead of page-wide.
- Templates swept to use component classes: file_info, summary,
results, dynamic_info, static_info, doppelganger, error, upload,
partials/_macros. JS renderers in results/tools.js,
results/renderers.js, and the holygrail/byovd/upload core.js
modules updated to emit the new classes. Risk-level 4-way
conditional in file_info.html collapsed to a single
lb-badge-{{ risk_level|lower }} lookup.
- Bug fix: duplicate .logo-wrapper rule in style.css merged.
Self-contained report (report.html rewritten):
- Drops the https://cdn.tailwindcss.com runtime-JIT dependency and
the inline tailwind.config script. No <script> tags anywhere.
- All CSS inlined in a single <style> block: design tokens, the
subset of lb-* component classes the report uses, and only the
layout rules the report itself needs.
- Hand-written typography and layout: tabular-numeric risk scores,
restrained pill badges, severity-coded detection chips,
generous whitespace, dedicated @media print.
- Status icons use locked SVG dimensions so the green checkmark on
clean scans no longer renders at default-huge size.
- The LitterBox logo is embedded as a base64 PNG data URI so the
brand strip displays correctly when the file is downloaded and
opened offline. Logo sized at 64x64 in the brand strip.
CHANGELOG.md: v4.2.0 entry extended with "UI design system &
visual unification" and "Fully self-contained downloadable report"
sections.
No backend or API changes. Setup story unchanged. No new
dependencies; deploy stays Python-only with the precompiled
tailwind.min.css.