Release Notes
3.0.0
Suricata upgraded to 8.0.6
SO-CRATES now installs Suricata from Debian's trixie-backports repo
(8.0.6) instead of the base trixie repo's 7.0.10, along with
suricata-update 1.3.8 (fixes a real security issue — arbitrary file write
via path traversal in rule archive extraction, OISF redmine #8633). This
applies to both the Dockerfile and bare-metal installs.
Critical fix that came with the upgrade: Suricata 8 silently changed DNS
logging to a new default format — dns.rrname/dns.rrtype, read directly
by every DNS column in the UI, no longer exist at the top level at all (the
same data moved to dns.queries[0]). This broke the dns tab completely
(Query/Type went blank) — one of the highest-volume, most-viewed tabs in the
app. Fixed with a fallback that keeps working for previously-stored
analyses from Suricata 7 too.
New and fixed protocol support
- enip and ntp now produce real events — Suricata 7.0.10 detected both correctly but had no eve-log output module for either, so nothing ever reached the UI regardless of config. Both work now that Suricata 8 ships the loggers.
- websocket, pop3, mdns, ldap — full column, filtering, and aggregation support for these protocols, new in Suricata 8.
- arp — decode-layer logging support added, but kept off by default
(Suricata's own stance: "many events can be logged"). A live test across
35 sample captures showed ARP at up to 12% of events in a realistic
multi-host capture. Set the
ENABLE_ARP_LOGGINGenvironment variable to opt in. - 18 previously-enabled-but-unsupported Suricata protocols gained full
column/aggregation support for the first time (previously falling back to
a generic 6-column view): quic, dhcp, ftp_data, smb, ssh, krb5, sip, snmp,
mqtt, http2, dcerpc, rdp, tftp, ike, nfs, rfb, bittorrent_dht, smtp — plus
ftpandanomaly, which predated this work but had the same gap. - Fixed real data-shape bugs found while verifying against real traffic:
quic.ja3/ja3sare objects ({hash, string}), not plain strings — previously rendered as the literal text[object Object].rfb.client_protocol_version/server_protocol_versionare{major, minor}objects, andsecurity_typeis nested underauthentication, not top-level.anomaly.messagewas read in three separate places (a field that has never existed in Suricata's eve.json) — the real field isanomaly.event.- HTTP/2 traffic (including cleartext h2c) is always logged by Suricata
under
event_type: "http", never a separate"http2"type — removed dead code that assumed otherwise; real HTTP/2 traffic already renders correctly under the existinghttptab.
- Fixed a Suricata config-generation bug: re-running setup on an already-provisioned install could silently stop adding any newly-added protocol to eve-log output, once earlier protocols had already been inserted.
Performance & scalability
- Aggregation tables and the Sankey diagram are now computed server-side
(
GET /api/aggregation-data,GET /api/sankey-data) via SQLGROUP BY, scaling with the query instead of the full dataset size, with unfiltered results cached per-analysis. - Uploads are now parsed as a stream instead of buffered in memory — peak memory no longer scales with upload size. Leftover temp files from an upload interrupted by a server crash are now swept on the next startup.
- Upload size limit raised from a fixed 1,000 MB to a user-configurable ceiling (up to 5,000 MB hard max) via Settings; a disk-space check now runs before accepting an upload.
- Query result limit raised from 5,000 to a user-configurable ceiling (up to 100,000 hard max) via Settings.
UI
- 20 new themes (25 total, up from 5), grouped into Dark / Fun / Light
sections in the gear menu, each with its own favicon — including three
new Fun themes: CGA (classic 4-color CGA Palette 1 High-Intensity —
black background, cyan/magenta/white), C64 (Commodore 64 blue-on-blue
aesthetic, using the real Pepto/VICE C64 16-color palette — blue
background, light-blue border/text/accent, including the header's
"SO-CRATES" logo, for a deliberately flat, monochrome resting look, with a
distinct cyan
--interactive-highlightfor hover/focus/active borders so those states are still visible), and Vaporwave (a modern, non-retro counterpart to the other three — dark purple/navy background with hot-pink accents and cyan/mint/pastel-yellow highlights, evoking the 2010s+ vaporwave internet aesthetic rather than nostalgia for old hardware). - The active theme is now marked with a checkmark in the gear menu.
- Each Fun theme (C64, CGA, Hacker, Sguil, Vaporwave) now has its own typed cheat code — type it anywhere outside a text field to switch instantly. See Themes for the codes.
- The gear menu's Fun Themes section now appears after Light Themes
instead of between Dark and Light (
THEME_GROUP_ORDERinstatic/socrates.jsis now['dark', 'light', 'fun']); thethotkey cycle follows the same updated order. - CGA's header/footer text (the "SO-CRATES" logo, tagline, filename, and date/MD5 metadata) is now the CGA magenta accent instead of black/dark teal, matching the rest of the CGA palette more closely.
- Sguil's expanded data-table rows had mismatched field backgrounds:
when a light-blue zebra-striped row (
nth-of-type(4n+3)) was expanded, each field's value box stayed stark white instead of matching the light-blue row, looking like a patchwork of mismatched boxes..detail-valuenow follows the row's light-blue background in that case;.detail-labelintentionally keeps its own light-cyan background on every row.
Documentation
- Docs now live on a real site (MkDocs Material, deployed to GitHub Pages)
instead of a single growing README plus a handful of unlinked
docs/*.mdfiles.README.mdis now a short landing page (tagline, a screenshot, and links out to the docs site); everything else — installation (Docker/Podman/OhMyDebn/Manual), usage, themes, configuration, security, architecture, the API reference, and the filtering design doc — is now properly cross-linked, searchable, and navigable instead of split across files with no shared nav. - The Themes page shows a real screenshot of every one of the 25 themes, grouped under Dark/Fun/Light headings, click-to-zoom.
- Added
scripts/capture_screenshots.pyto regenerate every docs screenshot in one run against the app's own built-in sample pcap — no local fixture or hardcoded analysis needed. - Added a recorded demo video (
scripts/record_demo.py, Playwright) to the Home page, walking through a sample analysis end-to-end: upload, each data tab, All Events, Aggregation Tables filtering, drill-down, ASCII Transcript, and Hexdump. Published as an H.264/AAC MP4 (re-encoded from Playwright's raw WebM capture) rather than WebM directly, since MP4 is universally browser-supported and is also the format required to upload the same clip directly to X/Instagram/LinkedIn/Facebook. - The Architecture page is now split into focused subpages (Overview, Data Storage, Database, Event Types, UI, Security Model, Test Coverage) instead of one long page, matching Installation's existing Overview/Docker/Podman/OhMyDebn/Manual split.
- Went through every docs page and verified its claims directly against current source rather than trusting what the docs already said — fixed real drift in the API reference (missing endpoint, wrong response shapes, a fictional error code), the security page, the architecture page, and several others (stale file-layout diagrams, wrong config defaults, stale test/column counts).
Other fixes
- CGA theme's borders read as dark green instead of cyan: every
border/panel-outline in the app was driven by
--bg-hover, which also doubles as the hover-state background fill. CGA's--bg-hover(#004040) had equal green/blue channels at low brightness — green dominates human luminance perception far more than blue, so the color skewed green-looking despite being a "pure cyan" hue numerically. Fixed properly by splitting borders into their own--border-colorvariable, distinct from--bg-hover: CGA's--border-coloris now the real CGA light-cyan RGBI value (#55ffff, verified by sampling pixel colors from an actual CGA Palette 1 High-Intensity game screenshot), while--bg-hoverstays a muted#008080teal so hover-state fills don't get uncomfortably bright behind white text. Every other theme sets both variables to the same value they always rendered as, so this is a no-visible-change refactor for the other 22 themes. - CGA header/footer now use bright light cyan instead of near-black: the
dark
--bg-secondarybackground shared with every panel/card was making the header and footer blend into the rest of the black-on-teal UI in a way that read poorly. CGA's.app-header/.footernow use the real CGA light-cyan background (#55ffff) directly, with--text-bright/--text-mutedswitched to dark colors scoped to that same rule for legibility. The gear dropdown menu (a child of the header in the DOM, but rendered on its own dark panel) resets those two variables back to their normal light values so its own text doesn't inherit the header's dark override. - Dead CSS custom properties removed:
--accent-rgband--filter-bar-bgwere defined identically in all 23 theme blocks but never referenced anywhere viavar(--name)in CSS/JS/HTML. Removed, with a test (test_dead_theme_vars_removed) to keep them from quietly coming back. (--border-colorwas briefly removed alongside these for the same reason, then reintroduced with the real purpose described above.) - Upload disk-space check used the wrong number:
/api/upload's upfront disk-space check was sized against the rawContent-Lengthof the request, not the resolved upload-size ceiling (effective_max) — a compressed upload (e.g. a ZIP) can have aContent-Lengthfar smaller than what it's allowed to expand to, so the check could pass even when there wasn't really enough room./api/load-urlalready checked againsteffective_max;/api/uploadnow does too. - Load-from-URL password gap:
/api/load-urlonly ever tried the MTA-style dated password (infected_YYYYMMDD) when a URL's path matched/YYYY/MM/DD/onmalware-traffic-analysis.net— any other password attempt was skipped entirely, unlike/api/upload, which always tries the plaininfectedpassword regardless of source./api/load-urlnow always triesinfectedtoo (cheap, harmless even when it doesn't apply), trying the MTA dated variant first when the URL matches. - Fun-theme cheat codes shorter than 5 characters (e.g.
cga) only ever matched in the first few keystrokes after page load, since the keystroke buffer they were checked against stays a fixed 5 characters once filled and the check used===instead of.endsWith(). Fixed for all three codes (cga,31337,sguil). - The Welcome modal's help text had a hardcoded
Maximum file size is 1000MB.string that never reflected reality once upload size became user-configurable (see Performance & scalability, above) — a user who'd raised their own ceiling in Settings still saw the stale default with no indication it was adjustable. Now computed from the user's actual effective limit each time the modal opens. extractAllValue()'s'Command'/'Message'column overrides were stale and actively wrong —Commandignored pgsql/enip/pop3's own real command fields in the "All Events" view, andMessageread the same never-existedanomaly.messagefield. Both removed in favor of the already-correct per-protocol handling.- Fixed the equivalent
anomaly.messagebug in the event detail side panel. docs/FILTERING.md's "Column Overlap" reference table, which had grown stale over many protocol additions, now points at the actual source of truth (getColumnsForType()) instead of duplicating an ever-drifting list.- Podman Compose deployment bug:
docker-compose.podman.yml'suser: "${UID}:${GID}"silently resolved to an emptyuser: ":"when following the README's exact instructions, since bash doesn't export$UID/$GIDby default - this forced the container to run as root instead of the current user, defeating the whole point of theuserns_mode: keep-idvolume-permission mapping. Confirmed by actually building and running the image. README now has users write a.envfile instead of relying on a shell export, sincepodman composereads that automatically from any terminal, including for a laterdown/restart.