// SPDX-License-Identifier: GPL-3.0-or-later package detectors import ( "fmt" "sort" "strings" "codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/config" "codeberg.org/anassaeneroi/enodia-sentinal/go-agent/internal/model" ) // Persistence ports the Python persistence detector (SID 100015). // PersistenceFiles is an injectable path-to-mtime view; live filesystem // collection remains deferred until the sidecar gains configured slow scans. func Persistence(state model.State, cfg config.Config) []model.Alert { if state.PersistSince == nil { return []model.Alert{} } alerts := make([]model.Alert, 0) paths := make([]string, 0, len(state.PersistenceFiles)) for path := range state.PersistenceFiles { paths = append(paths, path) } sort.Strings(paths) for _, path := range paths { mtime := state.PersistenceFiles[path] if mtime <= *state.PersistSince || !watchedPath(path, cfg.WatchPersistence) { continue } alerts = append(alerts, model.Alert{ SID: 100015, Severity: "HIGH", Signature: "persistence", Classtype: "persistence", Key: "persist:" + path, Detail: fmt.Sprintf("persistence file modified: %s", path), PIDs: []int{}, }) } return alerts } func watchedPath(path string, roots []string) bool { for _, root := range roots { root = strings.TrimRight(root, "/") if path == root || (root != "" && strings.HasPrefix(path, root+"/")) { return true } } return false }