189 Commits

Author SHA1 Message Date
BlackSnufkin a609527c0b Add HTML smuggling analyzer, surface macro detail, split per-type modules 2026-05-05 06:01:58 -07:00
BlackSnufkin 5dbcf6892d Switch RedEdr to source-built EXE v5.0.0 2026-05-04 09:01:22 -07:00
BlackSnufkin f9b2357110 Refresh scanner binaries + restructure YARA rules 2026-05-04 08:56:43 -07:00
BlackSnufkin b156b6a4a1 Report sections expandable, file-prevention alert rendering, save mkdir 2026-05-04 04:55:01 -07:00
BlackSnufkin ac46c3d3b7 Drop /api/system/scanners from CHANGELOG (consolidated into /health) 2026-05-04 02:28:32 -07:00
BlackSnufkin 8a54bdd5d0 Collapse 4 saved-result routes into one handler 2026-05-04 02:21:02 -07:00
BlackSnufkin 964aa71ad7 Unify /health: scanner inventory + EDR agents in one route 2026-05-04 02:11:31 -07:00
BlackSnufkin c7a705ee30 Update demo gif 2026-05-04 01:00:36 -07:00
BlackSnufkin 9d084eba24 Add LitterBox v5 logo banner 2026-05-03 13:31:00 -07:00
BlackSnufkin c79122a4b3 Improve CONTRIBUTING.md 2026-05-03 13:05:50 -07:00
BlackSnufkin d5e9c12871 Untrack release-notes.md 2026-05-03 13:04:10 -07:00
BlackSnufkin 4f1498743c Bump deps for Dependabot alerts 2026-05-03 13:02:24 -07:00
BlackSnufkin 52d844a6d4 Bump deps for Dependabot alerts 2026-05-03 12:59:50 -07:00
BlackSnufkin 717b28ee99 v5 release prep: shrink top-level READMEs, dead-code cleanup, release notes
- README, GrumpyCats/README, Whiskers/README: trim feature dumps; point at the wiki for deep docs
- Whiskers/BUILD.md: folded into Whiskers/README "Building from source"
- HolyGrail analyzer: drop 178 lines of dead code
- Patriot, blender, holygrail, manager: pyflakes-clean unused imports
- Add release-notes.md
2026-05-03 12:46:38 -07:00
BlackSnufkin 892934f23d Frontend perf: saved-view lazy fetch, diff-aware EDR re-render, poll backoff + visibility pause
- Saved EDR view ships a tiny shell + small ref; JSON is fetched lazily — HTML 329KB → 13KB on alert-heavy runs
- EDR alerts table fingerprints IDs into dataset.alertsKey; skips re-render when unchanged; preserves user-expanded rows
- Alert detail bodies built lazily on first expand (data-built flag); collapsed rows skip JSON.stringify of raw _source
- EDR Phase-2 client poll: 2s base, ×1.5 backoff to 15s on consecutive unchanged ticks; reset on movement; stop on terminal
- Dashboard / agents / EDR / analyze-all polls pause on tab hidden, resume + immediate refresh on visible
2026-05-03 07:31:53 -07:00
BlackSnufkin 800d949482 Backend perf: summary cache, hash-dir cache, BYOVD compile_time short-circuit
- /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
2026-05-03 07:21:23 -07:00
BlackSnufkin 193a06d4c9 Parallelize static analyzers, redesign /analyze/all, tidy logging + saved-view
- AnalysisManager: static analyzers run concurrently via a ThreadPoolExecutor;
  dynamic stays parallel for yara/pe_sieve/moneta/patriot, hsb runs solo
  after to keep its sleep-timing measurements clean. Per-tool start +
  finish + wall-time logged so progress is visible.
- /analyze/all redesign: stat tiles (stages / alerts / elapsed),
  phase-banded rows, color-coded state pills, agent-down preflight
  marks unreachable EDR profiles SKIPPED instead of burning the timeout,
  done banner only links to stages that actually produced data.
- file_info hero: buttons fully data-driven — Static / Dynamic /
  HolyGrail / per-EDR-profile only render if the corresponding saved
  JSON exists for the sample.
- analyze_edr no longer writes a JSON for pre-execution failures
  (agent_unreachable / busy / error). The error still surfaces in the
  HTTP response; the saved-view route stops rendering fake results.
- Logging: single root-level handler, compact formatter — HH:MM:SS,
  fixed-width colored level, dim module name with package prefixes
  stripped, werkzeug renamed to http and access lines reformatted to
  METHOD path → status. urllib3 / requests muted to WARNING.
2026-05-03 07:08:44 -07:00
BlackSnufkin e5fd459c69 EDR — cap stdio, gate killed_by_edr on alerts, alert-only DETECTED badge
- AgentClient.get_execution_logs now caps stdout/stderr at 256 KB.
  Prevents the saved-view template from inlining a 263 MB stdout
  (mimikatz spamming the prompt 18M times) and hanging the browser.
- /results/edr/<profile>/<target> route truncates stdio defensively at
  load time so older saved findings render without a re-save.
- _classify_kill (both elastic + fibratus) requires alert evidence for
  ALL payloads, not just DLLs. A non-zero exit alone is not enough —
  payloads crash on their own and Fibratus is detect-only anyway.
- summary.js: DETECTED badge fires only when the run is terminal AND
  total_alerts > 0. killed_by_edr / blocked_by_av / failure / polling
  states only influence the detail string, never the badge.
2026-05-03 04:01:53 -07:00
BlackSnufkin 0c2100b8a5 Docs refresh for Fibratus, dashboard cache, GrumpyCats package split 2026-04-30 05:46:14 -07:00
BlackSnufkin fb52b1432e Add Fibratus EDR profile + dashboard cache + GrumpyCats package split
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.
2026-04-30 05:28:54 -07:00
BlackSnufkin 023b5197a0 Add system dashboard, scanner-health API, Whiskers --install + samples dir
- 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.
2026-04-30 03:37:14 -07:00
BlackSnufkin 96ced766e6 Add 'All' pipeline + EDR saved-view + Whiskers chunked XOR
- New 'All' analysis mode: client-side coordinator runs Static + every EDR
  profile in parallel; Dynamic waits only for Static (EDR is on a remote
  VM, no local resource contention). New /analyze/all/<target> route +
  analyze_all.html + analyze-all/core.js. Done banner exposes per-result
  jump links; rows linkify to their saved detail views (no auto-redirect).

- /results/edr/<profile>/<target>: saved-view route that loads the saved
  JSON and renders via the same tools/edr.js module the live page uses,
  so the saved view shows MITRE chips, call stack, triggering API,
  memory region, expandable per-alert detail and raw _source. New
  edr_info.html embeds findings as window.__edrSavedResults; new
  edr-saved.js bootstraps the renderer.

- Whiskers: chunked XOR write (64 KiB working buffer) replaces the
  byte-by-byte loop that was timing out the orchestrator on multi-MB
  payloads. AgentClient gains a separate exec_timeout (180s) for the
  multipart upload + agent-side decode path.

- file_info.html: Dynamic button uses lb-btn-primary to match Static and
  EDR (drops the orphan yellow styling).
2026-04-30 02:52:55 -07:00
BlackSnufkin d30ee2469d Summary/file-info: drop EDR from risk score, fix badge color via lb-tag 2026-04-30 01:57:26 -07:00
BlackSnufkin 532f2bfe45 Summary page: include EDR runs in /files aggregation + per-row badge 2026-04-30 01:49:37 -07:00
BlackSnufkin 4857d157f1 Refactor /results/* + /api/results/* to put type before target 2026-04-30 01:43:22 -07:00
BlackSnufkin 966d14104c EDR: XOR-on-the-wire, DLL via rundll32, Whiskers page, kill-detection fix 2026-04-30 01:27:51 -07:00
BlackSnufkin 36eab29536 Add Elastic EDR integration (Whiskers agent + orchestrator) 2026-04-29 14:57:38 -07:00
BlackSnufkin 5759d76296 Maximize RedEdr telemetry extraction 2026-04-29 03:40:59 -07:00
BlackSnufkin 78485740a0 Update CHANGELOG.md 2026-04-29 01:46:09 -07:00
BlackSnufkin e2f192720a Adjust colors to softer palette 2026-04-29 01:23:15 -07:00
BlackSnufkin 75ec5a8e05 Shift UI terminology toward operator-flavored, observation-based language
Reframes verdict/score language across templates, JS renderers, MCP and
GrumpyCats client docs so findings read as feedback on the operator's own
payload rather than threat judgments. Risk Score becomes Detection Score,
Risk Factors becomes Triggering Indicators, Suspicious Imports becomes
Sensitive Imports, CheckPlz "Threat detected" becomes "Signature triggered",
HolyGrail "Dangerous Imports" becomes "Critical Imports". Dynamic-analysis
warning modal on the static results page now accepts command-line arguments
(pre-populated from last run) and persists them via localStorage, matching
the upload-page flow.
2026-04-28 08:01:48 -07:00
BlackSnufkin 75b40ff693 Update CHANGELOG.md 2026-04-28 06:33:31 -07:00
BlackSnufkin 4922a72c13 Modernize GrumpyCats clients and address upstream issues
GrumpyCats:
- grumpycat.py: replace the 130-line if/elif chain in main() with a
  COMMAND_HANDLERS dispatch table (each subcommand is now a small
  _cmd_* function), parallelize get_comprehensive_results across a
  ThreadPoolExecutor (4 reads in ~one round-trip instead of four),
  add get_risk_assessment for the new /api/results/<target>/risk
  endpoint, drop the unused _file_cache, dead imports
  (hashlib, Tuple, Any), and the unreliable __del__.
- LitterBoxMCP.py: full rewrite onto modern FastMCP. Fixes broken
  import (was pointing at optimized_litterbox_client), replaces the
  removed mcp.serve(host=..., port=...) API with mcp.run(transport=...),
  routes logs to stderr (required for stdio transport), drops the
  handle_api_operation try/except envelope (FastMCP converts
  exceptions to MCP errors automatically), drops the
  LitterBoxMCPClient indirection, makes every tool async with
  asyncio.to_thread, adds Annotated[..., Field(description=...)]
  parameter docs, drops shutdown_client (server lifecycle isn't an
  LLM concern), defaults bind to 127.0.0.1, and trims the 5
  150-200-line OPSEC prompts to 4 focused 15-25-line ones.
- install_mcp.py: new installer modeled on ida-pro-mcp's approach.
  Auto-detects the project venv Python, supports six clients
  (claude-code project + global, claude-desktop, cursor, windsurf,
  vscode-project), idempotent JSON merge that preserves existing
  MCP servers, atomic .tmp+rename writes, dependency check that
  warns if mcp/requests are missing. --list / --install / --uninstall
  / --print modes.
- README.md: rewritten to match — three-component framing, accurate
  dependency list (mcp + requests, not the fictional fastmcp
  package), full installer reference, current 22 MCP tools and 4
  prompts.

Upstream issues + small fixes:
- app/static/js/upload/core.js: wire up the missing
  macroDetectionNotes element (upstream issue: scanning .xls files
  threw "can't access property 'innerHTML', elements.macroDetectionNotes
  is undefined").
- app/templates/report.html: Stringnalyzer section now expands every
  non-empty bucket (URLs, IPs, domains, file paths, etc.) into a full
  code block instead of showing a truncated 3-item, 140-char sample.
  Categories expanded from 7 to 16, capped at 100 items per category
  with "and N more" overflow.
- app/blueprints/api.py: /api/results/<target>/risk endpoint
  returning {risk_score, risk_level, risk_factors} (upstream PR).
- app/templates/dynamic_info.html: Process Telemetry summary panel
  no longer mixes a flush chip-row with an inset 3-column kvgrid;
  uses the lb-hash-row label/value pattern instead and surfaces
  image_path + commandline when RedEdr provides them.
2026-04-28 06:09:47 -07:00
BlackSnufkin 921be01911 Tailor downloadable report for driver samples
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.
2026-04-28 04:08:07 -07:00
BlackSnufkin 9ee58ad618 Tidy UI shell and fix scope-mismatched detection counts on summary pages
Shell:
- Brand (logo + name) moves from sidebar header into the titlebar so the
  top-left reads `[logo] LitterBox | <breadcrumb>` instead of having two
  separate brand strips.
- The bottom IDE-style status bar is removed; it duplicated the
  sidebar-foot status indicator. The sidebar foot now also shows the
  version on the right (`[dot] Active                v5.0.0`).
- Titlebar height bumped 36 → 44px and the brand mark to 28px so the
  logo has breathing room and balances the wordmark.
- file_info header: Back / Static Analysis / Dynamic Analysis buttons
  consolidated into the panel header on the right. Dynamic gets a
  yellow border to flag that it executes the payload.

Bug fix:
- /results/<hash>/static was rendering YARA as "Suspicious" with a
  matching count even when the static scan returned zero matches. Cause:
  RouteHelpers.get_detection_counts(data) prefers `dynamic_results` if
  any dynamic scan exists, so the static page was rendering its row
  count from the dynamic scope while the row's match list came from the
  static scope. render_analysis_info now extracts counts from the actual
  analysis_results being rendered.

Misc:
- Drop unused .lb-tb-right, .lb-tb-version, .lb-sidebar-brand, and all
  .lb-statusbar* rules from style.css; remove dead statusbar_left block
  override in error.html.
- Bump app version to 5.0.0 in Config/config.yaml.
2026-04-28 03:30:01 -07:00
BlackSnufkin ff4f2ca2e2 Redesign UI on terminal/IDE shell with per-tool scanner modules and Tailwind v4
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
2026-04-28 02:42:12 -07:00
BlackSnufkin f0ab1323a5 Unify UI design system and rewrite the downloadable report
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.
2026-04-27 07:50:55 -07:00
BlackSnufkin d53359174d Add v4.2.0 changelog entry 2026-04-27 06:46:39 -07:00
BlackSnufkin ce9a926246 Refactor backend into blueprints/services/utils package and frontend into ES6 modules
Backend (Python):
- Split app/routes.py (1,389 lines) into 6 Flask blueprints (upload, analysis,
  results, doppelganger, management, api) under app/blueprints/, plus
  service modules (rendering, summary, tool_check, error_handling) under
  app/services/, and the shared RouteHelpers class in app/helpers.py.
  app/__init__.py wires shared deps via app.extensions['litterbox'].
- Split app/utils.py (1,400 lines) into the app/utils/ package with
  single-concern modules: file_io, validators, path_manager, risk_analyzer,
  forensics, json_helpers, reporting. No facade — every caller migrated.
- Extracted BaseSubprocessAnalyzer in app/analyzers/base.py; refactored 9
  subprocess analyzers (yara/checkplz/stringnalyzer static; yara/pe_sieve/
  moneta/patriot/hsb/hollows_hunter dynamic) as thin subclasses that only
  declare config + implement _parse_output.

Frontend (JS):
- Split results.js (2,060), holygrail.js (1,025), byovd_info.js (1,069),
  and upload.js (974) into per-concern ES6 modules under
  app/static/js/{results,holygrail,byovd,upload}/.
- Added app/static/js/utils/ with shared helpers: escape, formatters,
  severity, fetch, modals, dom (single source of truth for escapeHtml,
  formatBytes, severity-color mapping, etc.).
- Converted base.js, summary.js, blender.js, fuzzy.js to ES6 modules;
  every <script> tag now uses type="module". window.X assignments preserved
  so inline onclick handlers in templates keep resolving.
- Targeted XSS hardening at user-data interpolation sites in results
  renderers (str.data, hex_dump, scan_info.target, list items).

Templates:
- New app/templates/partials/_macros.html with reusable scanner-table
  macros + 3-card status grid; static_info.html and dynamic_info.html
  migrated to use them, eliminating identical-HTML duplication.

CSS:
- Fixed broken @apply in .drag-over (no Tailwind build pipeline → @apply
  was silently ignored, leaving drag-and-drop visual feedback broken).
  Replaced with raw CSS equivalent.
- Dedented stray 8-space-indented block (lines 127-end) for consistency.
- Added header comment documenting the no-build-pipeline constraint.

Gitignore:
- Anchored Results/, Uploads/, DoppelgangerDB/Blender/, and Scanners/*
  patterns to repo root with leading slash so they don't shadow same-
  named directories elsewhere (notably the new app/static/js/results/
  module directory and app/blueprints/results.py).
- Added /Scanners/PE-Sieve/process_*/ for runtime scan artifacts.
2026-04-27 06:41:19 -07:00
BlackSnufkin cca74069c8 Add badge for Ask DeepWiki to README 2025-11-12 15:30:28 +02:00
BlackSnufkin 45d1ab5ab9 LitterBox v4.1.0 2025-09-06 23:48:58 +03:00
BlackSnufkin 6c78acc300 LitterBox v4.1.0 2025-09-06 23:48:03 +03:00
BlackSnufkin 5ce9b5c4b4 LitterBox v4.1.0 2025-09-06 12:37:18 -07:00
BlackSnufkin 67edc0f87f Merge branch 'main' of https://github.com/BlackSnufkin/LitterBox 2025-09-06 12:33:50 -07:00
BlackSnufkin e3d286163e LitterBox v4.1.0 2025-09-06 12:33:45 -07:00
BlackSnufkin ef66d7fa33 LitterBox v4.1.0 2025-09-04 10:19:13 +03:00
BlackSnufkin 3c9bb5b296 LitterBox v4.1.0 2025-09-02 08:19:00 -07:00
BlackSnufkin 1d09d279d7 LitterBox v4.1.0 2025-09-02 07:40:13 -07:00
BlackSnufkin 01df8eb099 LitterBox v4.1.0 2025-09-02 07:36:52 -07:00
BlackSnufkin a40b354f68 Update README.md 2025-08-31 23:00:18 +03:00