Skip to content

fix(adhoc-sweep-fixes): 58 review findings across 40 files - #39

Draft
flamingo[bot] wants to merge 40 commits into
masterfrom
ai-fix/adhoc-sweep-fixes-766783e7-01e7aadc
Draft

fix(adhoc-sweep-fixes): 58 review findings across 40 files#39
flamingo[bot] wants to merge 40 commits into
masterfrom
ai-fix/adhoc-sweep-fixes-766783e7-01e7aadc

Conversation

@flamingo

@flamingo flamingo Bot commented Aug 24, 2026

Copy link
Copy Markdown

Closes 58 review findings across 40 files.

Draft — this is a starting point, not a finished change. The fix required judgment, so read it before trusting it.

# Fix confidence Finding Location
1 🟢 92 high SQL injection in SQLiteDatabasePlugin::get() via unsanitized key concatenation plugins/database/sqlite.cpp:111
2 🟡 85 medium sqlite3_stmt leaked on failure paths in putBatch, remove, and removeRange plugins/database/sqlite.cpp:199
3 🟡 75 medium SQL injection risk in SQLiteDatabasePlugin::scan() via unsanitized prefix in LIKE clause plugins/database/sqlite.cpp:226
4 🟢 95 high Wrong subject token copied into pid for AUT_SUBJECT64 in socket_events.cpp osquery/tables/events/darwin/socket_events.cpp:163
5 🟢 90 high Typo bug in AUT_HEADER32_EX branch: AUE_ACCEPT check reads from wrong header token (hdr32 instead of hdr32_ex) osquery/tables/events/darwin/socket_events.cpp:109
6 🟢 90 high Same header-union typo repeated in AUT_HEADER64/HEADER64_EX branch osquery/tables/events/darwin/socket_events.cpp:120
7 🟢 95 high azure_instance_metadata.cpp integration test fails to compile: missing comma and unclosed brace tests/integration/tables/azure_instance_metadata.cpp:22
8 🟢 90 high Closing namespace comment mismatched — says 'table_tests' instead of 'osquery' tests/integration/tables/azure_instance_metadata.cpp:40
9 🟡 88 medium genDnsCache: no NULL check on LoadLibraryExW/GetProcAddress before invoking DnsGetCacheDataTable osquery/tables/system/windows/dns_cache.cpp:143
10 🟡 85 medium genDnsCache never calls FreeLibrary(hLib) after LoadLibraryExW osquery/tables/system/windows/dns_cache.cpp:144
11 🔴 40 low — review closely prefetch.cpp parsePrefetch: compressed_data.size() checked against sizeof(PPREFETCH_COMPRESSED_HEADER) (a pointer type), not sizeof(PREFETCH_COMPRESSED_HEADER) (the struct), allowing undersized buffers through osquery/tables/system/windows/prefetch.cpp:290
12 🔴 40 low — review closely prefetch.cpp parsePrefetch: second undersized-buffer check also uses sizeof(pointer typedef) instead of sizeof(struct) osquery/tables/system/windows/prefetch.cpp:315
13 🟢 95 high Stray } // namespace osquery closing brace inside function body causes malformed nesting in validateIMDSV2RequestAttempts osquery/utils/aws/aws_util.cpp:178
14 🟡 85 medium std::cerr used for diagnostic output instead of LOG() macro osquery/utils/aws/aws_util.cpp:178
15 🔴 40 low — review closely compress()/decompress() use std::vector<void*> as raw byte buffers, wasting 8x memory and risking undefined behavior with read()/write() osquery/filesystem/file_compression.cpp:1
16 🔴 40 low — review closely decompress() repeats the same std::vector<void*> buffer sizing bug as compress() osquery/filesystem/file_compression.cpp:1
17 🟢 92 high logon_sessions.cpp: unchecked map::find()->second on kLogonTypeToStr can dereference end() iterator osquery/tables/system/windows/logon_sessions.cpp:65
18 🟡 85 medium logon_sessions.cpp never frees session_data or the sessions array returned by LSA osquery/tables/system/windows/logon_sessions.cpp:44
19 🟡 85 medium Inverted existence check causes SCNetwork subscription targets to never be re-added during configure() osquery/events/darwin/scnetwork.cpp:108
20 🟡 70 medium SCNetworkEventPublisher::Callback never fires the event to subscribers osquery/events/darwin/scnetwork.cpp:26
21 🟢 95 high Inverted boolean logic makes validateSocketDescriptor always fail when domain is set osquery/events/tests/linux/bpf/utils.cpp:170
22 🟢 95 high EtwProviderConfig::isValid() checks getPostProcessor() twice instead of also validating getPreProcessor() osquery/events/windows/etw/etw_provider_config.cpp:15
23 🔴 40 low — review closely genPortageKeywordSummary never actually calls the parser when unmasked file is missing/empty osquery/tables/system/linux/portage.cpp:288
24 🟢 95 high requireAction uses bitwise-AND assignment instead of OR, silently discarding previously-set mask bits osquery/events/darwin/fsevents.cpp:48
25 🟢 98 high Off-by-one/logic bug: hostname port-delimiter check uses unsigned wraparound when ':' is not found osquery/tables/networking/curl_certificate.cpp:285
26 🟢 95 high cleanOldAggregationCacheEntries erases the current iterator then increments it, causing use-after-erase osquery/events/windows/etw/etw_publisher_processes.cpp:353
27 🔴 45 low — review closely processImageCache_ in EtwPublisherProcesses grows unbounded with no eviction osquery/events/windows/etw/etw_publisher_processes.cpp:320
28 🟢 95 high Insecure/deprecated os.makedirs mode literal uses Python 2 octal syntax (0755) — will fail to parse under Python 3 tools/codegen/gentargets.py:128
29 🟡 85 medium JSON parse failure in gentargets.py is logged critical but execution continues, leading to a later crash tools/codegen/gentargets.py:112
30 🟢 95 high queries_from_pack references undefined variable config_path in error message tools/tests/utils.py:116
31 🟢 90 high profile_cmd() calls p.wait() twice, second call after process already reaped tools/tests/utils.py:190
32 🟢 95 high getProcessProperties() copies egid into euid field, duplicating egid lookup and never reading ruid for euid osquery/events/darwin/es_utils.cpp:152
33 🟡 70 medium getCDHash() uses find_first_not_of(s.front()) which is a character-search bug, not an all-zero-check osquery/events/darwin/es_utils.cpp:120
34 🟢 90 high isOpenSSHKeyEncrypted can read out-of-bounds via substr on short key content osquery/tables/system/ssh_keys.cpp:44
35 🟢 90 high BIO_new result checked for null after being used, and passed to guard before null-check osquery/tables/system/ssh_keys.cpp:62
36 🔴 40 low — review closely Kafka topic_conf leaked when topic conf set fails in initTopic plugins/logger/kafka_producer.cpp:267
37 🟡 65 medium configureTopics() base-topic branch overwrites queryToTopics_[kKafkaBaseTopic] with nullptr on failed initTopic, silently breaking base-topic fallback plugins/logger/kafka_producer.cpp:314
38 🟢 95 high Shadowed variable name event_list in WindowsEventLogPublisher::run loop osquery/events/windows/windowseventlogpublisher.cpp:155
39 🟡 85 medium Potential division by zero in cosineSimilarity when buffer_size is 0 osquery/events/windows/windowseventlogpublisher.cpp:214
40 🟢 95 high executeCarve() truncates carve-status message to a hardcoded length of 13, corrupting output osquery/sql/sqlite_operations.cpp:53
41 🟢 95 high pidsFromContext copies procs into itself instead of the newly-queried proc result osquery/tables/system/system_utils.cpp:29
42 🔴 40 low — review closely FakeEventSubscriber(bool skip_name) constructor calls FakeEventSubscriber() as a temporary, not delegating construction osquery/events/tests/events_tests.cpp:297
43 🟡 85 medium 'hidden' column in scheduled_tasks is populated from get_Enabled instead of a hidden-state API osquery/tables/system/windows/scheduled_tasks.cpp:108
44 🟢 95 high Missing space in concatenated error message produces "NevaluetsFailed to log 3events"-style output osquery/core/plugins/logger.h:249
45 🟢 98 high Duplicate map entry silently makes ChromeBrowserType::Edge alias to 'edge_beta' unreachable osquery/tables/applications/chrome/utils.cpp:138
46 🟢 95 high Bitwise-AND-with-nonzero-mask misused as boolean test in hypervisor ID check osquery/tables/system/cpuid.cpp:176
47 🟢 95 high getBluetoothSharingStatus checks wrong map's end() iterator causing incorrect find failure detection osquery/tables/system/darwin/sharing_preferences.cpp:161
48 🟢 97 high GroupsCache::initializeCache does not hold cache_mutex_ while other methods do osquery/system/usersgroups/windows/users_groups_cache.cpp:100
49 🟢 95 high AUT_SUBJECT64 case copies pid from the 32-bit subject union member (copy-paste bug) osquery/tables/events/darwin/openbsm_events.cpp:168
50 🟢 92 high Potential null dereference of udev_device_get_sysattr_value(subdev, "model"/"vendor") result before std::string construction osquery/tables/system/linux/block_devices.cpp:95
51 🟡 65 medium safari_extensions integration test performs no validation at all tests/integration/tables/safari_extensions.cpp:26
52 🟢 95 high gentable.py references undefined yellow() function, will raise NameError on unknown column option tools/codegen/gentable.py:218
53 🟢 95 high Windows CodeProfiler passes metric name with a leading dot, producing a malformed metric key osquery/profiler/windows/code_profiler.cpp:47
54 🟢 95 high genArp indexes addr_map with RTA_DST (a bitmask flag) instead of RTAX_DST (an array index) osquery/tables/networking/darwin/routes.cpp:111
55 🟢 92 high sqlite3_prepare_v2 return code not checked in genGateKeeperApprovedApps before calling sqlite3_step osquery/tables/system/darwin/gatekeeper.cpp:191
56 🟢 95 high genNVRAM leaks options_dict when IORegistryEntryCreateCFProperties succeeds osquery/tables/system/darwin/nvram.cpp:138
57 🟢 95 high SceClientHelper::isValidSceProfileData checks readability of the wrong pointer (&profileData instead of profileData) osquery/tables/system/windows/security_profile_info_utils.cpp:155
58 🟢 95 high Filesystem::enumFiles shadows outer-scope directory local unique_ptr with a bool of the same name osquery/events/linux/bpf/filesystem.cpp:121

What changed — and what was deliberately left — is explained per finding as inline review comments on the lines each finding touched.


Run: https://product-hub.flamingo.so/admin/code-review
Run id: 01e7aadc-0204-47ef-b373-fc5dbadf3ab5

Merging this PR is recorded as acceptance of the rule that produced it;
closing it unmerged is recorded as rejection. Both feed rule health, so
closing a wrong suggestion is useful rather than merely tidy.

flamingo Bot added 30 commits August 24, 2026 05:20

@flamingo flamingo Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 What this fix changed, finding by finding

58 finding(s) fixed in this draft — 58 explained inline on the diff; 8 low-confidence hunk(s) need close review before merging.

Comment on lines 115 to 141
Status SQLiteDatabasePlugin::get(const std::string& domain,
const std::string& key,
std::string& value) const {
QueryData results;
char* err = nullptr;
std::string q = "select value from " + domain + " where key = '" + key + "';";
sqlite3_exec(db_, q.c_str(), getData, &results, &err);
if (err != nullptr) {
sqlite3_free(err);
sqlite3_stmt* stmt = nullptr;
std::string q = "select value from " + domain + " where key = ?1;";
auto rc = sqlite3_prepare_v2(db_, q.c_str(), -1, &stmt, nullptr);
if (rc != SQLITE_OK || stmt == nullptr) {
if (stmt != nullptr) {
sqlite3_finalize(stmt);
}
return Status(1);
}

// Only assign value if the query found a result.
if (results.size() > 0) {
value = std::move(results[0]["value"]);
sqlite3_bind_text(stmt, 1, key.c_str(), -1, SQLITE_STATIC);

rc = sqlite3_step(stmt);
if (rc == SQLITE_ROW) {
const auto* text = sqlite3_column_text(stmt, 0);
value = (text != nullptr) ? reinterpret_cast<const char*>(text) : "";
sqlite3_finalize(stmt);
return Status(0);
}

sqlite3_finalize(stmt);
return Status(1);
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 SQL injection in SQLiteDatabasePlugin::get() via unsanitized key concatenation

Rewrote SQLiteDatabasePlugin::get(const std::string&, const std::string&, std::string&) to use sqlite3_prepare_v2 + sqlite3_bind_text with a ?1 placeholder for key instead of concatenating it into the SQL string, eliminating the injection vector. Added prepare-failure and null-stmt checks with finalize, and reads the result via sqlite3_column_text/sqlite3_step (SQLITE_ROW) instead of the sqlite3_exec callback.

🤖 Prompt for AI agents
In plugins/database/sqlite.cpp around line 111, review and complete this code-review fix: SQL injection in SQLiteDatabasePlugin::get() via unsanitized key concatenation.
What the draft fix changed: Rewrote SQLiteDatabasePlugin::get(const std::string&, const std::string&, std::string&) to use sqlite3_prepare_v2 + sqlite3_bind_text with a `?1` placeholder for `key` instead of concatenating it into the SQL string, eliminating the injection vector. Added prepare-failure and null-stmt checks with finalize, and reads the result via sqlite3_column_text/sqlite3_step (SQLITE_ROW) instead of the sqlite3_exec callback.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 92 high — react 👍/👎 to teach the reviewer

}
return Status(1);
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 sqlite3_stmt leaked on failure paths in putBatch, remove, and removeRange

In putBatch, remove, and removeRange, added sqlite3_finalize(stmt) on the rc != SQLITE_DONE error path before returning Status(1), fixing the statement leak. Also added checks on the return value of sqlite3_prepare_v2 (and null stmt) in all three functions plus the rewritten get(), finalizing and returning Status(1) if preparation fails, preventing binds/steps on an invalid/null statement.

🤖 Prompt for AI agents
In plugins/database/sqlite.cpp around line 199, review and complete this code-review fix: sqlite3_stmt leaked on failure paths in putBatch, remove, and removeRange.
What the draft fix changed: In putBatch, remove, and removeRange, added sqlite3_finalize(stmt) on the `rc != SQLITE_DONE` error path before returning Status(1), fixing the statement leak. Also added checks on the return value of sqlite3_prepare_v2 (and null stmt) in all three functions plus the rewritten get(), finalizing and returning Status(1) if preparation fails, preventing binds/steps on an invalid/null statement.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

Comment on lines 243 to 260
const std::string& key) {
sqlite3_stmt* stmt = nullptr;
std::string q = "delete from " + domain + " where key IN (?1);";
sqlite3_prepare_v2(db_, q.c_str(), -1, &stmt, nullptr);
auto prc = sqlite3_prepare_v2(db_, q.c_str(), -1, &stmt, nullptr);
if (prc != SQLITE_OK || stmt == nullptr) {
if (stmt != nullptr) {
sqlite3_finalize(stmt);
}
return Status(1);
}

sqlite3_bind_text(stmt, 1, key.c_str(), -1, SQLITE_STATIC);
auto rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
sqlite3_finalize(stmt);
return Status(1);
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 SQL injection risk in SQLiteDatabasePlugin::scan() via unsanitized prefix in LIKE clause

Rewrote SQLiteDatabasePlugin::scan() to use a prepared statement with key LIKE ?1 || '%' and sqlite3_bind_text for prefix, replacing the string-concatenated LIKE clause and sqlite3_exec/getData callback. Results are now collected by stepping through the prepared statement with sqlite3_column_text. This changes the internal query mechanism (bound LIKE pattern rather than literal concatenation with max appended after prepare-time limit clause); behavior for max/limit is preserved but the switch away from sqlite3_exec's callback-based error string (err) means prepare failures are now handled by returning success with no results instead of setting err — worth a reviewer's confirmation that silently returning empty results on a prepare failure is acceptable versus surfacing an error status.

🤖 Prompt for AI agents
In plugins/database/sqlite.cpp around line 226, review and complete this code-review fix: SQL injection risk in SQLiteDatabasePlugin::scan() via unsanitized prefix in LIKE clause.
What the draft fix changed: Rewrote SQLiteDatabasePlugin::scan() to use a prepared statement with `key LIKE ?1 || '%'` and sqlite3_bind_text for `prefix`, replacing the string-concatenated LIKE clause and sqlite3_exec/getData callback. Results are now collected by stepping through the prepared statement with sqlite3_column_text. This changes the internal query mechanism (bound LIKE pattern rather than literal concatenation with `max` appended after prepare-time limit clause); behavior for `max`/limit is preserved but the switch away from sqlite3_exec's callback-based error string (`err`) means prepare failures are now handled by returning success with no results instead of setting `err ` — worth a reviewer's confirmation that silently returning empty results on a prepare failure is acceptable versus surfacing an error status.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 75 medium — react 👍/👎 to teach the reviewer

Comment on lines 146 to 152
case AUT_SUBJECT64:
r["auid"] = INTEGER(tok.tt.subj64.auid);
r["pid"] = INTEGER(tok.tt.subj64.pid);
pid = tok.tt.subj32.pid;
pid = tok.tt.subj64.pid;
break;
case AUT_SUBJECT32_EX:
r["auid"] = INTEGER(tok.tt.subj32_ex.auid);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 Wrong subject token copied into pid for AUT_SUBJECT64 in socket_events.cpp

In OpenBSMNetEvSubscriber::Callback, AUT_SUBJECT64 case: changed pid = tok.tt.subj32.pid; to pid = tok.tt.subj64.pid;, matching the correct 64-bit union member consistent with the preceding r["pid"] assignment on the same case.

🤖 Prompt for AI agents
In osquery/tables/events/darwin/socket_events.cpp around line 163, review and complete this code-review fix: Wrong subject token copied into pid for AUT_SUBJECT64 in socket_events.cpp.
What the draft fix changed: In `OpenBSMNetEvSubscriber::Callback`, `AUT_SUBJECT64` case: changed `pid = tok.tt.subj32.pid;` to `pid = tok.tt.subj64.pid;`, matching the correct 64-bit union member consistent with the preceding `r["pid"]` assignment on the same case.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

r["action"] = "bind";
} else if (tok.tt.hdr32.e_type == AUE_ACCEPT) {
} else if (tok.tt.hdr32_ex.e_type == AUE_ACCEPT) {
r["action"] = "accept";

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 Typo bug in AUT_HEADER32_EX branch: AUE_ACCEPT check reads from wrong header token (hdr32 instead of hdr32_ex)

In OpenBSMNetEvSubscriber::Callback, AUT_HEADER32_EX case: changed the AUE_ACCEPT comparison from tok.tt.hdr32.e_type to tok.tt.hdr32_ex.e_type, matching the other two comparisons in the same branch.

🤖 Prompt for AI agents
In osquery/tables/events/darwin/socket_events.cpp around line 109, review and complete this code-review fix: Typo bug in AUT_HEADER32_EX branch: AUE_ACCEPT check reads from wrong header token (hdr32 instead of hdr32_ex).
What the draft fix changed: In `OpenBSMNetEvSubscriber::Callback`, `AUT_HEADER32_EX` case: changed the AUE_ACCEPT comparison from `tok.tt.hdr32.e_type` to `tok.tt.hdr32_ex.e_type`, matching the other two comparisons in the same branch.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer

Comment on lines 119 to 125
// The cache will always know the address.
r["address"] = ipAsString(addr_map[RTAX_DST]);

auto sdl = (struct sockaddr_dl *)addr_map[RTA_DST];
auto sdl = (struct sockaddr_dl *)addr_map[RTAX_DST];
if (sdl->sdl_alen > 0) {
r["mac"] = macAsString(LLADDR(sdl));
} else {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 genArp indexes addr_map with RTA_DST (a bitmask flag) instead of RTAX_DST (an array index)

In genArp (osquery/tables/networking/darwin/routes.cpp), changed auto sdl = (struct sockaddr_dl *)addr_map[RTA_DST]; to auto sdl = (struct sockaddr_dl *)addr_map[RTAX_DST];, replacing the bitmask constant RTA_DST with the correct array index constant RTAX_DST, consistent with all other addr_map accesses in the file.

🤖 Prompt for AI agents
In osquery/tables/networking/darwin/routes.cpp around line 111, review and complete this code-review fix: genArp indexes addr_map with RTA_DST (a bitmask flag) instead of RTAX_DST (an array index).
What the draft fix changed: In genArp (osquery/tables/networking/darwin/routes.cpp), changed `auto sdl = (struct sockaddr_dl *)addr_map[RTA_DST];` to `auto sdl = (struct sockaddr_dl *)addr_map[RTAX_DST];`, replacing the bitmask constant RTA_DST with the correct array index constant RTAX_DST, consistent with all other addr_map accesses in the file.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

Comment on lines 194 to +197
}
} // namespace tables
} // namespace osquery

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 sqlite3_prepare_v2 return code not checked in genGateKeeperApprovedApps before calling sqlite3_step

In genGateKeeperApprovedApps, added a check if (rc != SQLITE_OK || stmt == nullptr) immediately after sqlite3_prepare_v2, mirroring the pattern in isGateKeeperDevIdEnabled. On failure, finalizes stmt if non-null, closes db, and returns the (empty) results before reaching sqlite3_step, preventing use of a null/invalid statement.

🤖 Prompt for AI agents
In osquery/tables/system/darwin/gatekeeper.cpp around line 191, review and complete this code-review fix: sqlite3_prepare_v2 return code not checked in genGateKeeperApprovedApps before calling sqlite3_step.
What the draft fix changed: In `genGateKeeperApprovedApps`, added a check `if (rc != SQLITE_OK || stmt == nullptr)` immediately after `sqlite3_prepare_v2`, mirroring the pattern in `isGateKeeperDevIdEnabled`. On failure, finalizes `stmt` if non-null, closes `db`, and returns the (empty) `results` before reaching `sqlite3_step`, preventing use of a null/invalid statement.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 92 high — react 👍/👎 to teach the reviewer

Comment on lines 130 to 136
genSingleVariable(options, key, results);
}));
} else {
CFMutableDictionaryRef options_dict;
CFMutableDictionaryRef options_dict = nullptr;
kr = IORegistryEntryCreateCFProperties(
options, &options_dict, kCFAllocatorDefault, 0);
if (kr != KERN_SUCCESS) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 genNVRAM leaks options_dict when IORegistryEntryCreateCFProperties succeeds

In genNVRAM, initialized options_dict to nullptr and guarded the trailing CFRelease(options_dict) with if (options_dict != nullptr), so when IORegistryEntryCreateCFProperties fails (kr != KERN_SUCCESS), no CFRelease is called on an uninitialized/garbage pointer, eliminating the UB/crash path while still releasing the dictionary when creation succeeds.

🤖 Prompt for AI agents
In osquery/tables/system/darwin/nvram.cpp around line 138, review and complete this code-review fix: genNVRAM leaks options_dict when IORegistryEntryCreateCFProperties succeeds.
What the draft fix changed: In genNVRAM, initialized `options_dict` to `nullptr` and guarded the trailing `CFRelease(options_dict)` with `if (options_dict != nullptr)`, so when `IORegistryEntryCreateCFProperties` fails (kr != KERN_SUCCESS), no CFRelease is called on an uninitialized/garbage pointer, eliminating the UB/crash path while still releasing the dictionary when creation succeeds.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

Comment on lines 114 to 120
}

// Checking that input pointer points to an accessible SceProfileInfo layout
if (IsBadReadPtr(&profileData, sizeof(SceProfileInfo))) {
if (IsBadReadPtr(profileData, sizeof(SceProfileInfo))) {
return Status::failure("profileData layout is invalid.");
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 SceClientHelper::isValidSceProfileData checks readability of the wrong pointer (&profileData instead of profileData)

In SceClientHelper::isValidSceProfileData, changed IsBadReadPtr(&profileData, sizeof(SceProfileInfo)) to IsBadReadPtr(profileData, sizeof(SceProfileInfo)), so the readability check now validates the actual pointer value received from the SCE RPC call instead of the address of the local reference/parameter, matching the function's intended purpose.

🤖 Prompt for AI agents
In osquery/tables/system/windows/security_profile_info_utils.cpp around line 155, review and complete this code-review fix: SceClientHelper::isValidSceProfileData checks readability of the wrong pointer (&profileData instead of profileData).
What the draft fix changed: In `SceClientHelper::isValidSceProfileData`, changed `IsBadReadPtr(&profileData, sizeof(SceProfileInfo))` to `IsBadReadPtr(profileData, sizeof(SceProfileInfo))`, so the readability check now validates the actual pointer value received from the SCE RPC call instead of the address of the local reference/parameter, matching the function's intended purpose.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

Comment on lines 125 to 140
continue;
}

bool directory;
bool is_directory;
if (entry->d_type == DT_DIR) {
directory = true;
is_directory = true;
} else if (entry->d_type == DT_LNK || entry->d_type == DT_REG) {
directory = false;
is_directory = false;
} else {
continue;
}

callback(string_fd, directory);
callback(string_fd, is_directory);
}

return true;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 Filesystem::enumFiles shadows outer-scope directory local unique_ptr with a bool of the same name

Renamed the inner bool directory; local to bool is_directory; inside the for(;;) loop in Filesystem::enumFiles, and updated its two assignment sites and the callback(string_fd, is_directory); call to match, eliminating the shadowing of the outer UniqueDir directory variable.

🤖 Prompt for AI agents
In osquery/events/linux/bpf/filesystem.cpp around line 121, review and complete this code-review fix: Filesystem::enumFiles shadows outer-scope `directory` local unique_ptr with a bool of the same name.
What the draft fix changed: Renamed the inner `bool directory;` local to `bool is_directory;` inside the `for(;;)` loop in `Filesystem::enumFiles`, and updated its two assignment sites and the `callback(string_fd, is_directory);` call to match, eliminating the shadowing of the outer `UniqueDir directory` variable.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

@flamingo

flamingo Bot commented Aug 24, 2026

Copy link
Copy Markdown
Author

🦩 What this fix changed, finding by finding

58 finding(s) fixed in this draft. (Inline placement was rejected by GitHub for this PR.)

🔴 1. SQL injection in SQLiteDatabasePlugin::get() via unsanitized key concatenationplugins/database/sqlite.cpp:111
Rewrote SQLiteDatabasePlugin::get(const std::string&, const std::string&, std::string&) to use sqlite3_prepare_v2 + sqlite3_bind_text with a ?1 placeholder for key instead of concatenating it into the SQL string, eliminating the injection vector. Added prepare-failure and null-stmt checks with finalize, and reads the result via sqlite3_column_text/sqlite3_step (SQLITE_ROW) instead of the sqlite3_exec callback.

🤖 Prompt for AI agents
In plugins/database/sqlite.cpp around line 111, review and complete this code-review fix: SQL injection in SQLiteDatabasePlugin::get() via unsanitized key concatenation.
What the draft fix changed: Rewrote SQLiteDatabasePlugin::get(const std::string&, const std::string&, std::string&) to use sqlite3_prepare_v2 + sqlite3_bind_text with a `?1` placeholder for `key` instead of concatenating it into the SQL string, eliminating the injection vector. Added prepare-failure and null-stmt checks with finalize, and reads the result via sqlite3_column_text/sqlite3_step (SQLITE_ROW) instead of the sqlite3_exec callback.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 92 high — react 👍/👎 to teach the reviewer

🔴 2. sqlite3_stmt leaked on failure paths in putBatch, remove, and removeRangeplugins/database/sqlite.cpp:199
In putBatch, remove, and removeRange, added sqlite3_finalize(stmt) on the rc != SQLITE_DONE error path before returning Status(1), fixing the statement leak. Also added checks on the return value of sqlite3_prepare_v2 (and null stmt) in all three functions plus the rewritten get(), finalizing and returning Status(1) if preparation fails, preventing binds/steps on an invalid/null statement.

🤖 Prompt for AI agents
In plugins/database/sqlite.cpp around line 199, review and complete this code-review fix: sqlite3_stmt leaked on failure paths in putBatch, remove, and removeRange.
What the draft fix changed: In putBatch, remove, and removeRange, added sqlite3_finalize(stmt) on the `rc != SQLITE_DONE` error path before returning Status(1), fixing the statement leak. Also added checks on the return value of sqlite3_prepare_v2 (and null stmt) in all three functions plus the rewritten get(), finalizing and returning Status(1) if preparation fails, preventing binds/steps on an invalid/null statement.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

🟠 3. SQL injection risk in SQLiteDatabasePlugin::scan() via unsanitized prefix in LIKE clauseplugins/database/sqlite.cpp:226
Rewrote SQLiteDatabasePlugin::scan() to use a prepared statement with key LIKE ?1 || '%' and sqlite3_bind_text for prefix, replacing the string-concatenated LIKE clause and sqlite3_exec/getData callback. Results are now collected by stepping through the prepared statement with sqlite3_column_text. This changes the internal query mechanism (bound LIKE pattern rather than literal concatenation with max appended after prepare-time limit clause); behavior for max/limit is preserved but the switch away from sqlite3_exec's callback-based error string (err) means prepare failures are now handled by returning success with no results instead of setting err — worth a reviewer's confirmation that silently returning empty results on a prepare failure is acceptable versus surfacing an error status.

🤖 Prompt for AI agents
In plugins/database/sqlite.cpp around line 226, review and complete this code-review fix: SQL injection risk in SQLiteDatabasePlugin::scan() via unsanitized prefix in LIKE clause.
What the draft fix changed: Rewrote SQLiteDatabasePlugin::scan() to use a prepared statement with `key LIKE ?1 || '%'` and sqlite3_bind_text for `prefix`, replacing the string-concatenated LIKE clause and sqlite3_exec/getData callback. Results are now collected by stepping through the prepared statement with sqlite3_column_text. This changes the internal query mechanism (bound LIKE pattern rather than literal concatenation with `max` appended after prepare-time limit clause); behavior for `max`/limit is preserved but the switch away from sqlite3_exec's callback-based error string (`err`) means prepare failures are now handled by returning success with no results instead of setting `err ` — worth a reviewer's confirmation that silently returning empty results on a prepare failure is acceptable versus surfacing an error status.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 75 medium — react 👍/👎 to teach the reviewer

🔴 4. Wrong subject token copied into pid for AUT_SUBJECT64 in socket_events.cpposquery/tables/events/darwin/socket_events.cpp:163
In OpenBSMNetEvSubscriber::Callback, AUT_SUBJECT64 case: changed pid = tok.tt.subj32.pid; to pid = tok.tt.subj64.pid;, matching the correct 64-bit union member consistent with the preceding r["pid"] assignment on the same case.

🤖 Prompt for AI agents
In osquery/tables/events/darwin/socket_events.cpp around line 163, review and complete this code-review fix: Wrong subject token copied into pid for AUT_SUBJECT64 in socket_events.cpp.
What the draft fix changed: In `OpenBSMNetEvSubscriber::Callback`, `AUT_SUBJECT64` case: changed `pid = tok.tt.subj32.pid;` to `pid = tok.tt.subj64.pid;`, matching the correct 64-bit union member consistent with the preceding `r["pid"]` assignment on the same case.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🟠 5. Typo bug in AUT_HEADER32_EX branch: AUE_ACCEPT check reads from wrong header token (hdr32 instead of hdr32_ex)osquery/tables/events/darwin/socket_events.cpp:109
In OpenBSMNetEvSubscriber::Callback, AUT_HEADER32_EX case: changed the AUE_ACCEPT comparison from tok.tt.hdr32.e_type to tok.tt.hdr32_ex.e_type, matching the other two comparisons in the same branch.

🤖 Prompt for AI agents
In osquery/tables/events/darwin/socket_events.cpp around line 109, review and complete this code-review fix: Typo bug in AUT_HEADER32_EX branch: AUE_ACCEPT check reads from wrong header token (hdr32 instead of hdr32_ex).
What the draft fix changed: In `OpenBSMNetEvSubscriber::Callback`, `AUT_HEADER32_EX` case: changed the AUE_ACCEPT comparison from `tok.tt.hdr32.e_type` to `tok.tt.hdr32_ex.e_type`, matching the other two comparisons in the same branch.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer

🟠 6. Same header-union typo repeated in AUT_HEADER64/HEADER64_EX branchosquery/tables/events/darwin/socket_events.cpp:120
In OpenBSMNetEvSubscriber::Callback, combined AUT_HEADER64/AUT_HEADER64_EX case: changed the AUE_ACCEPT comparison from tok.tt.hdr64.e_type to tok.tt.hdr64_ex.e_type, matching the other two comparisons in the same branch.

🤖 Prompt for AI agents
In osquery/tables/events/darwin/socket_events.cpp around line 120, review and complete this code-review fix: Same header-union typo repeated in AUT_HEADER64/HEADER64_EX branch.
What the draft fix changed: In `OpenBSMNetEvSubscriber::Callback`, combined `AUT_HEADER64`/`AUT_HEADER64_EX` case: changed the AUE_ACCEPT comparison from `tok.tt.hdr64.e_type` to `tok.tt.hdr64_ex.e_type`, matching the other two comparisons in the same branch.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer

🔴 7. azure_instance_metadata.cpp integration test fails to compile: missing comma and unclosed bracetests/integration/tables/azure_instance_metadata.cpp:22
In TEST_F(azureInstanceMetadata, test_sanity), added the missing comma between {"sku", NormalType} and {"version", NormalType}, and added a closing } to terminate the TEST_F function body (after the if block), fixing the unclosed braces reported in the finding.

🤖 Prompt for AI agents
In tests/integration/tables/azure_instance_metadata.cpp around line 22, review and complete this code-review fix: azure_instance_metadata.cpp integration test fails to compile: missing comma and unclosed brace.
What the draft fix changed: In TEST_F(azureInstanceMetadata, test_sanity), added the missing comma between {"sku", NormalType} and {"version", NormalType}, and added a closing `}` to terminate the TEST_F function body (after the `if` block), fixing the unclosed braces reported in the finding.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🟠 8. Closing namespace comment mismatched — says 'table_tests' instead of 'osquery'tests/integration/tables/azure_instance_metadata.cpp:40
Changed the final closing namespace comment from } // namespace table_tests to } // namespace osquery to correctly match the outer namespace osquery per convention; kept the inner } // namespace table_tests as-is since it correctly closes namespace table_tests.

🤖 Prompt for AI agents
In tests/integration/tables/azure_instance_metadata.cpp around line 40, review and complete this code-review fix: Closing namespace comment mismatched — says 'table_tests' instead of 'osquery'.
What the draft fix changed: Changed the final closing namespace comment from `} // namespace table_tests` to `} // namespace osquery` to correctly match the outer `namespace osquery` per convention; kept the inner `} // namespace table_tests` as-is since it correctly closes `namespace table_tests`.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer

🔴 9. genDnsCache: no NULL check on LoadLibraryExW/GetProcAddress before invoking DnsGetCacheDataTableosquery/tables/system/windows/dns_cache.cpp:143
In genDnsCache (dns_cache.cpp), added a NULL check on the HINSTANCE returned by LoadLibraryExW (logs WARNING with GetLastError, frees pEntry, and returns early) and a NULL check on the DnsGetCacheDataTable pointer from GetProcAddress (logs WARNING, frees pEntry, calls FreeLibrary(hLib), and returns early). Also preserved the original malloc'd pointer in a new pHead variable and changed the final free(pEntry) to free(pHead) so the head allocation is correctly freed instead of leaking while only the traversal pointer's last address was freed.

🤖 Prompt for AI agents
In osquery/tables/system/windows/dns_cache.cpp around line 143, review and complete this code-review fix: genDnsCache: no NULL check on LoadLibraryExW/GetProcAddress before invoking DnsGetCacheDataTable.
What the draft fix changed: In genDnsCache (dns_cache.cpp), added a NULL check on the HINSTANCE returned by LoadLibraryExW (logs WARNING with GetLastError, frees pEntry, and returns early) and a NULL check on the DnsGetCacheDataTable pointer from GetProcAddress (logs WARNING, frees pEntry, calls FreeLibrary(hLib), and returns early). Also preserved the original malloc'd pointer in a new `pHead` variable and changed the final `free(pEntry)` to `free(pHead)` so the head allocation is correctly freed instead of leaking while only the traversal pointer's last address was freed.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 88 medium — react 👍/👎 to teach the reviewer

🟠 10. genDnsCache never calls FreeLibrary(hLib) after LoadLibraryExWosquery/tables/system/windows/dns_cache.cpp:144
In genDnsCache (dns_cache.cpp), added FreeLibrary(hLib) after the cache walk completes (before returning results) and on the early-exit path when DnsGetCacheDataTable resolution fails, ensuring the loaded DNSAPI.dll module handle is released on all exit paths reachable after a successful LoadLibraryExW call.

🤖 Prompt for AI agents
In osquery/tables/system/windows/dns_cache.cpp around line 144, review and complete this code-review fix: genDnsCache never calls FreeLibrary(hLib) after LoadLibraryExW.
What the draft fix changed: In genDnsCache (dns_cache.cpp), added `FreeLibrary(hLib)` after the cache walk completes (before returning results) and on the early-exit path when DnsGetCacheDataTable resolution fails, ensuring the loaded DNSAPI.dll module handle is released on all exit paths reachable after a successful LoadLibraryExW call.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

🔴 11. prefetch.cpp parsePrefetch: compressed_data.size() checked against sizeof(PPREFETCH_COMPRESSED_HEADER) (a pointer type), not sizeof(PREFETCH_COMPRESSED_HEADER) (the struct), allowing undersized buffers throughosquery/tables/system/windows/prefetch.cpp:290
In parsePrefetch, changed if (compressed_data.size() < sizeof(PPREFETCH_COMPRESSED_HEADER)) to sizeof(PREFETCH_COMPRESSED_HEADER), so the size check now measures the actual struct size (two DWORDs plus BYTE array) instead of the pointer type's size, before &compressed_data[0] is cast and Signature/TotalUncompressedSize are dereferenced.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In osquery/tables/system/windows/prefetch.cpp around line 290, review and complete this code-review fix: prefetch.cpp parsePrefetch: compressed_data.size() checked against sizeof(PPREFETCH_COMPRESSED_HEADER) (a pointer type), not sizeof(PREFETCH_COMPRESSED_HEADER) (the struct), allowing undersized buffers through.
What the draft fix changed: In `parsePrefetch`, changed `if (compressed_data.size() < sizeof(PPREFETCH_COMPRESSED_HEADER))` to `sizeof(PREFETCH_COMPRESSED_HEADER)`, so the size check now measures the actual struct size (two DWORDs plus BYTE array) instead of the pointer type's size, before `&compressed_data[0]` is cast and `Signature`/`TotalUncompressedSize` are dereferenced.

_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer

🔴 12. prefetch.cpp parsePrefetch: second undersized-buffer check also uses sizeof(pointer typedef) instead of sizeof(struct)osquery/tables/system/windows/prefetch.cpp:315
In parsePrefetch, changed if (data.size() < sizeof(PPREFETCH_FILE_HEADER)) to sizeof(PREFETCH_FILE_HEADER), so the check now measures the real ~144-byte header struct size instead of a pointer's size, before data is passed to parsePrefetchData and cast/dereferenced as PPREFETCH_FILE_HEADER.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In osquery/tables/system/windows/prefetch.cpp around line 315, review and complete this code-review fix: prefetch.cpp parsePrefetch: second undersized-buffer check also uses sizeof(pointer typedef) instead of sizeof(struct).
What the draft fix changed: In `parsePrefetch`, changed `if (data.size() < sizeof(PPREFETCH_FILE_HEADER))` to `sizeof(PREFETCH_FILE_HEADER)`, so the check now measures the real ~144-byte header struct size instead of a pointer's size, before `data` is passed to `parsePrefetchData` and cast/dereferenced as `PPREFETCH_FILE_HEADER`.

_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer

🔴 13. Stray } // namespace osquery closing brace inside function body causes malformed nesting in validateIMDSV2RequestAttemptsosquery/utils/aws/aws_util.cpp:178
In validateIMDSV2RequestAttempts (anonymous namespace, osquery/utils/aws/aws_util.cpp), removed the misleading/stray // namespace osquery comment that was attached to the if block's closing brace. The brace itself was correctly balanced (confirmed no actual namespace was closed early, since awsServiceTypeToString and subsequent helpers still compile within the same anonymous namespace, and the file's final } // namespace osquery remains intact at file end). Only the confusing comment text was deleted; no brace structure was altered.

🤖 Prompt for AI agents
In osquery/utils/aws/aws_util.cpp around line 178, review and complete this code-review fix: Stray `} // namespace osquery` closing brace inside function body causes malformed nesting in validateIMDSV2RequestAttempts.
What the draft fix changed: In `validateIMDSV2RequestAttempts` (anonymous namespace, `osquery/utils/aws/aws_util.cpp`), removed the misleading/stray `// namespace osquery` comment that was attached to the `if` block's closing brace. The brace itself was correctly balanced (confirmed no actual namespace was closed early, since `awsServiceTypeToString` and subsequent helpers still compile within the same anonymous namespace, and the file's final `} // namespace osquery` remains intact at file end). Only the confusing comment text was deleted; no brace structure was altered.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🟠 14. std::cerr used for diagnostic output instead of LOG() macroosquery/utils/aws/aws_util.cpp:178
In the same function, replaced std::cerr << error_message << std::endl; with LOG(ERROR) << error_message; exactly as suggested, so the validator failure is routed through glog/osquery's logging pipeline like other errors in this file, while retaining the existing osquery::systemLog(error_message); call above it.

🤖 Prompt for AI agents
In osquery/utils/aws/aws_util.cpp around line 178, review and complete this code-review fix: std::cerr used for diagnostic output instead of LOG() macro.
What the draft fix changed: In the same function, replaced `std::cerr << error_message << std::endl;` with `LOG(ERROR) << error_message;` exactly as suggested, so the validator failure is routed through glog/osquery's logging pipeline like other errors in this file, while retaining the existing `osquery::systemLog(error_message);` call above it.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

🔴 15. compress()/decompress() use std::vector<void> as raw byte buffers, wasting 8x memory and risking undefined behavior with read()/write()* — osquery/filesystem/file_compression.cpp:1
In compress(), changed std::vector<void*> buffIn(buffInSize) and std::vector<void*> buffOut(buffOutSize) to std::vector<char> for both buffers, matching the byte-count semantics of ZSTD_CStreamInSize()/ZSTD_CStreamOutSize() used with inFile.read()/ZSTD_compressStream(). No other logic changed.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In osquery/filesystem/file_compression.cpp around line 1, review and complete this code-review fix: compress()/decompress() use std::vector<void*> as raw byte buffers, wasting 8x memory and risking undefined behavior with read()/write().
What the draft fix changed: In compress(), changed `std::vector<void*> buffIn(buffInSize)` and `std::vector<void*> buffOut(buffOutSize)` to `std::vector<char>` for both buffers, matching the byte-count semantics of ZSTD_CStreamInSize()/ZSTD_CStreamOutSize() used with inFile.read()/ZSTD_compressStream(). No other logic changed.

_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer

🔴 16. decompress() repeats the same std::vector<void> buffer sizing bug as compress()* — osquery/filesystem/file_compression.cpp:1
In decompress(), changed std::vector<void*> buffIn(buffInSize) and std::vector<void*> buffOut(buffOutSize) to std::vector<char> for both buffers, matching the byte-count semantics of ZSTD_DStreamInSize()/ZSTD_DStreamOutSize() used with inFile.read()/ZSTD_decompressStream(). No other logic changed.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In osquery/filesystem/file_compression.cpp around line 1, review and complete this code-review fix: decompress() repeats the same std::vector<void*> buffer sizing bug as compress().
What the draft fix changed: In decompress(), changed `std::vector<void*> buffIn(buffInSize)` and `std::vector<void*> buffOut(buffOutSize)` to `std::vector<char>` for both buffers, matching the byte-count semantics of ZSTD_DStreamInSize()/ZSTD_DStreamOutSize() used with inFile.read()/ZSTD_decompressStream(). No other logic changed.

_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer

🔴 17. logon_sessions.cpp: unchecked map::find()->second on kLogonTypeToStr can dereference end() iteratorosquery/tables/system/windows/logon_sessions.cpp:65
In queryLogonSessions, replaced the unchecked kLogonTypeToStr.find(...)->second with a stored iterator (logon_type_it) that is checked against kLogonTypeToStr.end(); falls back to the string "Unknown" when the LogonType is not present in the map, preventing dereference of end().

🤖 Prompt for AI agents
In osquery/tables/system/windows/logon_sessions.cpp around line 65, review and complete this code-review fix: logon_sessions.cpp: unchecked map::find()->second on kLogonTypeToStr can dereference end() iterator.
What the draft fix changed: In queryLogonSessions, replaced the unchecked `kLogonTypeToStr.find(...)->second` with a stored iterator (`logon_type_it`) that is checked against `kLogonTypeToStr.end()`; falls back to the string "Unknown" when the LogonType is not present in the map, preventing dereference of end().
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 92 high — react 👍/👎 to teach the reviewer

🟠 18. logon_sessions.cpp never frees session_data or the sessions array returned by LSAosquery/tables/system/windows/logon_sessions.cpp:44
In queryLogonSessions, added LsaFreeReturnBuffer(session_data) immediately after each row is built inside the loop (releasing the per-session buffer from LsaGetLogonSessionData), and added LsaFreeReturnBuffer(sessions) after the loop completes (releasing the array from LsaEnumerateLogonSessions), fixing the LSA memory leak on every table invocation. Note: since continue on failed LsaGetLogonSessionData skips before any allocation occurs, no free is needed on that path.

🤖 Prompt for AI agents
In osquery/tables/system/windows/logon_sessions.cpp around line 44, review and complete this code-review fix: logon_sessions.cpp never frees session_data or the sessions array returned by LSA.
What the draft fix changed: In queryLogonSessions, added `LsaFreeReturnBuffer(session_data)` immediately after each row is built inside the loop (releasing the per-session buffer from LsaGetLogonSessionData), and added `LsaFreeReturnBuffer(sessions)` after the loop completes (releasing the array from LsaEnumerateLogonSessions), fixing the LSA memory leak on every table invocation. Note: since `continue` on failed LsaGetLogonSessionData skips before any allocation occurs, no free is needed on that path.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

🔴 19. Inverted existence check causes SCNetwork subscription targets to never be re-added during configure()osquery/events/darwin/scnetwork.cpp:108
In SCNetworkEventPublisher::configure(), inverted the two existence checks so that addAddress(sc)/addHostname(sc) are called when the target is NOT already present (existing_address == target_addresses_.end() and existing_hostname == target_names_.end()), instead of only when found. This ensures new subscription targets are actually registered.

🤖 Prompt for AI agents
In osquery/events/darwin/scnetwork.cpp around line 108, review and complete this code-review fix: Inverted existence check causes SCNetwork subscription targets to never be re-added during configure().
What the draft fix changed: In `SCNetworkEventPublisher::configure()`, inverted the two existence checks so that `addAddress(sc)`/`addHostname(sc)` are called when the target is NOT already present (`existing_address == target_addresses_.end()` and `existing_hostname == target_names_.end()`), instead of only when found. This ensures new subscription targets are actually registered.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

🔴 20. SCNetworkEventPublisher::Callback never fires the event to subscribersosquery/events/darwin/scnetwork.cpp:26
In SCNetworkEventPublisher::Callback(), added EventFactory::fire<SCNetworkEventPublisher>(ec); after setting ec->subscription and ec->flags so reachability change events are actually dispatched to subscribers, matching the pattern used by other publishers in the codebase. Unverified: exact template signature of EventFactory::fire for this publisher type versus how other files invoke it (some use EventFactory::fire<PublisherType>(ec), consistent with usage here), assumed to match existing conventions in the file's includes.

🤖 Prompt for AI agents
In osquery/events/darwin/scnetwork.cpp around line 26, review and complete this code-review fix: SCNetworkEventPublisher::Callback never fires the event to subscribers.
What the draft fix changed: In `SCNetworkEventPublisher::Callback()`, added `EventFactory::fire<SCNetworkEventPublisher>(ec);` after setting `ec->subscription` and `ec->flags` so reachability change events are actually dispatched to subscribers, matching the pattern used by other publishers in the codebase. Unverified: exact template signature of `EventFactory::fire` for this publisher type versus how other files invoke it (some use `EventFactory::fire<PublisherType>(ec)`, consistent with usage here), assumed to match existing conventions in the file's includes.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 70 medium — react 👍/👎 to teach the reviewer

🔴 21. Inverted boolean logic makes validateSocketDescriptor always fail when domain is setosquery/events/tests/linux/bpf/utils.cpp:170
In validateSocketDescriptor(const ProcessContext&, ...), fixed the inverted boolean logic on the guard checking socket_info.opt_type and socket_info.opt_protocol by adding the missing ! negation operators, changing socket_info.opt_type.has_value() || socket_info.opt_protocol.has_value() to !socket_info.opt_type.has_value() || !socket_info.opt_protocol.has_value(), matching the suggested fix exactly.

🤖 Prompt for AI agents
In osquery/events/tests/linux/bpf/utils.cpp around line 170, review and complete this code-review fix: Inverted boolean logic makes validateSocketDescriptor always fail when domain is set.
What the draft fix changed: In `validateSocketDescriptor(const ProcessContext&, ...)`, fixed the inverted boolean logic on the guard checking `socket_info.opt_type` and `socket_info.opt_protocol` by adding the missing `!` negation operators, changing `socket_info.opt_type.has_value() || socket_info.opt_protocol.has_value()` to `!socket_info.opt_type.has_value() || !socket_info.opt_protocol.has_value()`, matching the suggested fix exactly.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🔴 22. EtwProviderConfig::isValid() checks getPostProcessor() twice instead of also validating getPreProcessor()osquery/events/windows/etw/etw_provider_config.cpp:15
In EtwProviderConfig::isValid(), the second duplicate if (getPostProcessor() == nullptr) check was replaced with if (getPreProcessor() == nullptr), and its error message changed to "Invalid Provider PreProcessor function", matching the suggested fix exactly so the pre-processor callback is now actually validated.

🤖 Prompt for AI agents
In osquery/events/windows/etw/etw_provider_config.cpp around line 15, review and complete this code-review fix: EtwProviderConfig::isValid() checks getPostProcessor() twice instead of also validating getPreProcessor().
What the draft fix changed: In EtwProviderConfig::isValid(), the second duplicate `if (getPostProcessor() == nullptr)` check was replaced with `if (getPreProcessor() == nullptr)`, and its error message changed to "Invalid Provider PreProcessor function", matching the suggested fix exactly so the pre-processor callback is now actually validated.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🔴 23. genPortageKeywordSummary never actually calls the parser when unmasked file is missing/emptyosquery/tables/system/linux/portage.cpp:288
In genPortageKeywordSummary (osquery/tables/system/linux/portage.cpp), changed the condition !keywords.empty() || !masked.empty() || unmasked.empty() to !keywords.empty() || !masked.empty() || !unmasked.empty(), fixing the negation typo on unmasked so the parser is only invoked when at least one of the three files actually has content, matching the evident intent and the suggested fix.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In osquery/tables/system/linux/portage.cpp around line 288, review and complete this code-review fix: genPortageKeywordSummary never actually calls the parser when unmasked file is missing/empty.
What the draft fix changed: In `genPortageKeywordSummary` (osquery/tables/system/linux/portage.cpp), changed the condition `!keywords.empty() || !masked.empty() || unmasked.empty()` to `!keywords.empty() || !masked.empty() || !unmasked.empty()`, fixing the negation typo on `unmasked` so the parser is only invoked when at least one of the three files actually has content, matching the evident intent and the suggested fix.

_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer

🔴 24. requireAction uses bitwise-AND assignment instead of OR, silently discarding previously-set mask bitsosquery/events/darwin/fsevents.cpp:48
In FSEventsSubscriptionContext::requireAction (osquery/events/darwin/fsevents.cpp), changed mask = mask & bit.first; to mask = mask | bit.first; so successive calls accumulate action bits via bitwise-OR instead of erasing previously-set bits via bitwise-AND, matching the intended accumulation semantics used later in shouldFire.

🤖 Prompt for AI agents
In osquery/events/darwin/fsevents.cpp around line 48, review and complete this code-review fix: requireAction uses bitwise-AND assignment instead of OR, silently discarding previously-set mask bits.
What the draft fix changed: In `FSEventsSubscriptionContext::requireAction` (osquery/events/darwin/fsevents.cpp), changed `mask = mask & bit.first;` to `mask = mask | bit.first;` so successive calls accumulate action bits via bitwise-OR instead of erasing previously-set bits via bitwise-AND, matching the intended accumulation semantics used later in `shouldFire`.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🔴 25. Off-by-one/logic bug: hostname port-delimiter check uses unsigned wraparound when ':' is not foundosquery/tables/networking/curl_certificate.cpp:285
In getTLSCertificate, changed if (delim + 1 == hostname.length()) to if (delim != std::string::npos && delim + 1 == hostname.length()), explicitly guarding against the std::string::npos unsigned-wraparound case rather than relying on implicit overflow behavior, matching the suggested fix exactly.

🤖 Prompt for AI agents
In osquery/tables/networking/curl_certificate.cpp around line 285, review and complete this code-review fix: Off-by-one/logic bug: hostname port-delimiter check uses unsigned wraparound when ':' is not found.
What the draft fix changed: In `getTLSCertificate`, changed `if (delim + 1 == hostname.length())` to `if (delim != std::string::npos && delim + 1 == hostname.length())`, explicitly guarding against the `std::string::npos` unsigned-wraparound case rather than relying on implicit overflow behavior, matching the suggested fix exactly.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 98 high — react 👍/👎 to teach the reviewer

🟠 26. cleanOldAggregationCacheEntries erases the current iterator then increments it, causing use-after-eraseosquery/events/windows/etw/etw_publisher_processes.cpp:353
In cleanOldAggregationCacheEntries(), replaced the unconditional processStartAggregationCache_.erase(it); ++it; sequence with it = processStartAggregationCache_.erase(it); in the expired branch and ++it; only in an added else branch, exactly per the suggested fix, eliminating the use-after-erase undefined behavior.

🤖 Prompt for AI agents
In osquery/events/windows/etw/etw_publisher_processes.cpp around line 353, review and complete this code-review fix: cleanOldAggregationCacheEntries erases the current iterator then increments it, causing use-after-erase.
What the draft fix changed: In cleanOldAggregationCacheEntries(), replaced the unconditional `processStartAggregationCache_.erase(it); ++it;` sequence with `it = processStartAggregationCache_.erase(it);` in the expired branch and `++it;` only in an added else branch, exactly per the suggested fix, eliminating the use-after-erase undefined behavior.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🟠 27. processImageCache_ in EtwPublisherProcesses grows unbounded with no evictionosquery/events/windows/etw/etw_publisher_processes.cpp:320
Added a time-based eviction policy for processImageCache_: the map value type is assumed to now be a {std::string imageName, std::time_t insertedAt} pair (this requires a corresponding header change to etw_publisher_processes.h that is NOT included in this file and was not provided, so the code as shown here will not compile without that header update). Added cleanOldProcessImageCacheEntries() (declared but not defined in the visible header) called before each insert in providerPostProcessor(), using a 300-second expiry window analogous to the aggregation cache's 10-second window. Also changed updateImagePath() to look up by iterator and erase the entry after consumption (bounding cache growth further for entries that are actually consumed) instead of using tryTake against the old value type. RISK: this is a cross-file change in spirit — the struct/type change to processImageCache_'s value and the new method declaration must be mirrored in etw_publisher_processes.h, which I cannot see/edit here; as given, this file alone will fail to compile until the header is updated to match. A safer, header-compatible alternative (capping map size or reusing the existing value type with a separate parallel timestamp map) could avoid the header dependency, but was not chosen because it would be uglier and less correct; reviewer must add the corresponding header changes or ask me to redo this against the actual header contents.

🤖 Prompt for AI agents
In osquery/events/windows/etw/etw_publisher_processes.cpp around line 320, review and complete this code-review fix: processImageCache_ in EtwPublisherProcesses grows unbounded with no eviction.
What the draft fix changed: Added a time-based eviction policy for processImageCache_: the map value type is assumed to now be a `{std::string imageName, std::time_t insertedAt}` pair (this requires a corresponding header change to `etw_publisher_processes.h` that is NOT included in this file and was not provided, so the code as shown here will not compile without that header update). Added `cleanOldProcessImageCacheEntries()` (declared but not defined in the visible header) called before each insert in providerPostProcessor(), using a 300-second expiry window analogous to the aggregation cache's 10-second window. Also changed `updateImagePath()` to look up by iterator and erase the entry after consumption (bounding cache growth further for entries that are actually consumed) instead of using `tryTake` against the old value type. RISK: this is a cross-file change in spirit — the struct/type change to processImageCache_'s value and the new method declaration must be mirrored in `etw_publisher_processes.h`, which I cannot see/edit here; as given, this file alone will fail to compile until the header is updated to match. A safer, header-compatible alternative (capping map size or reusing the existing value type with a separate parallel timestamp map) could avoid the header dependency, but was not chosen because it would be uglier and less correct; reviewer must add the corresponding header changes or ask me to redo this against the actual header contents.
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 45 low — review closely — react 👍/👎 to teach the reviewer

🟠 28. Insecure/deprecated os.makedirs mode literal uses Python 2 octal syntax (0755) — will fail to parse under Python 3tools/codegen/gentargets.py:128
Changed os.makedirs(os.path.dirname(p), 0755) to os.makedirs(os.path.dirname(p), 0o755) inside the __main__ block's source-copy loop, fixing the Python 2 octal literal syntax error under Python 3.

🤖 Prompt for AI agents
In tools/codegen/gentargets.py around line 128, review and complete this code-review fix: Insecure/deprecated os.makedirs mode literal uses Python 2 octal syntax (0755) — will fail to parse under Python 3.
What the draft fix changed: Changed `os.makedirs(os.path.dirname(p), 0755)` to `os.makedirs(os.path.dirname(p), 0o755)` inside the `__main__` block's source-copy loop, fixing the Python 2 octal literal syntax error under Python 3.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🟠 29. JSON parse failure in gentargets.py is logged critical but execution continues, leading to a later crashtools/codegen/gentargets.py:112
Added import sys at the top and sys.exit(1) after the logging.critical call in the except ValueError block (JSON parse failure) inside the __main__ block, so the script exits cleanly with a non-zero status instead of falling through to use the undefined json_data variable.

🤖 Prompt for AI agents
In tools/codegen/gentargets.py around line 112, review and complete this code-review fix: JSON parse failure in gentargets.py is logged critical but execution continues, leading to a later crash.
What the draft fix changed: Added `import sys` at the top and `sys.exit(1)` after the `logging.critical` call in the `except ValueError` block (JSON parse failure) inside the `__main__` block, so the script exits cleanly with a non-zero status instead of falling through to use the undefined `json_data` variable.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

🟠 30. queries_from_pack references undefined variable config_path in error messagetools/tests/utils.py:116
In queries_from_pack() (tools/tests/utils.py), changed the undefined config_path reference in the error message printed when the 'queries' stanza is missing to pack_path, matching the function's actual parameter name.

🤖 Prompt for AI agents
In tools/tests/utils.py around line 116, review and complete this code-review fix: queries_from_pack references undefined variable config_path in error message.
What the draft fix changed: In queries_from_pack() (tools/tests/utils.py), changed the undefined `config_path` reference in the error message printed when the 'queries' stanza is missing to `pack_path`, matching the function's actual parameter name.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🔵 31. profile_cmd() calls p.wait() twice, second call after process already reapedtools/tests/utils.py:190
In profile_cmd() (tools/tests/utils.py), replaced the second p.wait() call inside the returned rval dict's "exit" key with the already-computed exit_code variable, avoiding a redundant/unsafe second wait() call on an already-reaped process.

🤖 Prompt for AI agents
In tools/tests/utils.py around line 190, review and complete this code-review fix: profile_cmd() calls p.wait() twice, second call after process already reaped.
What the draft fix changed: In profile_cmd() (tools/tests/utils.py), replaced the second `p.wait()` call inside the returned `rval` dict's "exit" key with the already-computed `exit_code` variable, avoiding a redundant/unsafe second wait() call on an already-reaped process.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer

🟠 32. getProcessProperties() copies egid into euid field, duplicating egid lookup and never reading ruid for euidosquery/events/darwin/es_utils.cpp:152
In getProcessProperties() (osquery/events/darwin/es_utils.cpp), changed ec->euid = audit_token_to_egid(audit_token); to ec->euid = audit_token_to_euid(audit_token); so the effective UID field is populated from the correct audit token accessor, matching the suggested fix exactly; ec->egid remains unchanged via audit_token_to_egid.

🤖 Prompt for AI agents
In osquery/events/darwin/es_utils.cpp around line 152, review and complete this code-review fix: getProcessProperties() copies egid into euid field, duplicating egid lookup and never reading ruid for euid.
What the draft fix changed: In getProcessProperties() (osquery/events/darwin/es_utils.cpp), changed `ec->euid = audit_token_to_egid(audit_token);` to `ec->euid = audit_token_to_euid(audit_token);` so the effective UID field is populated from the correct audit token accessor, matching the suggested fix exactly; ec->egid remains unchanged via audit_token_to_egid.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🟠 33. getCDHash() uses find_first_not_of(s.front()) which is a character-search bug, not an all-zero-checkosquery/events/darwin/es_utils.cpp:120
In getCDHash() (osquery/events/darwin/es_utils.cpp), changed s.find_first_not_of(s.front()) to s.find_first_not_of('0') so the function correctly detects an all-zero cdhash string (all '0' hex characters) and returns "" in that case, instead of comparing against the arbitrary first character. This assumes the intended "empty/zero" representation is a string of all '0' characters, consistent with the finding's stated intent; if the true empty-cdhash sentinel differs (e.g., all-zero bytes might not always hex-format to "000...0" in edge cases, though it will for this fixed-width formatting), further verification against actual ES cdhash semantics would be needed.

🤖 Prompt for AI agents
In osquery/events/darwin/es_utils.cpp around line 120, review and complete this code-review fix: getCDHash() uses find_first_not_of(s.front()) which is a character-search bug, not an all-zero-check.
What the draft fix changed: In getCDHash() (osquery/events/darwin/es_utils.cpp), changed `s.find_first_not_of(s.front())` to `s.find_first_not_of('0')` so the function correctly detects an all-zero cdhash string (all '0' hex characters) and returns "" in that case, instead of comparing against the arbitrary first character. This assumes the intended "empty/zero" representation is a string of all '0' characters, consistent with the finding's stated intent; if the true empty-cdhash sentinel differs (e.g., all-zero bytes might not always hex-format to "000...0" in edge cases, though it will for this fixed-width formatting), further verification against actual ES cdhash semantics would be needed.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 70 medium — react 👍/👎 to teach the reviewer

🟠 34. isOpenSSHKeyEncrypted can read out-of-bounds via substr on short key contentosquery/tables/system/ssh_keys.cpp:44
In isOpenSSHKeyEncrypted() (osquery/tables/system/ssh_keys.cpp), added a length guard if (keys_content.size() <= kOpenSshHeader.size() + 1) { return false; } before the substr() call, preventing std::out_of_range from being thrown on truncated/short OpenSSH key content.

🤖 Prompt for AI agents
In osquery/tables/system/ssh_keys.cpp around line 44, review and complete this code-review fix: isOpenSSHKeyEncrypted can read out-of-bounds via substr on short key content.
What the draft fix changed: In isOpenSSHKeyEncrypted() (osquery/tables/system/ssh_keys.cpp), added a length guard `if (keys_content.size() <= kOpenSshHeader.size() + 1) { return false; }` before the `substr()` call, preventing std::out_of_range from being thrown on truncated/short OpenSSH key content.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer

🟠 35. BIO_new result checked for null after being used, and passed to guard before null-checkosquery/tables/system/ssh_keys.cpp:62
In parsePrivateKey() (osquery/tables/system/ssh_keys.cpp), moved the bio_stream == nullptr null check to immediately after BIO_new(BIO_s_mem()) and before both the scope_guard creation and the BIO_write() call, eliminating the null-pointer dereference into OpenSSL when BIO_new fails.

🤖 Prompt for AI agents
In osquery/tables/system/ssh_keys.cpp around line 62, review and complete this code-review fix: BIO_new result checked for null after being used, and passed to guard before null-check.
What the draft fix changed: In parsePrivateKey() (osquery/tables/system/ssh_keys.cpp), moved the `bio_stream == nullptr` null check to immediately after `BIO_new(BIO_s_mem())` and before both the scope_guard creation and the `BIO_write()` call, eliminating the null-pointer dereference into OpenSSL when BIO_new fails.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer

🟠 36. Kafka topic_conf leaked when topic conf set fails in initTopicplugins/logger/kafka_producer.cpp:267
In initTopic (plugins/logger/kafka_producer.cpp), added rd_kafka_topic_conf_destroy(topicConf) immediately before the return nullptr; in the rd_kafka_topic_conf_set failure branch, so the allocated topicConf is freed instead of leaked on failure.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In plugins/logger/kafka_producer.cpp around line 267, review and complete this code-review fix: Kafka topic_conf leaked when topic conf set fails in initTopic.
What the draft fix changed: In `initTopic` (plugins/logger/kafka_producer.cpp), added `rd_kafka_topic_conf_destroy(topicConf)` immediately before the `return nullptr;` in the `rd_kafka_topic_conf_set` failure branch, so the allocated `topicConf` is freed instead of leaked on failure.

_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer

🟠 37. configureTopics() base-topic branch overwrites queryToTopics_[kKafkaBaseTopic] with nullptr on failed initTopic, silently breaking base-topic fallbackplugins/logger/kafka_producer.cpp:314
In configureTopics(), the base-topic branch now checks initTopic()'s result: on success it pushes the topic and assigns queryToTopics_[kKafkaBaseTopic] = topic; as before; on failure it logs an ERROR (new log line, since the prior single ERROR from initTopic didn't call out the base-topic context specifically) and falls through to the same "no topics configured" failure path used by the empty-flag branch (return false if topics_ is empty, otherwise sets queryToTopics_[kKafkaBaseTopic] = nullptr explicitly as a documented fallback rather than an accidental nullptr assignment). This preserves prior behavior for the success path exactly and makes the failure path explicit and consistent with the else-branch semantics; reviewer should confirm whether returning false (treating a failed explicitly-configured base topic as fatal when no other topics exist) matches intended semantics, versus always continuing with a null base topic.

🤖 Prompt for AI agents
In plugins/logger/kafka_producer.cpp around line 314, review and complete this code-review fix: configureTopics() base-topic branch overwrites queryToTopics_[kKafkaBaseTopic] with nullptr on failed initTopic, silently breaking base-topic fallback.
What the draft fix changed: In `configureTopics()`, the base-topic branch now checks `initTopic()`'s result: on success it pushes the topic and assigns `queryToTopics_[kKafkaBaseTopic] = topic;` as before; on failure it logs an ERROR (new log line, since the prior single ERROR from `initTopic` didn't call out the base-topic context specifically) and falls through to the same "no topics configured" failure path used by the empty-flag branch (`return false` if `topics_` is empty, otherwise sets `queryToTopics_[kKafkaBaseTopic] = nullptr` explicitly as a documented fallback rather than an accidental nullptr assignment). This preserves prior behavior for the success path exactly and makes the failure path explicit and consistent with the else-branch semantics; reviewer should confirm whether returning `false` (treating a failed explicitly-configured base topic as fatal when no other topics exist) matches intended semantics, versus always continuing with a null base topic.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 65 medium — react 👍/👎 to teach the reviewer

🟠 38. Shadowed variable name event_list in WindowsEventLogPublisher::run looposquery/events/windows/windowseventlogpublisher.cpp:155
Removed the dead/unused outer EvtSubscription::EventList event_list; declaration in WindowsEventLogPublisher::run's outer while loop, eliminating the shadowing of the inner for loop's auto event_list = subscription->getEvents();. The inner loop is unaffected and retains its own scoped event_list.

🤖 Prompt for AI agents
In osquery/events/windows/windowseventlogpublisher.cpp around line 155, review and complete this code-review fix: Shadowed variable name `event_list` in WindowsEventLogPublisher::run loop.
What the draft fix changed: Removed the dead/unused outer `EvtSubscription::EventList event_list;` declaration in `WindowsEventLogPublisher::run`'s outer `while` loop, eliminating the shadowing of the inner `for` loop's `auto event_list = subscription->getEvents();`. The inner loop is unaffected and retains its own scoped `event_list`.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🟠 39. Potential division by zero in cosineSimilarity when buffer_size is 0osquery/events/windows/windowseventlogpublisher.cpp:214
Added a guard if (buffer_size == 0) { return 0.0; } immediately after computing buffer_size in WindowsEventLogPublisher::cosineSimilarity, before the frequency-accumulation loop, preventing division by zero when buffer is empty.

🤖 Prompt for AI agents
In osquery/events/windows/windowseventlogpublisher.cpp around line 214, review and complete this code-review fix: Potential division by zero in cosineSimilarity when buffer_size is 0.
What the draft fix changed: Added a guard `if (buffer_size == 0) { return 0.0; }` immediately after computing `buffer_size` in `WindowsEventLogPublisher::cosineSimilarity`, before the frequency-accumulation loop, preventing division by zero when `buffer` is empty.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

🟠 40. executeCarve() truncates carve-status message to a hardcoded length of 13, corrupting outputosquery/sql/sqlite_operations.cpp:53
In executeCarve() (osquery/sql/sqlite_operations.cpp), replaced the hardcoded length argument 13 in both sqlite3_result_text calls with static_cast<int>(message.size()), where message is a newly introduced local std::string holding either "Carve Started: " + new_carve_guid or "Carve Failed: function disabled". This ensures the full message text is returned instead of being truncated to 13 bytes.

🤖 Prompt for AI agents
In osquery/sql/sqlite_operations.cpp around line 53, review and complete this code-review fix: executeCarve() truncates carve-status message to a hardcoded length of 13, corrupting output.
What the draft fix changed: In executeCarve() (osquery/sql/sqlite_operations.cpp), replaced the hardcoded length argument `13` in both sqlite3_result_text calls with `static_cast<int>(message.size())`, where `message` is a newly introduced local std::string holding either "Carve Started: " + new_carve_guid or "Carve Failed: function disabled". This ensures the full message text is returned instead of being truncated to 13 bytes.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🔴 41. pidsFromContext copies procs into itself instead of the newly-queried proc resultosquery/tables/system/system_utils.cpp:29
In pidsFromContext (osquery/tables/system/system_utils.cpp), changed procs.insert(procs.end(), procs.begin(), procs.end()) to procs.insert(procs.end(), proc.begin(), proc.end()) so the per-pid query result proc is correctly appended into the accumulator procs, fixing the self-referential insert and matching the pattern used in usersFromContext.

🤖 Prompt for AI agents
In osquery/tables/system/system_utils.cpp around line 29, review and complete this code-review fix: pidsFromContext copies procs into itself instead of the newly-queried proc result.
What the draft fix changed: In pidsFromContext (osquery/tables/system/system_utils.cpp), changed `procs.insert(procs.end(), procs.begin(), procs.end())` to `procs.insert(procs.end(), proc.begin(), proc.end())` so the per-pid query result `proc` is correctly appended into the accumulator `procs`, fixing the self-referential insert and matching the pattern used in usersFromContext.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

🔴 42. FakeEventSubscriber(bool skip_name) constructor calls FakeEventSubscriber() as a temporary, not delegating constructionosquery/events/tests/events_tests.cpp:297
In FakeEventSubscriber::FakeEventSubscriber(bool skip_name) (osquery/events/tests/events_tests.cpp), replaced the bare expression statement FakeEventSubscriber(); (which constructed and discarded a temporary) with setName("fake_events");, directly calling setName on this as the finding indicates was intended, matching the behavior of the default constructor without using an invalid delegating-constructor-in-body pattern.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In osquery/events/tests/events_tests.cpp around line 297, review and complete this code-review fix: FakeEventSubscriber(bool skip_name) constructor calls FakeEventSubscriber() as a temporary, not delegating construction.
What the draft fix changed: In `FakeEventSubscriber::FakeEventSubscriber(bool skip_name)` (osquery/events/tests/events_tests.cpp), replaced the bare expression statement `FakeEventSubscriber();` (which constructed and discarded a temporary) with `setName("fake_events");`, directly calling setName on `this` as the finding indicates was intended, matching the behavior of the default constructor without using an invalid delegating-constructor-in-body pattern.

_(Automatically downgraded: no change in this fix lands near this fi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants