v1.1 — payload dedup, memory caps, diagnostics
Maintenance release. Drop-in upgrade from v1 — no config changes, no schema breaks (migration v3 runs automatically on first start).
Payload library: deduplicated by SHA-256
The payload library previously rendered one row per artifact INSERT, so a single binary delivered via N rotated URLs from M source IPs appeared as N visually identical rows. In a 7-day window the table was 200 mostly-duplicate rows for ~80 unique payloads (the top SHA, an Outlaw SSH key, alone accounted for 462 of 893 captures).
store: newListArtifactsAggregatedSincereturns one row per unique sha withoccurrences,urlCount,ipCount,actorCount,sessionCount, plus the most-recent capture metadata asLast{URL,SrcIP,Actor,Session,TS}. Portable SQL: CTE + correlated subqueries, no window functions./api/intel/payloads: response keepsurl/actor/session/srcIp/tskeys (now last-seen) for backward compatibility and addsfirstTs,occurrences,urlCount,ipCount,actorCount,sessionCount./api/intel/payloads?limit=>1000now clamps to 1000 instead of silently falling back to 200./api/intel/sessionsaccepts?limit=(default 200, ceiling 2000) instead of being hard-coded at 200 — the session panel was losing ~367 of 567 command-bearing sessions in a 7-day window.- Dashboard: payload table gains a
deliverycolumn showingNx · Mip; the meta line readsN unique · M captures · Wh windowso the dedup story is visible at a glance.
Memory: bound the live collector + geo cache
Across ~2.5 days of uptime, RSS peaked at 1.6 GB. The cause was two unbounded in-memory structures: the live SSH journal collector accumulated per-IP user maps across thousands of attacker IPs × hundreds of distinct usernames each, and the web geo-resolver cache never evicted.
actor.liveJournalCollectorreplaces the unbounded collector:- LRU cap of 4096 distinct source IPs.
- Per-IP user-map cap of 256 keys; overflow rolls into an
_overflow_synthetic bucket so aggregate counts stay accurate. - Idle-TTL sweep at 12h (opportunistic, ≤4 evictions per insert).
- DB hydration on re-entry: when an evicted IP returns,
store.LoadJournalIPStats(ip)loads persisted counters before the next upsert, so the running total is preserved across in-memory eviction cycles.
web.geoResolver.cachebecomes an LRU capped at 4096 entries (override viaSHARDLURE_GEO_CACHE_MAX), with promotion on hit and opportunistic expiry sweep on insert.
Expected ceiling at saturation is now in the low tens of MB rather than unbounded. Verified on the Oracle ARM honeypot: sys=29.8 MB, heapAlloc=2–3 MB, 15 goroutines, flat across sampling.
Diagnostics endpoints
All gated behind the existing dashboard token (SHARDLURE_DASH_TOKEN); same auth as the rest of /api/intel/*.
/debug/pprof/{,cmdline,profile,symbol,trace}fromnet/http/pprof./debug/runtimereturns a JSON snapshot ofruntime.MemStatsplus bounded-cache sizes (liveJournalCollectorIPs,geoCacheEntries, etc.).- HTTP
WriteTimeoutraised from 20s to 60s so/debug/pprof/profile?seconds=30completes.
Other
Carried forward from the live-capture branch since v1:
web: TTY transcripts decoded and surfaced in the intel session modal; shell-session panel populated from live capture; command-column scrub for noisy CRLF.store: migration v3 normalizescommandto''instead ofNULLso downstream JOINs/aggregations don't drop rows.scripts/install.sh: auto-detects architecture, downloads the matching binary from this release, and provisions the systemd unit.--tagoverrides the auto-resolved latest.
Install
curl -fsSL https://github.com/hett-patell/ShardLure/releases/download/v1.1/install.sh | sudo bash
Or pin explicitly:
sudo TAG=v1.1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/hett-patell/ShardLure/v1.1/scripts/install.sh)"
Upgrade from v1
Stop the service, replace the binary, restart:
sudo systemctl stop shardlure-live
sudo install -m 0755 shardlure-linux-$(uname -m | sed s/x86_64/amd64/;s/aarch64/arm64/) /usr/local/bin/shardlure
sudo systemctl start shardlure-live
Migration v3 runs automatically. No config changes required.
Full changelog
f8890db actor/web: bound live collector + geo cache, gate pprof behind dash token
4166e1c web/store: aggregate payload library by sha256
658bf67 web: surface decoded TTY transcripts in the intel session modal
6001fbe store: migration v3 sets command='' instead of NULL
1e17e5b live capture: TTY transcripts, shell-session panel, command-column scrub
2ec42ef foundation: add CONTRIBUTING, SECURITY, COC + README badges and ecosystem footer
95056ef add install.sh: auto-detect arch, download binary from release, setup systemd