Repository navigation
Releases: pisentry/pisentry
Releases · pisentry/pisentry
Release list
pisentry v0.2.0
[0.2.0] - 2026-11-01
Upgrading from v0.1.0
- New image location: images publish to
ghcr.io/pisentry/pisentryfrom this release. Update image references and tag overrides, and pin by digest - Go module path: imports change from
github.com/MrGuato/pisentrytogithub.com/pisentry/pisentry proc.miner_names: now adds names to the built-in list instead of replacing it. Check any override you set- Deprecated
fieldskeys: move queries and alerts to the typed entity groups beforev0.3.0, which removes the old keys - Security fixes: three fixes for forged log lines are listed under Fixed
Added
- Every event follows Event Schema v1: events now carry
id(UUIDv4),schema_version(1) and typed entity groups (process,source,user,file,container,rule), with OCSF and ECS mapping tables - Signed releases with Sigstore cosign: images are signed keyless by digest, and
SHA256SUMSships with a Sigstore bundle (SHA256SUMS.sigstore.json, requires cosign 3.0 or later). Verification steps are in SECURITY.md - Your own detection rules: Rule Schema v1 and a strict JSON rule loader (
internal/rules,docs/rule-schema.md). Rules use Sigma-aligned field names, match on Event Schema v1 fields with literal operators kept apart from RE2 regex, and take per-rule exceptions by exe, parent comm, uid, user, container image, CIDR, path and command line. Unknown fields, duplicate IDs, bad regexes, unknown categories and oversize input are rejected, never truncated - Built-in rules embedded in the binary:
deploy/rules/default.jsonholds the eight risky-sudo patterns (PS04-SUDO-*) and the miner name and pool argument lists (PS06-MINER-*), each with an ID and MITRE techniques. Shell names, stratum ports, backdoor ports, the FIM watch list, GTFOBins SUID names, package managers and privileged groups move into the bundle'scatalog. Events from a rule carryrule.id,rule.titleand its techniques - Operator rule bundles in rules.d:
rules.dir(default/etc/pisentry/rules.d, envPISENTRY_RULES_DIR) loads operator bundles over the built-in rules. A rule with a built-in ID replaces it, which is how exceptions are added to a built-in rule. A broken bundle is logged at startup and the agent runs on the built-in rules - Rules reload without a restart (#13): on SIGHUP (
systemctl reload pisentry, the unit now hasExecReload) and whenrules.dchanges, checked everyrules.reload_interval(default10s). The new set is validated in the background and swapped atomically; a broken file keeps the previous set active, logs the error and raises a High PS00 event. The directory is watched through symlinks so Kubernetes ConfigMap updates are seen, and a burst of changes is debounced into one reload. New metricspisentry_rules_loaded,pisentry_rules_last_reload_timestamp_secondsandpisentry_rules_reload_failures_total - Rule validation with pisentry check:
pisentry check [-rules PATH]validates bundles and, on an invalid one, exits 1 naming the file, rule and field - Process rules beyond cryptominers: process rules outside PS06 (for example from a rule pack) are reported under their own category, and rules can match on
process.uidandprocess.parent_comm - Positive and negative fixtures per rule: under
internal/rules/testdata/rules/<rule-id>/, replayed bygo testwith no root. The test fails when a rule lacks either kind - Prometheus alert rules shipped (#26):
deploy/prometheus/pisentry-rules.yamlfor a plain Prometheus and aPrometheusRulein the Kubernetes base. Alerts cover agent down or absent, a node with no agent (Kubernetes), critical and high events, stale detectors (fast and slow tiers), detector errors, dropped alerts and rejected rule reloads, each with a one-line runbook annotation.promtoolunit tests inpisentry-rules.test.yaml; CI runspromtool check rules,promtool test rulesandkubeconformagainst the CRD schema. A Go test fails if the two copies drift or an alert references a metric that does not exist - Grafana dashboard alert panels: "Firing pisentry alerts", "Rules loaded" and "Rule reloads rejected (24h)"
- Fuzzing of every attacker-facing parser (#32): syslog lines, journal JSON,
/proc/<pid>/stat,/proc/net/*, the sanitizer (engine.Truncateproperties), and the auth and port-scan matchers end to end through the engine with Event Schema v1 validation.make fuzz, 30 seconds per target on every pull request and 10 minutes per target weekly (.github/workflows/fuzz.yml) - Fuzz target for the rule loader:
FuzzLoadBytes - CodeQL analysis of the Go code: runs on every push to main, every pull request and weekly, with results in code scanning. Badge in the README
- OpenSSF Scorecard: runs weekly and on every push to main, with results published to scorecard.dev and uploaded to code scanning. Badge in the README
- Attack simulation in a container, no root needed:
make sim(scripts/sim-container/) runs the agent in apython:3-slimcontainer with file-mode logs and short detector intervals, fires harmless stand-ins for the eight simulatable categories, writesevents.jsonl,report.json,metrics.txtandtop10.json, and exits non-zero unless all eight fired - README demo GIFs from real runs:
make demo(scripts/demo/) records live detection in a split terminal, the posture audit and a rule hot reload. The Grafana screenshot is re-rendered with a real Prometheus evaluating the shipped alert rules - Grafana screenshot from the simulation:
docs/assets/grafana-top10.png, the bundled dashboard rendered from the container simulation - Project website with a live roadmap: https://pisentry.dev/ (
site/), built byscripts/build-site.pyand published by thepagesworkflow. The roadmap and the live numbers are rendered from the GitHub API at build time, so the pages make no requests of their own. The pages rebuild when a milestone or a roadmap issue changes
Changed
- The project moved to the
pisentryGitHub organization and its own domain. The repository is nowgithub.com/pisentry/pisentry(old URLs redirect), the Go module path isgithub.com/pisentry/pisentry, images publish toghcr.io/pisentry/pisentrystarting with this release, and the website is https://pisentry.dev/. The v0.1.0 image stays atghcr.io/mrguato/pisentry - Kubernetes manifests pin the image by release digest instead of by tag, and the staging overlay comment shows a digest override
proc.miner_namesnow adds names on top of thePS06-MINER-KNOWN-NAMErule instead of replacing the built-in list, and its default is empty.proc.stratum_portsandproc.shell_namesstill replace the built-in lists when set- The SUID walk and the posture audit resume their 6-hour schedule after a restart instead of running again on every start. The last run time is saved with the baselines, so
pisentry baseline resetstill forces a fresh scan. On a Pi that kept restarting, the repeated walk filled the page and inode cache, and the agent's own reads stalled other workloads on the same SD card - The SUID walk runs at idle disk priority so it yields to databases sharing the disk
- Memory cap 96 MiB -> 256 MiB in the systemd unit (
MemoryMax) and the Kubernetes DaemonSet. The process still uses about 12 MB; both caps also count the kernel dentry/inode cache from the walks, and 96 MiB could be filled by that cache alone - DaemonSet liveness probe: timeout 1s -> 5s, failureThreshold 3 -> 5, so a slow SD card does not get the agent killed
pisentry_events_total{category="PS00",severity="high"}is pre-created at 0 like the Top 10 series, soincrease()sees the first operational event. The dashboard's attack panels exclude PS00- README and website state the new cap, and the FAQ describes the v0.1.0 restart loop on a control-plane Pi
Deprecated
v0.1.0entity keys insidefields(pid,ppid,comm,exe,cmdline,command,src_ip,port,user,uid,owner_uid,path,old_sha256,sha256,check) are superseded by the typed entity groups (process.*,source.*,user.*,file.*,rule.*). They remain populated infieldsthroughv0.2.xand will be removed inv0.3.0
Fixed
- A forged sshd log line with a port above 65535 produced an event with an out-of-range
source.portthat failed Event Schema v1 validation. Out-of-range ports are now dropped. Found byFuzzAuthHandle - In file mode, a forged kernel firewall line with a
SRC=that is not an address or aDPT=above 65535 could raise a PS09 event that failed Event Schema v1 validation. Such lines are now ignored. Found byFuzzPortScanHandleafter 8 minutes - The event
key(the cooldown de-duplication key) was the one attacker-influenced string the sanitizer did not touch. The sudo detector keys on the command line, so a forged sudo log line produced a multi-kilobyte key with terminal escapes and invalid UTF-8, breaking Event Schema v1's 512-byte limit, and up to 5000 such keys could sit in the cooldown map. Keys are now sanitized and capped at 256 bytes, with a hash of the full key appended when cut so distinct commands still cool down separately. Found byFuzzAuthHandleafter 10 minutes
pisentry v0.1.0
0.1.0 - 2026-10-15
First release.
Added
- Ten detection categories, PS01 to PS10: SSH brute force, suspicious login, insecure posture, privilege escalation, persistence, cryptominers, unexpected listeners, reverse shells, port scans, critical file tampering. Each event carries MITRE ATT&CK technique IDs
- Detectors for journald and classic syslog files,
/procpolling,/proc/1/netlisteners, file integrity with package-manager awareness, a SUID/SGID walk and a posture audit - Learning period, persistent baselines, alert-once-then-adopt, per-key cooldown, and one sanitizer for every attacker-controlled string
- Outputs: ranked Top 10 terminal report, JSON events on stdout or to a file, Prometheus metrics on
:9817, a small HTTP API, and webhooks for ntfy, Discord, Slack and generic JSON with rate limiting and a separate Critical budget - Commands:
run,report,audit,baseline reset,test-alert,categories - Hardened systemd unit and an installer for Raspberry Pi OS, Ubuntu, Debian and RHEL-family hosts
- Distroless multi-arch image (arm64, armv7, amd64) with provenance and SBOM
- Flux-ready Kubernetes manifests: DaemonSet, NetworkPolicy, PodMonitor, Grafana dashboard
- Safe, self-cleaning attack simulation script