9{
11
12 const std::string
json =
13 R"({"received_at":"2026-08-03T08:00:00Z","event":"permission-change","verdict":"blocked","pid":42,"tgid":42,"ppid":1,"old_euid":0,"new_euid":0,"rule_id":7,"reason_flags":32768,"device":8388609,"inode":1234,"actor_device":8388609,"actor_inode":777,"parent_device":8388609,"parent_inode":778,"actor_start_boottime_ns":123456789,"old_mode":493,"new_mode":2541,"old_uid":0,"new_uid":0,"old_gid":0,"new_gid":0,"comm":"chmod","parent_comm":"sudo","actor_executable":"/usr/bin/chmod","parent_executable":"/usr/bin/sudo","filename":"/etc/systemd/system/example.service","path_resolution":"protected-baseline","xattr_name":""})";
14
16 assert(event.has_value());
17 assert(event->pid == 42);
18 assert(event->device == 8388609);
19 assert(event->inode == 1234);
20 assert(event->actor_device == 8388609);
21 assert(event->actor_inode == 777);
22 assert(event->parent_inode == 778);
23 assert(event->parent_comm == "sudo");
24 assert(event->parent_executable == "/usr/bin/sudo");
25 assert(event->old_mode == 493);
26 assert(event->new_mode == 2541);
30 assert(event->actor_executable == "/usr/bin/chmod");
31 assert(event->path_resolution == "protected-baseline");
35 assert(
format_event(*event).find(
"mode=755->4755") != std::string::npos);
36
38 R"({"event":"permission-change","verdict":"audit","rule_id":0,"reason_flags":4194304,"device":42,"inode":99,"old_mode":420,"new_mode":384,"comm":"chmod","parent_comm":"sudo","actor_device":42,"actor_inode":100,"actor_executable":"/usr/bin/chmod","filename":"/var/tmp/permission-test","path_resolution":"lsm-exact"})");
39 assert(legacyGlobal.has_value());
40
44 assert(legacyGlobal->path_resolution == "lsm-exact");
45 assert(legacyGlobal->parent_comm == "sudo");
46 assert(
format_event(*legacyGlobal).find(
"actor=/usr/bin/chmod") != std::string::npos);
47 assert(
format_event(*legacyGlobal).find(
"actor-identity=42:100") != std::string::npos);
48 assert(
format_event(*legacyGlobal).find(
"path-resolution=lsm-exact") != std::string::npos);
49 assert(
format_event(*legacyGlobal).find(
"identity=42:99") != std::string::npos);
50
52 R"({"event":"permission-change","verdict":"audit","rule_id":0,"reason_flags":163840,"old_mode":493,"new_mode":2541,"old_uid":0,"new_uid":0,"comm":"chmod","filename":"/tmp/helper","path_resolution":"lsm-exact"})");
53 assert(setidAdded.has_value());
58
60 R"({"event":"owner-change","verdict":"audit","rule_id":0,"reason_flags":196608,"old_mode":420,"new_mode":420,"old_uid":1000,"new_uid":0,"comm":"chown","filename":"/usr/share/example.dat","path_resolution":"lsm-exact"})");
61 assert(ownerToRoot.has_value());
66
68 R"({"event":"permission-change","verdict":"audit","rule_id":0,"reason_flags":8519680,"old_mode":420,"new_mode":436,"old_uid":0,"new_uid":0,"comm":"chmod","filename":"/var/lib/example/state.db","path_resolution":"lsm-exact"})");
69 assert(nonExecutableRootWrite.has_value());
73
75 R"({"event":"permission-change","verdict":"audit","rule_id":0,"reason_flags":8519680,"old_mode":493,"new_mode":509,"old_uid":0,"new_uid":0,"comm":"chmod","filename":"/usr/local/bin/tool","path_resolution":"lsm-exact"})");
76 assert(sensitiveGroupWriteExecutable.has_value());
79
81 R"({"event":"permission-change","verdict":"audit","rule_id":0,"reason_flags":8519680,"old_mode":493,"new_mode":509,"old_uid":0,"new_uid":0,"comm":"chmod","filename":"/srv/build/tool","path_resolution":"lsm-exact"})");
82 assert(collaborativeGroupWriteExecutable.has_value());
85
87 R"({"event":"permission-change","verdict":"audit","rule_id":0,"reason_flags":8519680,"old_mode":493,"new_mode":495,"old_uid":0,"new_uid":0,"comm":"chmod","filename":"/srv/build/tool","path_resolution":"lsm-exact"})");
88 assert(worldWriteExecutable.has_value());
91
93 R"({"event":"xattr-change","verdict":"audit","rule_id":0,"reason_flags":131328,"lsm_flags":0,"auxiliary":1,"old_mode":493,"new_mode":493,"old_uid":0,"new_uid":0,"comm":"setcap","filename":"/usr/local/bin/helper","path_resolution":"basename-only"})");
94 assert(executableCapability.has_value());
98
100 R"({"event":"xattr-change","verdict":"audit","rule_id":0,"reason_flags":131328,"lsm_flags":-1,"auxiliary":1,"old_mode":493,"new_mode":493,"old_uid":0,"new_uid":0,"comm":"setcap","filename":"/usr/local/bin/helper","path_resolution":"basename-only"})");
101 assert(capabilityRemoval.has_value());
102 assert(capabilityRemoval->lsm_flags == -1);
105
107 R"({"event":"xattr-change","verdict":"audit","rule_id":0,"reason_flags":131328,"lsm_flags":0,"auxiliary":1,"old_mode":420,"new_mode":420,"old_uid":0,"new_uid":0,"comm":"setcap","filename":"/var/lib/example/blob","path_resolution":"basename-only"})");
108 assert(nonExecutableCapability.has_value());
111
112
114 R"({"event":"permission-change","verdict":"audit","rule_id":0,"reason_flags":16908288,"auxiliary":64,"old_mode":420,"new_mode":384,"old_uid":1000,"new_uid":1000,"comm":"chmod","filename":"/home/user/document","path_resolution":"lsm-exact"})");
115 assert(metadataBurst.has_value());
119
121 R"({"event":"permission-change","verdict":"audit","rule_id":9,"reason_flags":64,"device":42,"inode":102,"old_mode":420,"new_mode":384,"old_uid":0,"new_uid":0,"old_gid":0,"new_gid":0,"comm":"chmod","actor_executable":"/usr/bin/chmod","filename":"/etc/sudoers","path_resolution":"protected-baseline"})");
122 assert(protectedAudit.has_value());
125
127 R"({"event":"setuid","verdict":"trusted","filename":"/usr/bin/sudo"})");
128 assert(trusted.has_value());
131
132 std::cout << "RootGuardEventTests: OK\n";
133 return 0;
134}
std::string event_fingerprint(const Event &event)
bool is_actionable_incident(const Event &event) noexcept
bool is_security_observation(const Event &event) noexcept
std::string format_event(const Event &event)
std::optional< Event > parse_event_json(const std::string &line)
EventSeverity classify_event(const Event &event) noexcept
bool is_system_service_path(const std::string &path) noexcept
@ RG_REASON_SECURITY_CAPABILITY
@ RG_REASON_ROOT_OWNED_WRITE_EXPOSURE
@ RG_REASON_METADATA_BURST
@ RG_REASON_OWNER_TO_ROOT