From e2510463a58dcdc103ccf2c2539a69211f110285 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:26 +0000 Subject: [PATCH 01/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- plugins/database/sqlite.cpp | 122 ++++++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 27 deletions(-) diff --git a/plugins/database/sqlite.cpp b/plugins/database/sqlite.cpp index 9423b266451..8549d06525c 100644 --- a/plugins/database/sqlite.cpp +++ b/plugins/database/sqlite.cpp @@ -115,20 +115,29 @@ static int getData(void* argument, int argc, char* argv[], char* column[]) { 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"]); - return Status(0); + sqlite3_bind_text(stmt, 1, key.c_str(), -1, SQLITE_STATIC); + + Status result = Status(1); + rc = sqlite3_step(stmt); + if (rc == SQLITE_ROW) { + const auto* text = sqlite3_column_text(stmt, 0); + value = (text != nullptr) ? std::string(reinterpret_cast(text)) + : std::string(); + result = Status(0); } - return Status(1); + + sqlite3_finalize(stmt); + return result; } Status SQLiteDatabasePlugin::get(const std::string& domain, @@ -156,9 +165,25 @@ static void tryVacuum(sqlite3* db) { "s1.rowid + 1 = s2.rowid; "; QueryData results; - sqlite3_exec(db, q.c_str(), getData, &results, nullptr); + char* err = nullptr; + auto rc = sqlite3_exec(db, q.c_str(), getData, &results, &err); + if (rc != SQLITE_OK) { + if (err != nullptr) { + LOG(WARNING) << "tryVacuum stat query failed: " << err; + sqlite3_free(err); + } + return; + } + if (results.size() > 0 && results[0]["v"].back() == '1') { - sqlite3_exec(db, "vacuum;", nullptr, nullptr, nullptr); + err = nullptr; + rc = sqlite3_exec(db, "vacuum;", nullptr, nullptr, &err); + if (rc != SQLITE_OK) { + if (err != nullptr) { + LOG(WARNING) << "tryVacuum vacuum failed: " << err; + sqlite3_free(err); + } + } } } @@ -195,7 +220,13 @@ Status SQLiteDatabasePlugin::putBatch(const std::string& domain, // Bind each value from the rows we got sqlite3_stmt* stmt = nullptr; - 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); + } { int i = 1; @@ -213,6 +244,7 @@ Status SQLiteDatabasePlugin::putBatch(const std::string& domain, auto rc = sqlite3_step(stmt); if (rc != SQLITE_DONE) { + sqlite3_finalize(stmt); return Status(1); } @@ -228,11 +260,18 @@ Status SQLiteDatabasePlugin::remove(const std::string& domain, 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); } @@ -252,12 +291,19 @@ Status SQLiteDatabasePlugin::removeRange(const std::string& domain, sqlite3_stmt* stmt = nullptr; std::string q = "delete from " + domain + " where key >= ?1 and key <= ?2;"; - 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, low.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 2, high.c_str(), -1, SQLITE_STATIC); auto rc = sqlite3_step(stmt); if (rc != SQLITE_DONE) { + sqlite3_finalize(stmt); return Status(1); } @@ -272,24 +318,46 @@ Status SQLiteDatabasePlugin::scan(const std::string& domain, std::vector& results, const std::string& prefix, uint64_t max) const { - QueryData _results; - char* err = nullptr; - - std::string q = - "select key from " + domain + " where key LIKE '" + prefix + "%'"; + sqlite3_stmt* stmt = nullptr; + std::string q = "select key from " + domain + " where key LIKE ?1 ESCAPE '\\'"; if (max > 0) { q += " limit " + std::to_string(max); } - sqlite3_exec(db_, q.c_str(), getData, &_results, &err); - if (err != nullptr) { - sqlite3_free(err); + q += ";"; + + 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::success(); } - // Only assign value if the query found a result. - for (auto& r : _results) { - results.push_back(std::move(r["key"])); + // Escape LIKE wildcard characters in the prefix before binding, since the + // prefix is user/config-derived and must not alter the query semantics. + std::string escapedPrefix; + escapedPrefix.reserve(prefix.size()); + for (const auto& c : prefix) { + if (c == '%' || c == '_' || c == '\\') { + escapedPrefix.push_back('\\'); + } + escapedPrefix.push_back(c); } + escapedPrefix += "%"; + sqlite3_bind_text(stmt, 1, escapedPrefix.c_str(), -1, SQLITE_TRANSIENT); + + int rc = 0; + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + const auto* text = sqlite3_column_text(stmt, 0); + if (text != nullptr) { + results.push_back(std::string(reinterpret_cast(text))); + } else { + results.push_back(std::string()); + } + } + + sqlite3_finalize(stmt); return Status::success(); } } // namespace osquery From 689a01161e77a033c351054e981b7b81a32d1554 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:27 +0000 Subject: [PATCH 02/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- tools/tests/test_windows_service.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/tests/test_windows_service.py b/tools/tests/test_windows_service.py index ae0f6a48ebb..35b5638816b 100644 --- a/tools/tests/test_windows_service.py +++ b/tools/tests/test_windows_service.py @@ -103,11 +103,11 @@ def sc(*args): ['sc.exe'] + list(args), stderr=subprocess.PIPE, stdout=subprocess.PIPE) - except subprocess.CalledProcessError, err: + except subprocess.CalledProcessError as err: return (err.returncode, err.output) out, _ = p.communicate() - out = [x.strip() for x in out.split('\r\n') if x.strip() is not ''] + out = [x.strip() for x in out.split('\r\n') if x.strip() != ''] if len(out) >= 1: if 'SUCCESS' in out[0]: @@ -246,10 +246,10 @@ def setUp(self): self.flagfile = os.path.join(self.tmp_dir, 'osquery.flags') # Write out our mock configuration files - with open(self.config_path, 'wb') as fd: + with open(self.config_path, 'w') as fd: fd.write(CONFIG_FILE) - with open(self.flagfile, 'wb') as fd: + with open(self.flagfile, 'w') as fd: fd.write( FLAGS_FILE.format(self.log_path, self.pidfile, test_http_server.HTTP_SERVER_CA, From fbad87613293a5a8805ed0bc33559c528b786843 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:28 +0000 Subject: [PATCH 03/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/applications/jetbrains_plugins.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osquery/tables/applications/jetbrains_plugins.cpp b/osquery/tables/applications/jetbrains_plugins.cpp index b0cb4c4046a..829c355f934 100644 --- a/osquery/tables/applications/jetbrains_plugins.cpp +++ b/osquery/tables/applications/jetbrains_plugins.cpp @@ -27,6 +27,9 @@ namespace tables { // Function to convert JetBrainsProductType enum to string const std::string getProductName(const JetBrainsProductType type) { auto product = kProductTypeToString.find(type); + if (product == kProductTypeToString.end()) { + return "unknown"; + } return product->second; } @@ -50,8 +53,7 @@ FileData extractSpecificFileFromArchive(const std::string& archive_file_path, if (archive != nullptr) { int free_result = archive_read_free(archive); if (free_result != ARCHIVE_OK) { - VLOG(1) << "Failed to close zip file: " << archive_error_string(archive) - << std::endl; + VLOG(1) << "Failed to close zip file: " << archive_error_string(archive); } } }); @@ -59,8 +61,7 @@ FileData extractSpecificFileFromArchive(const std::string& archive_file_path, result = archive_read_open_filename( archive, archive_file_path.c_str(), 10240); // 10KB buffer if (result != ARCHIVE_OK) { - VLOG(1) << "Failed to open zip file: " << archive_error_string(archive) - << std::endl; + VLOG(1) << "Failed to open zip file: " << archive_error_string(archive); return file_data; } @@ -87,8 +88,7 @@ FileData extractSpecificFileFromArchive(const std::string& archive_file_path, } if (archive_errno(archive) != 0) { - VLOG(1) << "Error reading data block: " << archive_error_string(archive) - << std::endl; + VLOG(1) << "Error reading data block: " << archive_error_string(archive); } break; @@ -437,3 +437,4 @@ QueryData genJetBrainsPlugins(QueryContext& context) { } } // namespace tables } // namespace osquery + From 6007dcf6d66f7965ba3de1e8a8c015596f45d84f Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:29 +0000 Subject: [PATCH 04/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/events/darwin/es_utils.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osquery/events/darwin/es_utils.cpp b/osquery/events/darwin/es_utils.cpp index 2d3afc38e32..53a62ccda0f 100644 --- a/osquery/events/darwin/es_utils.cpp +++ b/osquery/events/darwin/es_utils.cpp @@ -157,9 +157,9 @@ void getProcessProperties(const es_process_t* p, ec->codesigning_flags = getCodesigningFlags(p); auto user = getpwuid(ec->uid); - ec->username = user->pw_name != nullptr ? std::string(user->pw_name) : ""; - - ec->cwd = getCwdPathFromPid(ec->pid); + ec->username = (user != nullptr && user->pw_name != nullptr) + ? std::string(user->pw_name) + : ""; } void appendQuotedString(std::ostream& out, std::string s, char delim) { @@ -171,3 +171,4 @@ void appendQuotedString(std::ostream& out, std::string s, char delim) { } } // namespace osquery + From a01d2ed7dde25615321da69298878a9686a1852c Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:30 +0000 Subject: [PATCH 05/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/core/windows/wmi.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osquery/core/windows/wmi.cpp b/osquery/core/windows/wmi.cpp index 89c821a97d0..4d594d644f5 100644 --- a/osquery/core/windows/wmi.cpp +++ b/osquery/core/windows/wmi.cpp @@ -205,7 +205,7 @@ Status WmiResultItem::GetUnsignedInt32(const std::string& name, VariantClear(&value); return Status::failure("Invalid data type returned."); } - ret = value.uiVal; + ret = value.uintVal; VariantClear(&value); return Status::success(); } @@ -238,7 +238,7 @@ Status WmiResultItem::GetUnsignedLong(const std::string& name, VariantClear(&value); return Status::failure("Invalid data type returned."); } - ret = value.lVal; + ret = value.ulVal; VariantClear(&value); return Status::success(); } @@ -255,7 +255,7 @@ Status WmiResultItem::GetLongLong(const std::string& name, VariantClear(&value); return Status::failure("Invalid data type returned."); } - ret = value.lVal; + ret = value.llVal; VariantClear(&value); return Status::success(); } @@ -272,7 +272,7 @@ Status WmiResultItem::GetUnsignedLongLong(const std::string& name, VariantClear(&value); return Status::failure("Invalid data type returned."); } - ret = value.lVal; + ret = value.ullVal; VariantClear(&value); return Status::success(); } @@ -598,3 +598,4 @@ Status WmiRequest::ExecMethod(const WmiResultItem& object, } } // namespace osquery + From ccaced3f357b2ec064a46f9dfadbbd02f838a47c Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:31 +0000 Subject: [PATCH 06/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/windows/smbios_tables.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osquery/tables/system/windows/smbios_tables.cpp b/osquery/tables/system/windows/smbios_tables.cpp index 01c1f4d852c..fc03809c886 100644 --- a/osquery/tables/system/windows/smbios_tables.cpp +++ b/osquery/tables/system/windows/smbios_tables.cpp @@ -29,8 +29,8 @@ const std::vector kFormFactors = { }; std::string getFormFactor(long id) { - if (id < kFormFactors.size()) { - return kFormFactors[id]; + if (id >= 0 && static_cast(id) < kFormFactors.size()) { + return kFormFactors[static_cast(id)]; } return std::to_string(id); } @@ -45,8 +45,8 @@ const std::vector kMemoryTypes = { "DDR3", "FBD2", "DDR4"}; std::string getMemoryType(int id) { - if (id < kMemoryTypes.size()) { - return kMemoryTypes[id]; + if (id >= 0 && static_cast(id) < kMemoryTypes.size()) { + return kMemoryTypes[static_cast(id)]; } return std::to_string(id); } From 6ae3fe7de2f2c38a7c49cb81f3b64c1b4b537e0a Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:32 +0000 Subject: [PATCH 07/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/events/darwin/scnetwork.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osquery/events/darwin/scnetwork.cpp b/osquery/events/darwin/scnetwork.cpp index 9c2fa1b2b29..8e0aa816982 100644 --- a/osquery/events/darwin/scnetwork.cpp +++ b/osquery/events/darwin/scnetwork.cpp @@ -50,7 +50,7 @@ void SCNetworkEventPublisher::addTarget( // Assign a context (the subscription context) to the target. SCNetworkReachabilityContext* context = new SCNetworkReachabilityContext(); - context->info = (void*)≻ + context->info = (void*)(new SCNetworkSubscriptionContextRef(sc)); context->retain = nullptr; context->release = nullptr; contexts_.push_back(context); @@ -94,6 +94,7 @@ void SCNetworkEventPublisher::clearAll() { targets_.clear(); for (auto& context : contexts_) { + delete (SCNetworkSubscriptionContextRef*)(context->info); delete context; } contexts_.clear(); @@ -116,14 +117,14 @@ void SCNetworkEventPublisher::configure() { if (sc->type == ADDRESS_TARGET) { auto existing_address = std::find( target_addresses_.begin(), target_addresses_.end(), sc->target); - if (existing_address != target_addresses_.end()) { + if (existing_address == target_addresses_.end()) { // Add the address target. addAddress(sc); } } else { auto existing_hostname = std::find(target_names_.begin(), target_names_.end(), sc->target); - if (existing_hostname != target_names_.end()) { + if (existing_hostname == target_names_.end()) { // Add the hostname target. addHostname(sc); } @@ -183,3 +184,4 @@ Status SCNetworkEventPublisher::run() { return Status::success(); } }; + From 6a658b49ac5fe1dc36fcdcf1b8077474f9cbeb23 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:33 +0000 Subject: [PATCH 08/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- .../tables/system/windows/windows_search.cpp | 136 +++++++++++++++--- 1 file changed, 116 insertions(+), 20 deletions(-) diff --git a/osquery/tables/system/windows/windows_search.cpp b/osquery/tables/system/windows/windows_search.cpp index 57aa320491c..1f0c87f56b4 100644 --- a/osquery/tables/system/windows/windows_search.cpp +++ b/osquery/tables/system/windows/windows_search.cpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace osquery { namespace tables { @@ -242,10 +243,65 @@ osquery::QueryData executeWindowsSearchQuery(CSession& cSession, return results; } -std::string generateSqlFromUserQuery(const std::string& userInput, - std::set columns, - std::string sort, - LONG maxResults) { +// Validates that a candidate column/property name is safe to embed in the +// SQL fragments passed to ISearchQueryHelper. Only allow alphanumeric +// characters, dots and underscores (the shape of valid Windows Search +// property names, e.g. "system.itemname"), and require it to be a known +// (allowlisted) property. +bool isAllowedSearchColumn(const std::string& column, + const std::set& allowedColumns) { + if (column.empty()) { + return false; + } + + for (const auto& c : column) { + if (!(std::isalnum(static_cast(c)) || c == '.' || + c == '_')) { + return false; + } + } + + return allowedColumns.count(column) > 0; +} + +// Validates a sort expression of the form "[ ASC|DESC][, ...]" +// against the allowlist of known columns. +bool isAllowedSearchSort(const std::string& sort, + const std::set& allowedColumns) { + if (sort.empty()) { + return false; + } + + for (const auto& clause : osquery::split(sort, ",")) { + auto parts = osquery::split(clause, " "); + if (parts.empty()) { + return false; + } + + if (!isAllowedSearchColumn(parts[0], allowedColumns)) { + return false; + } + + if (parts.size() == 2) { + std::string direction = parts[1]; + std::transform( + direction.begin(), direction.end(), direction.begin(), ::toupper); + if (direction != "ASC" && direction != "DESC") { + return false; + } + } else if (parts.size() > 2) { + return false; + } + } + + return true; +} + +Status generateSqlFromUserQuery(const std::string& userInput, + std::set columns, + std::string sort, + LONG maxResults, + std::string& generatedSql) { HRESULT hr = NULL; // Create ISearchManager instance @@ -258,7 +314,7 @@ std::string generateSqlFromUserQuery(const std::string& userInput, if (FAILED(hr)) { LOG(ERROR) << windowsSearchTableName << ": failed to create ISearchManager instance"; - return ""; + return Status::failure("failed to create ISearchManager instance"); } auto const pSearchManagerGuard = scope_guard::create([pSearchManager]() { pSearchManager->Release(); }); @@ -270,7 +326,7 @@ std::string generateSqlFromUserQuery(const std::string& userInput, hr = pSearchManager->GetCatalog(L"SystemIndex", &pSearchCatalogManager); if (FAILED(hr)) { LOG(ERROR) << windowsSearchTableName << ": failed to get catalog manager"; - return ""; + return Status::failure("failed to get catalog manager"); } auto const pSearchCatalogManagerGuard = scope_guard::create( [pSearchCatalogManager]() { pSearchCatalogManager->Release(); }); @@ -281,7 +337,7 @@ std::string generateSqlFromUserQuery(const std::string& userInput, hr = pSearchCatalogManager->GetQueryHelper(&pQueryHelper); if (FAILED(hr)) { LOG(ERROR) << windowsSearchTableName << ": failed to get query helper"; - return ""; + return Status::failure("failed to get query helper"); } auto const pQueryHelperGuard = scope_guard::create([pQueryHelper]() { pQueryHelper->Release(); }); @@ -289,13 +345,13 @@ std::string generateSqlFromUserQuery(const std::string& userInput, hr = pQueryHelper->put_QueryMaxResults(maxResults); if (FAILED(hr)) { LOG(ERROR) << windowsSearchTableName << ": failed to set max results"; - return ""; + return Status::failure("failed to set max results"); } if (!columns.empty()) { - // TODO: find a way to verify that the columns requested exist before the - // query else we just get an error. If a new column is added or dropped on - // an OS could break existing queries. + // Every column name has already been validated against the allowlist + // of known Windows Search properties by the caller before reaching + // this point. std::string selectColumns; for (const auto& k : columns) { selectColumns += k + ","; @@ -310,7 +366,7 @@ std::string generateSqlFromUserQuery(const std::string& userInput, stringToWstring(selectColumns).c_str()); if (FAILED(hr)) { LOG(ERROR) << windowsSearchTableName << ": failed to set columns"; - return ""; + return Status::failure("failed to set columns"); } } @@ -318,7 +374,7 @@ std::string generateSqlFromUserQuery(const std::string& userInput, hr = pQueryHelper->put_QuerySorting(stringToWstring(sort).c_str()); if (FAILED(hr)) { LOG(ERROR) << windowsSearchTableName << ": failed to set sort"; - return ""; + return Status::failure("failed to set sort"); } } @@ -328,12 +384,12 @@ std::string generateSqlFromUserQuery(const std::string& userInput, if (FAILED(hr)) { LOG(ERROR) << windowsSearchTableName << ": failed to generate SQL from user query"; - return ""; + return Status::failure("failed to generate SQL from user query"); } - std::string ret = wstringToString(sql); + generatedSql = wstringToString(sql); CoTaskMemFree(sql); - return ret; + return Status::success(); } QueryData genWindowsSearch(QueryContext& context) { @@ -401,9 +457,26 @@ QueryData genWindowsSearch(QueryContext& context) { userInputAdditionalProperties = SQL_TEXT(*additionalPropertiesConstraint.begin()); - // include the user defined additional properties in all properties + // include the user defined additional properties in all properties, + // but only if they look like valid Windows Search property names. + // Anything that doesn't match is dropped rather than passed through + // to the query helper, to avoid injecting arbitrary SQL fragments. for (const auto& v : osquery::split(userInputAdditionalProperties, ",")) { - allProperties.insert(v); + bool valid = !v.empty(); + for (const auto& c : v) { + if (!(std::isalnum(static_cast(c)) || c == '.' || + c == '_')) { + valid = false; + break; + } + } + if (valid) { + allProperties.insert(v); + } else { + LOG(WARNING) << windowsSearchTableName + << ": ignoring invalid additional_properties entry: " + << v; + } } } @@ -411,6 +484,12 @@ QueryData genWindowsSearch(QueryContext& context) { if (context.hasConstraint("sort", EQUALS)) { auto sortConstraint = context.constraints["sort"].getAll(EQUALS); sort = SQL_TEXT(*sortConstraint.begin()); + + if (!sort.empty() && !isAllowedSearchSort(sort, allProperties)) { + LOG(ERROR) << windowsSearchTableName + << ": invalid sort expression, ignoring: " << sort; + sort = ""; + } } std::string query = "*"; @@ -419,8 +498,24 @@ QueryData genWindowsSearch(QueryContext& context) { query = SQL_TEXT(*queryContext.begin()); } - auto generatedQuery = - generateSqlFromUserQuery(query, allProperties, sort, maxResults); + // Only pass through select columns that are in the validated allowlist. + std::set selectColumns; + for (const auto& col : allProperties) { + if (isAllowedSearchColumn(col, allProperties)) { + selectColumns.insert(col); + } + } + + std::string generatedQuery; + auto status = generateSqlFromUserQuery( + query, selectColumns, sort, maxResults, generatedQuery); + if (!status.ok()) { + LOG(ERROR) << windowsSearchTableName + << ": failed to generate SQL from user query: " + << status.getMessage(); + return results; + } + auto queryResults = executeWindowsSearchQuery(cSession, generatedQuery); for (size_t i = 0; i < queryResults.size(); i++) { @@ -476,3 +571,4 @@ QueryData genWindowsSearch(QueryContext& context) { } // namespace tables } // namespace osquery + From aea9ef2995385ed5930c5c0932e43fef75c34502 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:34 +0000 Subject: [PATCH 09/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/system_utils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osquery/tables/system/system_utils.cpp b/osquery/tables/system/system_utils.cpp index 4f934caeb59..30b73b9d5c4 100644 --- a/osquery/tables/system/system_utils.cpp +++ b/osquery/tables/system/system_utils.cpp @@ -37,7 +37,7 @@ QueryData pidsFromContext(const QueryContext& context, bool all) { context.iteritems("pid", EQUALS, ([&procs](const std::string& expr) { auto proc = SQL::selectAllFrom( "processes", "pid", EQUALS, expr); - procs.insert(procs.end(), procs.begin(), procs.end()); + procs.insert(procs.end(), proc.begin(), proc.end()); })); } else if (!all) { procs = SQL::selectAllFrom( @@ -49,3 +49,4 @@ QueryData pidsFromContext(const QueryContext& context, bool all) { } } } + From 6e349b9f6cec9d4f5b8bb39c998f74c21547e6bb Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:35 +0000 Subject: [PATCH 10/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/linux/portage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osquery/tables/system/linux/portage.cpp b/osquery/tables/system/linux/portage.cpp index 82b753b862c..7e3c5f33c82 100644 --- a/osquery/tables/system/linux/portage.cpp +++ b/osquery/tables/system/linux/portage.cpp @@ -314,7 +314,7 @@ QueryData genPortageKeywordSummary(QueryContext& context) { readFile(kPortageMask, masked); readFile(kPortageUnMask, unmasked); - if (!keywords.empty() || !masked.empty() || unmasked.empty()) { + if (!keywords.empty() || !masked.empty() || !unmasked.empty()) { return parsePortageKeywordSummaryContent(keywords, masked, unmasked); } else { return {}; From acf06d86edd40a6bcb64ec843482f2b344c259d2 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:36 +0000 Subject: [PATCH 11/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/darwin/quicklook_cache.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osquery/tables/system/darwin/quicklook_cache.cpp b/osquery/tables/system/darwin/quicklook_cache.cpp index 2a8d23a071c..e6c4470907e 100644 --- a/osquery/tables/system/darwin/quicklook_cache.cpp +++ b/osquery/tables/system/darwin/quicklook_cache.cpp @@ -119,6 +119,12 @@ QueryData genQuicklookCache(QueryContext& context) { "thumbnails GROUP BY file_id) t WHERE t.file_id = rowid;"; sqlite3_stmt* stmt = nullptr; rc = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr); + if (rc != SQLITE_OK || stmt == nullptr) { + VLOG(1) << "Cannot prepare query against " << index << ": " << rc + << " " << getStringForSQLiteReturnCode(rc); + sqlite3_close(db); + continue; + } while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { Row r; genQuicklookRow(stmt, r); From dbd7f777d2118cd98e1dfe9c153bf6c7dd49c242 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:37 +0000 Subject: [PATCH 12/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/yara/yara_utils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osquery/tables/yara/yara_utils.cpp b/osquery/tables/yara/yara_utils.cpp index 3c935556c6c..a4a0c9ec655 100644 --- a/osquery/tables/yara/yara_utils.cpp +++ b/osquery/tables/yara/yara_utils.cpp @@ -195,7 +195,7 @@ YaraCompilerResult compileSingleFile(const std::string& file) { return YaraCompilerResult::success(tmp_rules); -} // namespace osquery +} /** * Compile yara rules from string and load it into rule pointer. @@ -472,3 +472,4 @@ Status YARAConfigParserPlugin::update(const std::string& source, /// Call the simple YARA ConfigParserPlugin "yara". REGISTER(YARAConfigParserPlugin, "config_parser", "yara"); } // namespace osquery + From 3a0a9968b33a4658f74585eaa2e82b89336df750 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:39 +0000 Subject: [PATCH 13/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/windows/dns_cache.cpp | 36 +++++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/osquery/tables/system/windows/dns_cache.cpp b/osquery/tables/system/windows/dns_cache.cpp index 311ed6b42a3..cf0ddaf69e5 100644 --- a/osquery/tables/system/windows/dns_cache.cpp +++ b/osquery/tables/system/windows/dns_cache.cpp @@ -133,25 +133,47 @@ std::string dnsTypeToString(unsigned short wType) { QueryData genDnsCache(QueryContext& context) { QueryData results; - PDNSCACHEENTRY pEntry = (PDNSCACHEENTRY)malloc(sizeof(DNSCACHEENTRY)); HINSTANCE hLib = LoadLibraryExW(L"DNSAPI.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (hLib == nullptr) { + LOG(WARNING) << "Failed to load DNSAPI.dll"; + return results; + } + DNS_GET_CACHE_DATA_TABLE DnsGetCacheDataTable = (DNS_GET_CACHE_DATA_TABLE)GetProcAddress(hLib, "DnsGetCacheDataTable"); + if (DnsGetCacheDataTable == nullptr) { + LOG(WARNING) << "Failed to resolve DnsGetCacheDataTable"; + FreeLibrary(hLib); + return results; + } + + PDNSCACHEENTRY pEntry = (PDNSCACHEENTRY)malloc(sizeof(DNSCACHEENTRY)); + if (pEntry == nullptr) { + FreeLibrary(hLib); + return results; + } int stat = DnsGetCacheDataTable(pEntry); - pEntry = pEntry->pNext; - while (pEntry != nullptr) { + if (stat == 0) { + free(pEntry); + FreeLibrary(hLib); + return results; + } + + PDNSCACHEENTRY pCurrent = pEntry->pNext; + while (pCurrent != nullptr) { Row r; - r["name"] = wstringToString(pEntry->pszName); - r["type"] = dnsTypeToString(pEntry->wType); - r["flags"] = INTEGER(pEntry->dwFlags); + r["name"] = wstringToString(pCurrent->pszName); + r["type"] = dnsTypeToString(pCurrent->wType); + r["flags"] = INTEGER(pCurrent->dwFlags); results.push_back(r); - pEntry = pEntry->pNext; + pCurrent = pCurrent->pNext; } free(pEntry); + FreeLibrary(hLib); return results; } From 3bda833c62161a493606d37fc8a49744884c35ec Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:41 +0000 Subject: [PATCH 14/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- .../tables/system/windows/scheduled_tasks.cpp | 59 ++++++++++++------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/osquery/tables/system/windows/scheduled_tasks.cpp b/osquery/tables/system/windows/scheduled_tasks.cpp index d17719ceacf..f2c535661d1 100644 --- a/osquery/tables/system/windows/scheduled_tasks.cpp +++ b/osquery/tables/system/windows/scheduled_tasks.cpp @@ -87,12 +87,15 @@ void enumerateTasksForFolder(std::string path, QueryData& results) { } Row r; - BSTR taskName; + BSTR taskName = nullptr; ret = pRegisteredTask->get_Name(&taskName); - std::wstring wTaskName(taskName, SysStringLen(taskName)); - ::SysFreeString(taskName); - r["name"] = - ret == S_OK ? SQL_TEXT(wstringToString(wTaskName)) : std::string(); + if (ret == S_OK && taskName != nullptr) { + std::wstring wTaskName(taskName, SysStringLen(taskName)); + ::SysFreeString(taskName); + r["name"] = SQL_TEXT(wstringToString(wTaskName)); + } else { + r["name"] = std::string(); + } VARIANT_BOOL enabled = false; pRegisteredTask->get_Enabled(&enabled); @@ -104,11 +107,15 @@ void enumerateTasksForFolder(std::string path, QueryData& results) { ? kStateMap.at(taskState) : kStateMap.at(TASK_STATE_UNKNOWN); - BSTR taskPath; + BSTR taskPath = nullptr; ret = pRegisteredTask->get_Path(&taskPath); - std::wstring wTaskPath(taskPath, SysStringLen(taskPath)); - r["path"] = ret == S_OK ? wstringToString(wTaskPath) : std::string(); - ::SysFreeString(taskPath); + if (ret == S_OK && taskPath != nullptr) { + std::wstring wTaskPath(taskPath, SysStringLen(taskPath)); + r["path"] = wstringToString(wTaskPath); + ::SysFreeString(taskPath); + } else { + r["path"] = std::string(); + } VARIANT_BOOL hidden = false; pRegisteredTask->get_Enabled(&hidden); @@ -168,20 +175,29 @@ void enumerateTasksForFolder(std::string path, QueryData& results) { continue; } - BSTR taskExecPath; - execAction->get_Path(&taskExecPath); - std::wstring wTaskExecPath(taskExecPath, SysStringLen(taskExecPath)); - ::SysFreeString(taskExecPath); + BSTR taskExecPath = nullptr; + auto execRet = execAction->get_Path(&taskExecPath); + std::wstring wTaskExecPath; + if (execRet == S_OK && taskExecPath != nullptr) { + wTaskExecPath.assign(taskExecPath, SysStringLen(taskExecPath)); + ::SysFreeString(taskExecPath); + } - BSTR taskExecArgs; - execAction->get_Arguments(&taskExecArgs); - std::wstring wTaskExecArgs(taskExecArgs, SysStringLen(taskExecArgs)); - ::SysFreeString(taskExecArgs); + BSTR taskExecArgs = nullptr; + execRet = execAction->get_Arguments(&taskExecArgs); + std::wstring wTaskExecArgs; + if (execRet == S_OK && taskExecArgs != nullptr) { + wTaskExecArgs.assign(taskExecArgs, SysStringLen(taskExecArgs)); + ::SysFreeString(taskExecArgs); + } - BSTR taskExecRoot; - execAction->get_WorkingDirectory(&taskExecRoot); - std::wstring wTaskExecRoot(taskExecRoot, SysStringLen(taskExecRoot)); - ::SysFreeString(taskExecRoot); + BSTR taskExecRoot = nullptr; + execRet = execAction->get_WorkingDirectory(&taskExecRoot); + std::wstring wTaskExecRoot; + if (execRet == S_OK && taskExecRoot != nullptr) { + wTaskExecRoot.assign(taskExecRoot, SysStringLen(taskExecRoot)); + ::SysFreeString(taskExecRoot); + } execAction->Release(); @@ -231,3 +247,4 @@ QueryData genScheduledTasks(QueryContext& context) { } } // namespace tables } // namespace osquery + From ce57cb1ddf1f518d4a4f22cc0e9dd1031e5b6801 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:43 +0000 Subject: [PATCH 15/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/utils/pidfile/pidfile_posix.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osquery/utils/pidfile/pidfile_posix.cpp b/osquery/utils/pidfile/pidfile_posix.cpp index 9ffc19142a0..998c28ee381 100644 --- a/osquery/utils/pidfile/pidfile_posix.cpp +++ b/osquery/utils/pidfile/pidfile_posix.cpp @@ -114,8 +114,6 @@ boost::optional Pidfile::writeFile( auto buffer_size = static_cast(buffer.size()); auto remaining_bytes = buffer_size; - buffer_size = remaining_bytes = {static_cast(buffer.size())}; - for (int retry = 0; retry < 5 && remaining_bytes > 0; ++retry) { auto buffer_ptr = buffer.data() + buffer_size - remaining_bytes; @@ -187,3 +185,4 @@ void Pidfile::destroyFile(FileHandle file_handle, } } // namespace osquery + From 1b6702aa25eca017cb0d7dd4d77926c2d4f8e2c2 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:45 +0000 Subject: [PATCH 16/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/events/darwin/fsevents.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/osquery/events/darwin/fsevents.cpp b/osquery/events/darwin/fsevents.cpp index 1b0ebe9c21b..9f06af78bf2 100644 --- a/osquery/events/darwin/fsevents.cpp +++ b/osquery/events/darwin/fsevents.cpp @@ -233,9 +233,6 @@ void FSEventsEventPublisher::configure() { paths_.clear(); for (auto& sub : subscriptions_) { auto sc = getSubscriptionContext(sub->context); - if (sc->discovered_.size() > 0) { - continue; - } auto paths = transformSubscription(sc); paths_.insert(paths.begin(), paths.end()); } From 0d19facae7c233fbd7a2126fb6b3c407c5aeadaa Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:46 +0000 Subject: [PATCH 17/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/events/linux/bpf/filesystem.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osquery/events/linux/bpf/filesystem.cpp b/osquery/events/linux/bpf/filesystem.cpp index dab3a77606f..08313f2a4b5 100644 --- a/osquery/events/linux/bpf/filesystem.cpp +++ b/osquery/events/linux/bpf/filesystem.cpp @@ -128,7 +128,14 @@ bool Filesystem::enumFiles(int dirfd, EnumFilesCallback callback) const { bool directory; if (entry->d_type == DT_DIR) { directory = true; - } else if (entry->d_type == DT_LNK || entry->d_type == DT_REG) { + } else if (entry->d_type == DT_LNK) { + struct stat file_stats {}; + if (fstatat(dirfd, string_fd, &file_stats, 0) != 0) { + continue; + } + + directory = S_ISDIR(file_stats.st_mode); + } else if (entry->d_type == DT_REG) { directory = false; } else { continue; @@ -171,3 +178,4 @@ Status IFilesystem::create(Ref& obj) { } } // namespace osquery + From 71d0ac0211190dfc0cd0e81bffac4738c6dabbb7 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:47 +0000 Subject: [PATCH 18/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/windows/registry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osquery/tables/system/windows/registry.cpp b/osquery/tables/system/windows/registry.cpp index 28dbbf31e34..f69241ebe58 100644 --- a/osquery/tables/system/windows/registry.cpp +++ b/osquery/tables/system/windows/registry.cpp @@ -471,7 +471,7 @@ static inline Status populateAllKeysRecursive( } auto size_pre = rKeys.size(); - auto ret = populateSubkeys(rKeys); + auto ret = populateSubkeys(rKeys, false); if (!ret.ok()) { return ret; } From 9b7f56d491e10bb743132f1362bb5249775ba905 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:48 +0000 Subject: [PATCH 19/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/filesystem/file_compression.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osquery/filesystem/file_compression.cpp b/osquery/filesystem/file_compression.cpp index 08a1f28976e..4ec27af0432 100644 --- a/osquery/filesystem/file_compression.cpp +++ b/osquery/filesystem/file_compression.cpp @@ -48,8 +48,8 @@ Status compress(const boost::filesystem::path& in, size_t const buffInSize = ZSTD_CStreamInSize(); size_t const buffOutSize = ZSTD_CStreamOutSize(); - std::vector buffIn(buffInSize); - std::vector buffOut(buffOutSize); + std::vector buffIn(buffInSize); + std::vector buffOut(buffOutSize); auto read = buffInSize; auto toRead = buffInSize; size_t readSoFar = 0; @@ -114,8 +114,8 @@ Status decompress(const boost::filesystem::path& in, auto inFileSize = inFile.size(); size_t const buffInSize = ZSTD_DStreamInSize(); size_t const buffOutSize = ZSTD_DStreamOutSize(); - std::vector buffIn(buffInSize); - std::vector buffOut(buffOutSize); + std::vector buffIn(buffInSize); + std::vector buffOut(buffOutSize); ZSTD_DStream* const dstream = ZSTD_createDStream(); if (dstream == NULL) { @@ -201,3 +201,4 @@ Status archive(const std::set& paths, return Status::success(); }; } // namespace osquery + From 86d626ad2ad332f5d3a52e8e7b7d06fa5917cc83 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:49 +0000 Subject: [PATCH 20/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/carver/carver.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osquery/carver/carver.cpp b/osquery/carver/carver.cpp index c6f751999d4..51af59f9839 100644 --- a/osquery/carver/carver.cpp +++ b/osquery/carver/carver.cpp @@ -280,6 +280,9 @@ Status Carver::blockwiseCopy(PlatformFile& src, PlatformFile& dst) { if (bytesWritten < 0) { return Status(1, "Error writing bytes to tmp fs"); } + if (bytesWritten < bytesRead) { + return Status(1, "Partial write to tmp fs: wrote fewer bytes than read"); + } } } @@ -334,6 +337,7 @@ Status Carver::postCarve(const boost::filesystem::path& path) { auto contUri = TLSRequestHelper::makeURI(FLAGS_carver_continue_endpoint); Request contRequest(contUri); contRequest.setOption("hostname", FLAGS_tls_hostname); + size_t failedBlocks = 0; for (size_t i = 0; i < blkCount; i++) { std::vector block(FLAGS_carver_block_size, 0); auto r = pFile.read(block.data(), FLAGS_carver_block_size); @@ -354,10 +358,18 @@ Status Carver::postCarve(const boost::filesystem::path& path) { if (!status.ok()) { VLOG(1) << "Post of carved block " << i << " failed: " << status.getMessage(); + failedBlocks++; continue; } } + if (failedBlocks > 0) { + updateCarveValue(carveGuid_, "status", "DATA POST FAILED"); + return Status(1, + "Failed to post " + std::to_string(failedBlocks) + " of " + + std::to_string(blkCount) + " carve blocks"); + } + updateCarveValue(carveGuid_, "status", kCarverStatusSuccess); return Status::success(); }; From bc08922809e83b529d6876974a12cc5b2419feff Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:50 +0000 Subject: [PATCH 21/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/database/ephemeral.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osquery/database/ephemeral.cpp b/osquery/database/ephemeral.cpp index 2edeb3b5d17..72d3fb0dd4b 100644 --- a/osquery/database/ephemeral.cpp +++ b/osquery/database/ephemeral.cpp @@ -154,7 +154,10 @@ Status EphemeralDatabasePlugin::putBatch(const std::string& domain, Status EphemeralDatabasePlugin::remove(const std::string& domain, const std::string& k) { - db_[domain].erase(k); + auto it = db_.find(domain); + if (it != db_.end()) { + it->second.erase(k); + } return Status(0); } @@ -165,8 +168,12 @@ Status EphemeralDatabasePlugin::removeRange(const std::string& domain, return Status::failure("Invalid range: low > high"); } + if (db_.count(domain) == 0) { + return Status(0); + } + std::vector keys; - for (const auto& it : db_[domain]) { + for (const auto& it : db_.at(domain)) { if (it.first >= low && it.first <= high) { keys.push_back(it.first); } From f53f4f6a4d949f7e723cf1734bd98234851a7a60 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:51 +0000 Subject: [PATCH 22/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/events/linux/inotify.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osquery/events/linux/inotify.cpp b/osquery/events/linux/inotify.cpp index 22ed7855843..669a29a00ac 100644 --- a/osquery/events/linux/inotify.cpp +++ b/osquery/events/linux/inotify.cpp @@ -67,6 +67,10 @@ Status INotifyEventPublisher::setUp() { } WriteLock lock(scratch_mutex_); + if (scratch_ != nullptr) { + free(scratch_); + scratch_ = nullptr; + } scratch_ = (char*)malloc(kINotifyBufferSize); if (scratch_ == nullptr) { return Status(1, "Could not allocate scratch space"); @@ -351,7 +355,8 @@ bool INotifyEventPublisher::shouldFire(const INotifySubscriptionContextRef& sc, // Need to have two finds, // what if somebody excluded an individual file inside a directory if (!exclude_paths_.empty() && - (exclude_paths_.find(path) || exclude_paths_.find(ec->path))) { + (exclude_paths_.find(path) != exclude_paths_.end() || + exclude_paths_.find(ec->path) != exclude_paths_.end())) { return false; } @@ -486,3 +491,4 @@ bool INotifyEventPublisher::isPathMonitored(const std::string& path) const { return (path_iterator != path_descriptors_.end()); } } + From 25ebcc7a05252a0dd0e30b88648ba92c71000573 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:52 +0000 Subject: [PATCH 23/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/tests/linux/md_tables_tests.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osquery/tables/system/tests/linux/md_tables_tests.cpp b/osquery/tables/system/tests/linux/md_tables_tests.cpp index d89cea06a38..46998c170a8 100644 --- a/osquery/tables/system/tests/linux/md_tables_tests.cpp +++ b/osquery/tables/system/tests/linux/md_tables_tests.cpp @@ -209,6 +209,8 @@ TEST_F(GetDrivesForArrayTest, all_drives_removed) { {"slot", "5"}, }, }; + + EXPECT_EQ(got, expected); }; TEST_F(GetDrivesForArrayTest, all_drives_faulty) { @@ -1150,3 +1152,4 @@ TEST_F(ParseMDStatTest, negative_test_unexpected_texts_in_substr_receivers) { } // namespace tables } // namespace osquery + From 8522cba2e5bc833bcd5ddfac70eb3f42b3507da7 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:53 +0000 Subject: [PATCH 24/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/tests/linux/rpm_packages_tests.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osquery/tables/system/tests/linux/rpm_packages_tests.cpp b/osquery/tables/system/tests/linux/rpm_packages_tests.cpp index 20d6332a1cf..ac30cf93726 100644 --- a/osquery/tables/system/tests/linux/rpm_packages_tests.cpp +++ b/osquery/tables/system/tests/linux/rpm_packages_tests.cpp @@ -96,7 +96,7 @@ Status queryRpmDb(packageCallback predicate) { rpmInitCrypto(); if (rpmReadConfigFiles(nullptr, nullptr) != 0) { rpmFreeCrypto(); - Status::failure("Cannot read configuration"); + return Status::failure("Cannot read configuration"); } rpmts ts = rpmtsCreate(); @@ -223,3 +223,4 @@ TEST_F(RpmTests, test_ndb_packages) { } // namespace tables } // namespace osquery + From 69248d175393948116963175d408983fadf32a12 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:54 +0000 Subject: [PATCH 25/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/events/windows/etw/etw_provider_config.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osquery/events/windows/etw/etw_provider_config.cpp b/osquery/events/windows/etw/etw_provider_config.cpp index 1cd5b597e5a..5e2805fe582 100644 --- a/osquery/events/windows/etw/etw_provider_config.cpp +++ b/osquery/events/windows/etw/etw_provider_config.cpp @@ -26,8 +26,8 @@ Status EtwProviderConfig::isValid() const { return Status::failure("Type handlers were not provided"); } - if (getPostProcessor() == nullptr) { - return Status::failure("Invalid Provider PostProcessor function"); + if (getPreProcessor() == nullptr) { + return Status::failure("Invalid Provider PreProcessor function"); } return Status::success(); @@ -166,4 +166,4 @@ void EtwProviderConfig::addEventTypeToHandle(const EtwEventType& value) { eventTypes_.push_back(value); } -} // namespace osquery \ No newline at end of file +} // namespace osquery From 978ead655824b22fa6b34334c763ff493efa1cea Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:55 +0000 Subject: [PATCH 26/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/windows/windows_optional_features.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osquery/tables/system/windows/windows_optional_features.cpp b/osquery/tables/system/windows/windows_optional_features.cpp index 661050b691a..e933abdca60 100644 --- a/osquery/tables/system/windows/windows_optional_features.cpp +++ b/osquery/tables/system/windows/windows_optional_features.cpp @@ -41,7 +41,7 @@ QueryData genWinOptionalFeatures(QueryContext& context) { for (const auto& wmiObj : wmiResults) { Row r; - uint32_t state; + uint32_t state = 0; wmiObj.GetString("Name", r["name"]); wmiObj.GetString("Caption", r["caption"]); @@ -84,3 +84,4 @@ std::string getDismPackageFeatureStateName(uint32_t state) { } // namespace tables } // namespace osquery + From 848375b072bf0cc22591f2802b6c56ea97e07fc9 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:56 +0000 Subject: [PATCH 27/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/posix/system_controls.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osquery/tables/system/posix/system_controls.cpp b/osquery/tables/system/posix/system_controls.cpp index a6b64dc171d..86898af826d 100644 --- a/osquery/tables/system/posix/system_controls.cpp +++ b/osquery/tables/system/posix/system_controls.cpp @@ -64,7 +64,7 @@ void genControlConfigFromPath(const std::string& path, for (auto& line : osquery::split(content, "\n")) { boost::trim(line); - if (line[0] == '#' || line[0] == ';') { + if (line.empty() || line[0] == '#' || line[0] == ';') { continue; } @@ -123,3 +123,4 @@ QueryData genSystemControls(QueryContext& context) { } } } + From 5c01a16c2beee6754114f9a5b8d87f120ce4f55e Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:57 +0000 Subject: [PATCH 28/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/windows/intel_me.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osquery/tables/system/windows/intel_me.cpp b/osquery/tables/system/windows/intel_me.cpp index ed2fa772ee8..2d5b6bd1121 100644 --- a/osquery/tables/system/windows/intel_me.cpp +++ b/osquery/tables/system/windows/intel_me.cpp @@ -271,7 +271,7 @@ osquery::Status getDeviceInformationSet(DeviceInformationSet& dev_info_set, const GUID* guid_filter) { dev_info_set.reset(); - auto filter = const_cast(&HECI_INTERFACE_GUID); + auto filter = const_cast(guid_filter); HDEVINFO handle = SetupDiGetClassDevs( filter, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); From 3c3605b115a55532e4fa2587078bd12f683ee409 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:58 +0000 Subject: [PATCH 29/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/windows/groups.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osquery/tables/system/windows/groups.cpp b/osquery/tables/system/windows/groups.cpp index 46fdf282655..e9267bd3415 100644 --- a/osquery/tables/system/windows/groups.cpp +++ b/osquery/tables/system/windows/groups.cpp @@ -65,7 +65,6 @@ QueryData genGroups(QueryContext& context) { } } else if (!selected_gids.empty()) { - auto selected_gids = gid_it->second.getAll(EQUALS); for (const auto& selected_gid_str : selected_gids) { auto selected_gid_res = tryTo(selected_gid_str); @@ -94,3 +93,4 @@ QueryData genGroups(QueryContext& context) { } } // namespace tables } // namespace osquery + From c40530d7332e50defb0da8ce16fd5a3ad49e5855 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:21:59 +0000 Subject: [PATCH 30/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- tools/codegen/genapi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/codegen/genapi.py b/tools/codegen/genapi.py index a07b271d79d..0aca7ce1375 100755 --- a/tools/codegen/genapi.py +++ b/tools/codegen/genapi.py @@ -279,7 +279,7 @@ def main(argc, argv): cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) out, err = proc.communicate() - output_file = out.split("\n")[0] + ".json" + output_file = out.decode('utf-8').split("\n")[0] + ".json" if args.directory[-1:] == '/': output_path = args.directory + output_file else: From 7b85e94b5ed6df49f4633c27139b804e129673ab Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:22:00 +0000 Subject: [PATCH 31/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/darwin/keychain_utils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osquery/tables/system/darwin/keychain_utils.cpp b/osquery/tables/system/darwin/keychain_utils.cpp index f92dc4ad31f..a652a82c740 100644 --- a/osquery/tables/system/darwin/keychain_utils.cpp +++ b/osquery/tables/system/darwin/keychain_utils.cpp @@ -80,7 +80,7 @@ std::string getKeychainPath(const SecKeychainItemRef& item) { char keychain_path[1024] = {0}; OSQUERY_USE_DEPRECATED( status = SecKeychainGetPath(keychain, &path_size, keychain_path)); - if (status != errSecSuccess || (path_size > 0 && keychain_path[0] != 0)) { + if (status == errSecSuccess && path_size > 0 && keychain_path[0] != 0) { path = std::string(keychain_path); } @@ -196,3 +196,4 @@ void KeychainCache::Write(const boost::filesystem::path& path, } // namespace tables } // namespace osquery + From b392e9e39da7f6a35031dba349a3988f47446ea0 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:22:01 +0000 Subject: [PATCH 32/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/windows/cpu_info.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osquery/tables/system/windows/cpu_info.cpp b/osquery/tables/system/windows/cpu_info.cpp index 819a1637923..d7773eec7b3 100644 --- a/osquery/tables/system/windows/cpu_info.cpp +++ b/osquery/tables/system/windows/cpu_info.cpp @@ -19,7 +19,6 @@ namespace osquery { namespace tables { QueryData genCpuInfo(QueryContext& context) { - Row r; QueryData results; const Expected wmiSystemReq = @@ -30,6 +29,7 @@ QueryData genCpuInfo(QueryContext& context) { } const std::vector& wmiResults = wmiSystemReq->results(); for (const auto& data : wmiResults) { + Row r; long number = 0; data.GetString("DeviceID", r["device_id"]); data.GetString("SocketDesignation", r["socket_designation"]); @@ -67,3 +67,4 @@ QueryData genCpuInfo(QueryContext& context) { } } // namespace tables } // namespace osquery + From ecc4de070d5480517851bce9f702d713da0ca10a Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:22:02 +0000 Subject: [PATCH 33/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/windows/prefetch.cpp | 27 ++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/osquery/tables/system/windows/prefetch.cpp b/osquery/tables/system/windows/prefetch.cpp index 9f92f3fe9c3..62f96cb90bd 100644 --- a/osquery/tables/system/windows/prefetch.cpp +++ b/osquery/tables/system/windows/prefetch.cpp @@ -188,15 +188,17 @@ PrefetchFileInfo parseFileInfo( // Size is given in bytes. const auto size = prefetch_file_info->FileNameStringsSize; const auto offset = prefetch_file_info->FileNameStringsOffset; - if (offset > data.size()) { - // Unexpected offset. + if (offset > data.size() || size > data.size() || + static_cast(offset) + static_cast(size) > + data.size()) { + // Unexpected offset or size. return result; } size_t total_length{0}; std::vector filenames; auto next = (PWCHAR)(&data[0] + offset); - while (*next != L'\0') { + while (total_length < size && *next != L'\0') { auto length = wcsnlen_s(next, (size - total_length) / sizeof(WCHAR)); if (length == 0 || length == (size - total_length) / sizeof(WCHAR)) { // A null wide character was not found. @@ -229,8 +231,11 @@ PrefetchVolumeInfo parseVolumeInfo( const auto volume_offset = prefetch_file_info->VolumeInformationOffset; // Size is given in bytes. const auto volume_size = prefetch_file_info->VolumesInformationSize; - if (volume_offset > data.size()) { - // Unexpected offset. + if (volume_offset > data.size() || volume_size > data.size() || + static_cast(volume_offset) + + static_cast(volume_size) > + data.size()) { + // Unexpected offset or size. return result; } @@ -262,8 +267,9 @@ PrefetchVolumeInfo parseVolumeInfo( } for (size_t j = 0; j < dir_count; j++) { - if (volume_offset + dir_offset + sizeof(PDIRECTORY_STRING) > - data.size()) { + if (dir_offset >= volume_size || + volume_offset + dir_offset + sizeof(PDIRECTORY_STRING) > + data.size()) { // Unexpected offset. break; } @@ -272,6 +278,12 @@ PrefetchVolumeInfo parseVolumeInfo( (PDIRECTORY_STRING)(&data[0] + volume_offset + dir_offset); dir_offset += sizeof(DIRECTORY_STRING); + if (dir_offset >= volume_size || + volume_offset + dir_offset > data.size()) { + // Not enough remaining space for a directory string. + break; + } + auto length = wcsnlen_s(prefetch_directory->Directory, (volume_size - dir_offset) / sizeof(WCHAR)); if (length == 0 || length == (volume_size - dir_offset) / sizeof(WCHAR)) { @@ -414,3 +426,4 @@ void genPrefetch(RowYield& yield, QueryContext& context) { } } // namespace tables } // namespace osquery + From c2e2e84f6d1c78bd3a40b8e348a59d83564e1d1d Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:22:03 +0000 Subject: [PATCH 34/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/events/events.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osquery/events/events.cpp b/osquery/events/events.cpp index b43742d4fce..6e1a551d181 100644 --- a/osquery/events/events.cpp +++ b/osquery/events/events.cpp @@ -40,7 +40,9 @@ bool enforceEventsDenylist(const std::string& query) { // Check if the query only operates on event subscribers. // If it does, skip the denylist enforcement. std::set table_set(tables.begin(), tables.end()); - auto event_tables = EventFactory::subscriberNames(); + auto subscriber_names = EventFactory::subscriberNames(); + std::set event_tables(subscriber_names.begin(), + subscriber_names.end()); std::set overlap; std::set_intersection(table_set.begin(), From 4fabffdc4f66ee44d04ddb1cc811956edcca9819 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:22:04 +0000 Subject: [PATCH 35/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/sql/dynamic_table_row.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/osquery/sql/dynamic_table_row.cpp b/osquery/sql/dynamic_table_row.cpp index cbb1c89a7da..f8ff6cb19bc 100644 --- a/osquery/sql/dynamic_table_row.cpp +++ b/osquery/sql/dynamic_table_row.cpp @@ -101,20 +101,22 @@ int DynamicTableRow::get_column(sqlite3_context* ctx, } // Attempt to cast each xFilter-populated row/column to the SQLite type. - const auto& value = row[column_name]; - if (this->row.count(column_name) == 0) { + auto row_it = this->row.find(column_name); + if (row_it == this->row.end()) { // Missing content. VLOG(1) << "Error " << column_name << " is empty"; sqlite3_result_null(ctx); - } else if (type == TEXT_TYPE || type == BLOB_TYPE) { + } else if (const auto& value = row_it->second; + type == TEXT_TYPE || type == BLOB_TYPE) { sqlite3_result_text( ctx, value.c_str(), static_cast(value.size()), SQLITE_TRANSIENT); - } else if (value.empty() && + } else if (const auto& value = row_it->second; + value.empty() && (type == INTEGER_TYPE || type == BIGINT_TYPE || type == UNSIGNED_BIGINT_TYPE || type == DOUBLE_TYPE)) { // Don't Log a casting error for a known type if the column row is empty sqlite3_result_null(ctx); - } else if (type == INTEGER_TYPE) { + } else if (const auto& value = row_it->second; type == INTEGER_TYPE) { auto afinite = tryTo(value, 0); if (afinite.isError()) { VLOG(1) << "Error casting " << column_name << " (" << value @@ -123,7 +125,8 @@ int DynamicTableRow::get_column(sqlite3_context* ctx, } else { sqlite3_result_int(ctx, afinite.take()); } - } else if (type == BIGINT_TYPE || type == UNSIGNED_BIGINT_TYPE) { + } else if (const auto& value = row_it->second; + type == BIGINT_TYPE || type == UNSIGNED_BIGINT_TYPE) { auto afinite = tryTo(value, 0); if (afinite.isError()) { VLOG(1) << "Error casting " << column_name << " (" << value @@ -132,7 +135,7 @@ int DynamicTableRow::get_column(sqlite3_context* ctx, } else { sqlite3_result_int64(ctx, afinite.take()); } - } else if (type == DOUBLE_TYPE) { + } else if (const auto& value = row_it->second; type == DOUBLE_TYPE) { char* end = nullptr; double afinite = strtod(value.c_str(), &end); if (end == nullptr || end == value.c_str() || *end != '\0') { @@ -163,3 +166,4 @@ TableRowHolder DynamicTableRow::clone() const { } } // namespace osquery + From 69950af544bd749498f51dc94ebed98fcd051baf Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:22:05 +0000 Subject: [PATCH 36/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/windows/wmi_bios_info.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osquery/tables/system/windows/wmi_bios_info.cpp b/osquery/tables/system/windows/wmi_bios_info.cpp index 36be4f34d22..102dacf751a 100644 --- a/osquery/tables/system/windows/wmi_bios_info.cpp +++ b/osquery/tables/system/windows/wmi_bios_info.cpp @@ -126,8 +126,10 @@ Row getDellLegacyBiosInfo(const WmiResultItem& item) { if (vCurrentValue.size() == 1 && !vPossibleValues.empty()) { auto pos = std::find( vPossibleValues.begin(), vPossibleValues.end(), vCurrentValue[0]); - if (pos != vPossibleValues.end()) { - r["value"] = vPossibleValuesDescription[pos - vPossibleValues.begin()]; + auto index = pos - vPossibleValues.begin(); + if (pos != vPossibleValues.end() && + static_cast(index) < vPossibleValuesDescription.size()) { + r["value"] = vPossibleValuesDescription[index]; } else { r["value"] = "N/A"; } @@ -466,3 +468,4 @@ QueryData genBiosInfo(QueryContext& context) { } } // namespace tables } // namespace osquery + From acc7f4ee6cf10f1ca97b56743830f5100d6e0bfd Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:22:06 +0000 Subject: [PATCH 37/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/events/windows/etw/etw_kernel_session.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osquery/events/windows/etw/etw_kernel_session.cpp b/osquery/events/windows/etw/etw_kernel_session.cpp index a726a2824d1..248a07b987d 100644 --- a/osquery/events/windows/etw/etw_kernel_session.cpp +++ b/osquery/events/windows/etw/etw_kernel_session.cpp @@ -136,7 +136,9 @@ void KernelEtwSessionRunnable::start() { std::unique_lock lock(mutex_); if (kernelTraceSession_) { while (!endTraceSession_) { + lock.unlock(); kernelTraceSession_->start(); + lock.lock(); traceSessionStopped_ = true; if (!endTraceSession_) { @@ -156,8 +158,11 @@ void KernelEtwSessionRunnable::stop() { void KernelEtwSessionRunnable::pause() { if (kernelTraceSession_) { kernelTraceSession_->stop(); + std::unique_lock lock(mutex_); while (!traceSessionStopped_) { + lock.unlock(); Sleep(500); + lock.lock(); } traceSessionStopped_ = false; } @@ -165,6 +170,7 @@ void KernelEtwSessionRunnable::pause() { void KernelEtwSessionRunnable::resume() { if (kernelTraceSession_) { + std::unique_lock lock(mutex_); condition_.notify_one(); } } From 2ecfaf0fc09675bff6eaf9da7910987e981d863a Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:22:07 +0000 Subject: [PATCH 38/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/tables/system/windows/programs.cpp | 154 +++++++++++++-------- 1 file changed, 97 insertions(+), 57 deletions(-) diff --git a/osquery/tables/system/windows/programs.cpp b/osquery/tables/system/windows/programs.cpp index d25cc2bc8fe..7a7e52bdd9b 100644 --- a/osquery/tables/system/windows/programs.cpp +++ b/osquery/tables/system/windows/programs.cpp @@ -9,6 +9,9 @@ #include +#include +#include + #include #include #include @@ -19,53 +22,69 @@ namespace osquery { namespace tables { -// Function to extract attributes from a tag -std::map parseAttributes( - const std::string& tagContent) { - std::regex attributeRegex("((\\w+)=\"([^\"]*)\")"); - std::smatch match; +namespace { + +// Function to extract attributes from an xmlNode +std::map parseAttributes(xmlNodePtr node) { std::map attributes; + if (node == nullptr) { + return attributes; + } - std::string::const_iterator searchStart(tagContent.cbegin()); - while (std::regex_search( - searchStart, tagContent.cend(), match, attributeRegex)) { - // match[1] is the entire attribute="value" string - // match[2] is the attribute name - // match[3] is the attribute value - attributes[match[2]] = match[3]; - searchStart = match.suffix().first; + for (xmlAttrPtr attr = node->properties; attr != nullptr; + attr = attr->next) { + if (attr->name == nullptr) { + continue; + } + xmlChar* value = xmlNodeListGetString(node->doc, attr->children, 1); + if (value != nullptr) { + attributes[reinterpret_cast(attr->name)] = + reinterpret_cast(value); + xmlFree(value); + } } return attributes; } -// Function to extract the contents of a specific tag -std::string getTagContent(const std::string& xml, const std::string& tagName) { - std::regex tagRegex("<" + tagName + "[\\s\\S]*?>([\\s\\S]*?)<\\/" + tagName + - ">"); - std::smatch match; - - if (std::regex_search(xml, match, tagRegex)) { - // match[0] is the entire tag with contents contents - // match[1] is the contents of the tag - return match[1]; +// Recursively find the first descendant (including self) node with the +// given tag name, honoring XML namespaces by comparing local names only. +xmlNodePtr findNode(xmlNodePtr node, const std::string& tagName) { + for (xmlNodePtr cur = node; cur != nullptr; cur = cur->next) { + if (cur->type == XML_ELEMENT_NODE && cur->name != nullptr && + tagName == reinterpret_cast(cur->name)) { + return cur; + } + if (cur->children != nullptr) { + xmlNodePtr found = findNode(cur->children, tagName); + if (found != nullptr) { + return found; + } + } } - return ""; + return nullptr; } -// Function to find self closing tag in xml -std::string findSelfClosingTag(const std::string& xml, - const std::string& tagName) { - std::regex tagRegex("<" + tagName + "[\\s\\S]*?/>"); - std::smatch match; +// Get the text content of the first descendant node found with the given +// tag name, searching from the given root node. +std::string getTagContent(xmlNodePtr root, const std::string& tagName) { + xmlNodePtr node = findNode(root, tagName); + if (node == nullptr) { + return ""; + } - if (std::regex_search(xml, match, tagRegex)) { - // match[0] is the entire self-closing tag - return match[0]; + xmlChar* content = xmlNodeGetContent(node); + if (content == nullptr) { + return ""; } - return ""; + + std::string result(reinterpret_cast(content)); + xmlFree(content); + return result; } +} // namespace + // Convert a Unix timestamp to a date in YYYYMMDD format std::string formatTimestampToDate(time_t timestamp) { try { @@ -366,36 +385,57 @@ void genMsixPrograms(const std::string& key, continue; } - // Find the Identity tag, extract attributes - std::string identityTag = findSelfClosingTag(xmlContent, "Identity"); - if (!identityTag.empty()) { - auto attributes = parseAttributes(identityTag); - result["name"] = attributes["Name"]; - result["publisher"] = attributes["Publisher"]; - result["version"] = attributes["Version"]; + // Parse the manifest using a real XML parser rather than + // regex splicing, since AppxManifest.xml is untrusted, + // package-supplied data. + xmlDocPtr doc = xmlReadMemory(xmlContent.c_str(), + static_cast(xmlContent.size()), + "AppxManifest.xml", + nullptr, + XML_PARSE_NOENT | XML_PARSE_NONET); + if (doc == nullptr) { + VLOG(1) << "Failed to parse manifest file:'" + filePath + "'"; + result.clear(); + continue; } - // Find the Properties tag, extract child tags - std::string propertiesTag = getTagContent(xmlContent, "Properties"); - if (!propertiesTag.empty()) { - auto displayName = getTagContent(propertiesTag, "DisplayName"); - auto publisherDisplayName = - getTagContent(propertiesTag, "PublisherDisplayName"); - - // "ms-resource:" prefix means that the string is dynamically - // generated from a .pri file .pri file is a binary index of all - // localized and scaled resources compiled from .resw files or - // .resources at build time - if (!displayName.empty() && - displayName.find("ms-resource") == std::string::npos) { - result["name"] = displayName; + xmlNodePtr root = xmlDocGetRootElement(doc); + if (root != nullptr) { + // Find the Identity tag, extract attributes + xmlNodePtr identityNode = findNode(root, "Identity"); + if (identityNode != nullptr) { + auto attributes = parseAttributes(identityNode); + result["name"] = attributes["Name"]; + result["publisher"] = attributes["Publisher"]; + result["version"] = attributes["Version"]; } - if (!publisherDisplayName.empty() && - publisherDisplayName.find("ms-resource") == std::string::npos) { - result["publisher"] = publisherDisplayName; + + // Find the Properties tag, extract child tags + xmlNodePtr propertiesNode = findNode(root, "Properties"); + if (propertiesNode != nullptr) { + auto displayName = + getTagContent(propertiesNode->children, "DisplayName"); + auto publisherDisplayName = getTagContent( + propertiesNode->children, "PublisherDisplayName"); + + // "ms-resource:" prefix means that the string is dynamically + // generated from a .pri file .pri file is a binary index of all + // localized and scaled resources compiled from .resw files or + // .resources at build time + if (!displayName.empty() && + displayName.find("ms-resource") == std::string::npos) { + result["name"] = displayName; + } + if (!publisherDisplayName.empty() && + publisherDisplayName.find("ms-resource") == + std::string::npos) { + result["publisher"] = publisherDisplayName; + } } } + xmlFreeDoc(doc); + // Done processing this package registry entries // No need to read anymore keys continue; From 1993e7602a7b3cc32c5f1b7d610518abfa3d6cf3 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:22:08 +0000 Subject: [PATCH 39/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/utils/pidfile/pidfile_windows.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osquery/utils/pidfile/pidfile_windows.cpp b/osquery/utils/pidfile/pidfile_windows.cpp index 015d05c4def..da7f05ba3c0 100644 --- a/osquery/utils/pidfile/pidfile_windows.cpp +++ b/osquery/utils/pidfile/pidfile_windows.cpp @@ -97,6 +97,7 @@ Expected Pidfile::lockFile( FILE_FLAG_DELETE_ON_CLOSE); if (new_handle == INVALID_HANDLE_VALUE) { + CloseHandle(toNativeHandle(file_handle)); return createError(Error::Busy); } @@ -173,3 +174,4 @@ void Pidfile::destroyFile(FileHandle file_handle, const std::string&) noexcept { } } // namespace osquery + From 4fc2d5dcc4d56a03d2763b3c28bbedcb35347705 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:22:09 +0000 Subject: [PATCH 40/40] fix(adhoc-sweep-fixes): 56 review findings across 40 files --- osquery/worker/ipc/linux/linux_table_container_ipc.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osquery/worker/ipc/linux/linux_table_container_ipc.cpp b/osquery/worker/ipc/linux/linux_table_container_ipc.cpp index 2d1b269fb58..166dd074805 100644 --- a/osquery/worker/ipc/linux/linux_table_container_ipc.cpp +++ b/osquery/worker/ipc/linux/linux_table_container_ipc.cpp @@ -137,7 +137,9 @@ LinuxTableContainerIPC::LinuxTableContainerIPC(PipeChannelFactory& factory) : ipc_(factory, *this) {} LinuxTableContainerIPC::~LinuxTableContainerIPC() { - close(original_mnt_fd_); + if (original_mnt_fd_ > 0) { + close(original_mnt_fd_); + } } Status LinuxTableContainerIPC::connectToContainer(