Skip to content
API Documentation
BastionGuard™
RootGuardEventTests.cpp File Reference

Go to the source code of this file.

Functions

int main ()

Function Documentation

◆ main()

int main ( void )

Definition at line 8 of file RootGuardEventTests.cpp.

9{
10 using namespace BastionGuard::RootGuard;
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
15 const auto event = parse_event_json(json);
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);
27 assert(classify_event(*event) == EventSeverity::Incident);
28 assert(is_security_observation(*event));
29 assert(is_actionable_incident(*event));
30 assert(event->actor_executable == "/usr/bin/chmod");
31 assert(event->path_resolution == "protected-baseline");
32 assert(is_system_service_path(event->filename));
33 assert(is_system_service_path("/etc/conf.d/sshd"));
34 assert(!event_fingerprint(*event).empty());
35 assert(format_event(*event).find("mode=755->4755") != std::string::npos);
36
37 const auto legacyGlobal = parse_event_json(
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 // Historical broad-surveillance records remain Events-only telemetry.
41 assert(classify_event(*legacyGlobal) == EventSeverity::Telemetry);
42 assert(!is_security_observation(*legacyGlobal));
43 assert(!is_actionable_incident(*legacyGlobal));
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
51 const auto setidAdded = parse_event_json(
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());
54 assert((setidAdded->reason_flags & RG_REASON_SETID_ADDED) != 0);
55 assert(classify_event(*setidAdded) == EventSeverity::Observation);
56 assert(is_security_observation(*setidAdded));
57 assert(!is_actionable_incident(*setidAdded));
58
59 const auto ownerToRoot = parse_event_json(
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());
62 assert((ownerToRoot->reason_flags & RG_REASON_OWNER_TO_ROOT) != 0);
63 assert(classify_event(*ownerToRoot) == EventSeverity::Observation);
64 assert(is_security_observation(*ownerToRoot));
65 assert(!is_actionable_incident(*ownerToRoot));
66
67 const auto nonExecutableRootWrite = parse_event_json(
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());
70 assert((nonExecutableRootWrite->reason_flags & RG_REASON_ROOT_OWNED_WRITE_EXPOSURE) != 0);
71 assert(classify_event(*nonExecutableRootWrite) == EventSeverity::Observation);
72 assert(!is_actionable_incident(*nonExecutableRootWrite));
73
74 const auto sensitiveGroupWriteExecutable = parse_event_json(
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());
77 assert(classify_event(*sensitiveGroupWriteExecutable) == EventSeverity::Observation);
78 assert(!is_actionable_incident(*sensitiveGroupWriteExecutable));
79
80 const auto collaborativeGroupWriteExecutable = parse_event_json(
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());
83 assert(classify_event(*collaborativeGroupWriteExecutable) == EventSeverity::Observation);
84 assert(!is_actionable_incident(*collaborativeGroupWriteExecutable));
85
86 const auto worldWriteExecutable = parse_event_json(
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());
89 assert(classify_event(*worldWriteExecutable) == EventSeverity::Observation);
90 assert(!is_actionable_incident(*worldWriteExecutable));
91
92 const auto executableCapability = parse_event_json(
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());
95 assert((executableCapability->reason_flags & RG_REASON_SECURITY_CAPABILITY) != 0);
96 assert(classify_event(*executableCapability) == EventSeverity::Observation);
97 assert(!is_actionable_incident(*executableCapability));
98
99 const auto capabilityRemoval = parse_event_json(
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);
103 assert(classify_event(*capabilityRemoval) == EventSeverity::Observation);
104 assert(!is_actionable_incident(*capabilityRemoval));
105
106 const auto nonExecutableCapability = parse_event_json(
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());
109 assert(classify_event(*nonExecutableCapability) == EventSeverity::Observation);
110 assert(!is_actionable_incident(*nonExecutableCapability));
111
112
113 const auto metadataBurst = parse_event_json(
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());
116 assert((metadataBurst->reason_flags & RG_REASON_METADATA_BURST) != 0);
117 assert(classify_event(*metadataBurst) == EventSeverity::Incident);
118 assert(is_actionable_incident(*metadataBurst));
119
120 const auto protectedAudit = parse_event_json(
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());
123 assert(classify_event(*protectedAudit) == EventSeverity::Incident);
124 assert(is_actionable_incident(*protectedAudit));
125
126 const auto trusted = parse_event_json(
127 R"({"event":"setuid","verdict":"trusted","filename":"/usr/bin/sudo"})");
128 assert(trusted.has_value());
129 assert(classify_event(*trusted) == EventSeverity::Telemetry);
130 assert(!is_actionable_incident(*trusted));
131
132 std::cout << "RootGuardEventTests: OK\n";
133 return 0;
134}
nlohmann::json json
Definition Backend.cpp:2908
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
@ RG_REASON_SETID_ADDED

References BastionGuard::RootGuard::classify_event(), BastionGuard::RootGuard::event_fingerprint(), BastionGuard::RootGuard::format_event(), BastionGuard::RootGuard::Incident, BastionGuard::RootGuard::is_actionable_incident(), BastionGuard::RootGuard::is_security_observation(), BastionGuard::RootGuard::is_system_service_path(), main(), BastionGuard::RootGuard::Observation, BastionGuard::RootGuard::parse_event_json(), RG_REASON_METADATA_BURST, RG_REASON_OWNER_TO_ROOT, RG_REASON_ROOT_OWNED_WRITE_EXPOSURE, RG_REASON_SECURITY_CAPABILITY, RG_REASON_SETID_ADDED, and BastionGuard::RootGuard::Telemetry.