bastion 0.53.2
ci / personal-data (push) Successful in 5s
ci / test (push) Successful in 3m4s
ci / fuzz (push) Successful in 3m45s

This commit is contained in:
Privatae
2026-10-20 04:42:14 +00:00
commit e4c9b69b46
471 changed files with 159794 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
//go:build linux
package main
// Every process, not only the ones a signature table already recognises.
//
// THE DEFECT THIS FIXES DEFEATED THE FEATURE. The baseline is meant to walk
// the box and account for every pid. It was built from
// scanAgents(), which is signature-FILTERED — it returns a known agent binary,
// an interpreter-wrapped agent, or a process caught talking to a model
// (agents.go:248-252). So the accounting of "what is normal here" contained
// only things already recognised as agents.
//
// Follow that through and the whole detection story collapses: a brand-new
// unknown binary — precisely the rogue process the product exists to catch — is
// not in the baseline, and the delta built on that baseline would never compare
// against it either. The baseline has to hold EVERYTHING so that "not baseline"
// can mean something; what a process IS stays a property recorded on the entry,
// never a condition for being recorded at all.
//
// Found while answering a narrower review question (schedulers missing
// from a baseline whose own Kind field documented them).
import (
"os"
"strconv"
"strings"
)
// baselineAllProcesses returns one observation per live process, unfiltered.
// The fields are the ones the fingerprint needs and nothing more.
func baselineAllProcesses() ([]agentObs, bool) {
entries, err := os.ReadDir("/proc")
if err != nil {
return nil, false
}
facts := procFactsReader()
self := os.Getpid()
out := make([]agentObs, 0, 256)
for _, e := range entries {
if !e.IsDir() {
continue
}
pid, err := strconv.Atoi(e.Name())
if err != nil || pid == self {
continue
}
raw, err := os.ReadFile("/proc/" + e.Name() + "/cmdline")
if err != nil || len(raw) == 0 {
// A kernel thread has an empty cmdline. It is not a program anybody
// installed and it cannot be a rogue agent; excluding it keeps the
// baseline about userland without needing a name list.
continue
}
argv := splitNul(raw)
full := strings.Join(argv, " ")
a := agentObs{
PID: pid, User: procUser(pid), Cmdline: truncate(full, 200),
Exe: procExe(pid), raw: full,
}
if f, ok := facts(pid); ok {
a.Unit = f.Unit
a.PPID = f.PPID
}
// The signature when there IS one, as a PROPERTY of the entry. An
// unrecognised process is still recorded; it simply has no signature,
// which is itself the interesting fact about it.
if sig, auto, ok := matchSignature(argv); ok {
a.Signature, a.automation = sig, auto
}
out = append(out, a)
}
return out, true
}