-
Notifications
You must be signed in to change notification settings - Fork 0
fix(OSQUERY-002-2): 22 review findings across 13 files #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
e50e090
426054e
5229c87
1f746d4
49df5b1
4ee6514
12d45bb
9a84eab
e3b4487
b7bc1ef
915300d
f800510
a6a8b37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -300,7 +300,7 @@ Status getDatabaseValue(const std::string& domain, | |
|
|
||
| ReadLock lock(kDatabaseReset); | ||
| if (!kDBInitialized) { | ||
| throw std::runtime_error("Cannot get database value: " + key); | ||
| return Status::failure("Cannot get database value: " + key); | ||
| } else { | ||
| auto plugin = getDatabasePlugin(); | ||
| return plugin->get(domain, key, value); | ||
|
Comment on lines
300
to
306
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ getDatabaseValue/setDatabaseValue/deleteDatabaseValue throw std::runtime_error instead of returning Status when DB not initialized In (Automatically downgraded: no change in this fix lands near this finding's line β verify whether it was actually addressed.) π€ Prompt for AI agentsfix confidence: π΄ 40 low β review closely β react π/π to teach the reviewer
Comment on lines
300
to
306
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ getDatabaseValue(int&) calls std::stoi without validating or catching exceptions In π€ Prompt for AI agentsfix confidence: π‘ 75 medium β react π/π to teach the reviewer |
||
|
|
@@ -313,7 +313,11 @@ Status getDatabaseValue(const std::string& domain, | |
| std::string result; | ||
| auto s = getDatabaseValue(domain, key, result); | ||
| if (s.ok()) { | ||
| value = std::stoi(result); | ||
| auto ret = tryTo<int>(result); | ||
| if (ret.isError()) { | ||
| return Status::failure("Invalid integer value for key: " + key); | ||
| } | ||
| value = ret.get(); | ||
| } | ||
| return s; | ||
| } | ||
|
Comment on lines
313
to
323
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ setDatabaseBatch throws std::runtime_error instead of returning a failure Status In π€ Prompt for AI agentsfix confidence: π’ 90 high β react π/π to teach the reviewer |
||
|
|
@@ -342,7 +346,7 @@ Status setDatabaseBatch(const std::string& domain, | |
|
|
||
| ReadLock lock(kDatabaseReset); | ||
| if (!kDBInitialized) { | ||
| throw std::runtime_error("Cannot set database values"); | ||
| return Status::failure("Cannot set database values"); | ||
| } | ||
|
|
||
| auto plugin = getDatabasePlugin(); | ||
|
Comment on lines
346
to
352
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ deleteDatabaseValue throws std::runtime_error instead of returning a failure Status In π€ Prompt for AI agentsfix confidence: π’ 90 high β react π/π to teach the reviewer |
||
|
|
@@ -370,7 +374,7 @@ Status deleteDatabaseValue(const std::string& domain, const std::string& key) { | |
|
|
||
| ReadLock lock(kDatabaseReset); | ||
| if (!kDBInitialized) { | ||
| throw std::runtime_error("Cannot delete database value: " + key); | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ deleteDatabaseRange throws std::runtime_error instead of returning a failure Status In π€ Prompt for AI agentsfix confidence: π’ 90 high β react π/π to teach the reviewer |
||
| return Status::failure("Cannot delete database value: " + key); | ||
| } else { | ||
| auto plugin = getDatabasePlugin(); | ||
| return plugin->remove(domain, key); | ||
|
|
@@ -396,8 +400,8 @@ Status deleteDatabaseRange(const std::string& domain, | |
|
|
||
| ReadLock lock(kDatabaseReset); | ||
| if (!kDBInitialized) { | ||
| throw std::runtime_error("Cannot delete database values: " + low + " - " + | ||
| high); | ||
| return Status::failure("Cannot delete database values: " + low + " - " + | ||
| high); | ||
| } else { | ||
| auto plugin = getDatabasePlugin(); | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ scanDatabaseKeys throws std::runtime_error instead of returning a failure Status In π€ Prompt for AI agentsfix confidence: π’ 90 high β react π/π to teach the reviewer |
||
| return plugin->removeRange(domain, low, high); | ||
|
|
@@ -439,7 +443,7 @@ Status scanDatabaseKeys(const std::string& domain, | |
|
|
||
| ReadLock lock(kDatabaseReset); | ||
| if (!kDBInitialized) { | ||
| throw std::runtime_error("Cannot scan database values: " + prefix); | ||
| return Status::failure("Cannot scan database values: " + prefix); | ||
| } else { | ||
| auto plugin = getDatabasePlugin(); | ||
| return plugin->scan(domain, keys, prefix, max); | ||
|
|
@@ -751,3 +755,4 @@ IDatabaseInterface& getOsqueryDatabase() { | |
| return osquery_database; | ||
| } | ||
| } // namespace osquery | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,7 +42,8 @@ SystemStateTracker::Ref SystemStateTracker::create() { | |
| IProcessContextFactory::Ref process_context_factory; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ SystemStateTracker::create() throws Status instead of returning it In π€ Prompt for AI agentsfix confidence: π‘ 80 medium β react π/π to teach the reviewer |
||
| auto status = IProcessContextFactory::create(process_context_factory); | ||
| if (!status) { | ||
| throw status; | ||
| LOG(ERROR) << "Failed to create the state tracker: " << status.getMessage(); | ||
| return nullptr; | ||
| } | ||
|
|
||
| return create(std::move(process_context_factory)); | ||
|
|
@@ -51,12 +52,16 @@ SystemStateTracker::Ref SystemStateTracker::create() { | |
| SystemStateTracker::Ref SystemStateTracker::create( | ||
| IProcessContextFactory::Ref process_context_factory) { | ||
| try { | ||
| return SystemStateTracker::Ref( | ||
| std::unique_ptr<SystemStateTracker> tracker( | ||
| new SystemStateTracker(std::move(process_context_factory))); | ||
|
|
||
| } catch (const Status& status) { | ||
| LOG(ERROR) << "Failed to create the state tracker: " << status.getMessage(); | ||
| return nullptr; | ||
| auto status = tracker->restart(); | ||
| if (!status.ok()) { | ||
| LOG(ERROR) << "Failed to create the state tracker: " << status.getMessage(); | ||
| return nullptr; | ||
| } | ||
|
|
||
| return SystemStateTracker::Ref(tracker.release()); | ||
|
|
||
| } catch (const std::bad_alloc&) { | ||
| return nullptr; | ||
|
|
@@ -271,11 +276,6 @@ SystemStateTracker::SystemStateTracker( | |
| : d(new PrivateData) { | ||
| d->last_expiration = getUnixTime(); | ||
| d->process_context_factory = std::move(process_context_factory); | ||
|
|
||
| auto status = restart(); | ||
| if (!status.ok()) { | ||
| throw status; | ||
| } | ||
| } | ||
|
|
||
| ProcessContext& SystemStateTracker::getProcessContext( | ||
|
Comment on lines
276
to
281
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ SystemStateTracker private constructor throws Status on restart failure Removed the π€ Prompt for AI agentsfix confidence: π‘ 70 medium β react π/π to teach the reviewer |
||
|
|
@@ -1357,3 +1357,4 @@ SystemStateTracker::Context SystemStateTracker::getContextCopy() const { | |
| } | ||
|
|
||
| } // namespace osquery | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,14 +54,18 @@ Status EvtSubscription::create(EvtSubscription::Ref& obj, | |
| obj.reset(); | ||
|
|
||
| try { | ||
| obj.reset(new EvtSubscription(channel)); | ||
| auto obj_ptr = std::unique_ptr<EvtSubscription>(new EvtSubscription(channel)); | ||
|
|
||
| auto status = obj_ptr->init(); | ||
| if (!status.ok()) { | ||
| return status; | ||
| } | ||
|
|
||
| obj = std::move(obj_ptr); | ||
| return Status::success(); | ||
|
|
||
| } catch (const std::bad_alloc&) { | ||
| return Status::failure("Memory allocation failure"); | ||
|
|
||
| } catch (const Status& status) { | ||
| return status; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -96,7 +100,10 @@ EvtSubscription::EventList EvtSubscription::getEvents() { | |
| EvtSubscription::EvtSubscription(const std::string& channel) | ||
| : d_(new PrivateData) { | ||
| d_->channel = channel; | ||
| auto channel_utf16 = stringToWstring(channel); | ||
| } | ||
|
|
||
| Status EvtSubscription::init() { | ||
| auto channel_utf16 = stringToWstring(d_->channel); | ||
|
|
||
| auto subscription = EvtSubscribe(nullptr, | ||
| nullptr, | ||
|
|
@@ -109,11 +116,12 @@ EvtSubscription::EvtSubscription(const std::string& channel) | |
|
|
||
| if (subscription == nullptr) { | ||
| auto error = GetLastError(); | ||
| throw Status::failure("Failed to subscribe to the channel named " + | ||
| channel + ". Error " + std::to_string(error)); | ||
| return Status::failure("Failed to subscribe to the channel named " + | ||
| d_->channel + ". Error " + std::to_string(error)); | ||
| } | ||
|
|
||
| d_->handle = subscription; | ||
| return Status::success(); | ||
| } | ||
|
|
||
| void EvtSubscription::processEvent(EVT_HANDLE event) { | ||
|
Comment on lines
116
to
127
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ EvtSubscription constructor throws Status instead of returning it In π€ Prompt for AI agentsfix confidence: π΄ 55 low β review closely β react π/π to teach the reviewer |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -251,7 +251,7 @@ Status NTFSEventPublisher::getPathFromReferenceNumber( | |
| buffer.resize(required_characters); | ||
| if (buffer.size() != required_characters) { | ||
| ::CloseHandle(handle); | ||
| throw std::bad_alloc(); | ||
| return Status::failure("Failed to allocate buffer for path resolution"); | ||
| } | ||
|
|
||
| auto bytes_returned = static_cast<size_t>( | ||
|
Comment on lines
251
to
257
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π std::bad_alloc thrown instead of Status::failure in getPathFromReferenceNumber In (Automatically downgraded: no change in this fix lands near this finding's line β verify whether it was actually addressed.) π€ Prompt for AI agentsfix confidence: π΄ 40 low β review closely β react π/π to teach the reviewer
Comment on lines
251
to
257
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π std::bad_alloc used instead of Status in resize-failure guard while rest of function uses Status Same code change as finding 1 (both findings reference the identical line/pattern); the single (Automatically downgraded: no change in this fix lands near this finding's line β verify whether it was actually addressed.) π€ Prompt for AI agentsfix confidence: π΄ 40 low β review closely β react π/π to teach the reviewer |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,6 +67,11 @@ HIDDEN_FLAG(bool, | |
| tls_allow_unsafe, | ||
| false, | ||
| "Allow TLS server certificate trust failures"); | ||
|
|
||
| HIDDEN_FLAG(bool, | ||
| openframe_mode_allow_unsafe, | ||
| false, | ||
| "Allow disabling TLS peer verification in openframe_mode"); | ||
| #endif | ||
|
|
||
| HIDDEN_FLAG(bool, | ||
|
|
@@ -111,11 +116,13 @@ http::Client::Options TLSTransport::getOptions() { | |
|
|
||
| options.follow_redirects(true).timeout(16); | ||
|
|
||
| if (FLAGS_openframe_mode) { | ||
| #ifndef NDEBUG | ||
| if (FLAGS_openframe_mode && FLAGS_openframe_mode_allow_unsafe) { | ||
| options.always_verify_peer(false); | ||
| return options; | ||
| } | ||
|
|
||
| } | ||
| #endif | ||
|
|
||
| options.always_verify_peer(verify_peer_); | ||
| if (server_certificate_file_.size() > 0) { | ||
| if (!osquery::isReadable(server_certificate_file_).ok()) { | ||
|
Comment on lines
116
to
128
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π getOptions() falls back to always_verify_peer(false) unconditionally in openframe_mode In π€ Prompt for AI agentsfix confidence: π‘ 75 medium β react π/π to teach the reviewer |
||
|
|
@@ -308,3 +315,4 @@ Status TLSTransport::sendRequest(const std::string& params, bool compress) { | |
| return response_status_; | ||
| } | ||
| } // namespace osquery | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,7 +30,16 @@ static inline void toLower(String& s) { | |
| } | ||
| } | ||
|
|
||
| Uri::Uri() : hasAuthority_(false), port_(0) {} | ||
|
|
||
| Uri::Uri(const std::string& str) : hasAuthority_(false), port_(0) { | ||
| auto status = Uri::parse(str, *this); | ||
| if (!status.ok()) { | ||
| throw std::invalid_argument(status.getMessage()); | ||
| } | ||
| } | ||
|
|
||
| Status Uri::parse(const std::string& str, Uri& uri) { | ||
| static const std::regex uriRegex( | ||
| "([a-zA-Z][a-zA-Z0-9+.-]*):" // scheme: | ||
| "([^?#]*)" // authority and path | ||
|
|
@@ -40,19 +49,19 @@ Uri::Uri(const std::string& str) : hasAuthority_(false), port_(0) { | |
|
|
||
| std::smatch match; | ||
| if (!std::regex_match(str, match, uriRegex)) { | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ Uri constructor throws std::invalid_argument instead of returning osquery::Status Added a static π€ Prompt for AI agentsfix confidence: π΄ 55 low β review closely β react π/π to teach the reviewer |
||
| throw std::invalid_argument("Invalid URL"); | ||
| return Status::failure("Invalid URL"); | ||
| } | ||
|
|
||
| scheme_ = submatch(match, 1); | ||
| toLower(scheme_); | ||
| uri.scheme_ = submatch(match, 1); | ||
| toLower(uri.scheme_); | ||
|
|
||
| std::string authorityAndPath(match[2].first, match[2].second); | ||
| std::smatch authorityAndPathMatch; | ||
| if (!std::regex_match( | ||
| authorityAndPath, authorityAndPathMatch, authorityAndPathRegex)) { | ||
| // Does not start with //, doesn't have authority | ||
| hasAuthority_ = false; | ||
| path_ = authorityAndPath; | ||
| uri.hasAuthority_ = false; | ||
| uri.path_ = authorityAndPath; | ||
| } else { | ||
| static const std::regex authorityRegex( | ||
| "(?:([^@:]*)(?::([^@]*))?@)?" // username, password | ||
|
Comment on lines
49
to
67
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π΄ Uri constructor throws std::invalid_argument for invalid authority The second throw at the authority-parsing regex mismatch was replaced with π€ Prompt for AI agentsfix confidence: π΄ 55 low β review closely β react π/π to teach the reviewer |
||
|
|
@@ -66,26 +75,28 @@ Uri::Uri(const std::string& str) : hasAuthority_(false), port_(0) { | |
| authority.second, | ||
| authorityMatch, | ||
| authorityRegex)) { | ||
| throw std::invalid_argument("Invalid URI authority"); | ||
| return Status::failure("Invalid URI authority"); | ||
| } | ||
|
|
||
| std::string port(authorityMatch[4].first, authorityMatch[4].second); | ||
| if (!port.empty()) { | ||
| int iport = std::stoi(port); | ||
| if (iport < UINT16_MAX && iport >= 0) { | ||
| port_ = static_cast<uint16_t>(iport); | ||
| uri.port_ = static_cast<uint16_t>(iport); | ||
| } | ||
| } | ||
|
|
||
| hasAuthority_ = true; | ||
| username_ = submatch(authorityMatch, 1); | ||
| password_ = submatch(authorityMatch, 2); | ||
| host_ = submatch(authorityMatch, 3); | ||
| path_ = submatch(authorityAndPathMatch, 2); | ||
| uri.hasAuthority_ = true; | ||
| uri.username_ = submatch(authorityMatch, 1); | ||
| uri.password_ = submatch(authorityMatch, 2); | ||
| uri.host_ = submatch(authorityMatch, 3); | ||
| uri.path_ = submatch(authorityAndPathMatch, 2); | ||
| } | ||
|
|
||
| query_ = submatch(match, 3); | ||
| fragment_ = submatch(match, 4); | ||
| uri.query_ = submatch(match, 3); | ||
| uri.fragment_ = submatch(match, 4); | ||
|
|
||
| return Status::success(); | ||
| } | ||
|
|
||
| std::string Uri::authority() const { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -136,7 +136,12 @@ QueryData genPasswordPolicy(QueryContext& context) { | |
| CFRelease(user_policy); | ||
| } | ||
| } | ||
| CFRelease(records); | ||
| if (records != nullptr) { | ||
| CFRelease(records); | ||
| } | ||
| if (query != nullptr) { | ||
| CFRelease(query); | ||
| } | ||
| CFRelease(uid_string); | ||
| } | ||
|
|
||
|
Comment on lines
136
to
147
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π genPasswordPolicy leaks CFQueryRef and can double-release CFArrayRef records on empty result In genPasswordPolicy's uid loop, added π€ Prompt for AI agentsfix confidence: π‘ 88 medium β react π/π to teach the reviewer |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,8 +13,6 @@ | |
|
|
||
| #include <gtest/gtest.h> | ||
|
|
||
| #include <boost/filesystem.hpp> | ||
| #include <gtest/gtest.h> | ||
| #include <osquery/sql/sql.h> | ||
| #include <osquery/tables/system/posix/ssh_keys.h> | ||
| #include <osquery/utils/scope_guard.h> | ||
|
Comment on lines
13
to
18
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π Duplicate #include of boost/filesystem.hpp and gtest/gtest.h in ssh_keys_tests.cpp Removed the duplicate π€ Prompt for AI agentsfix confidence: π’ 95 high β react π/π to teach the reviewer |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,17 +68,16 @@ std::string findSelfClosingTag(const std::string& xml, | |
|
|
||
| // Convert a Unix timestamp to a date in YYYYMMDD format | ||
| std::string formatTimestampToDate(time_t timestamp) { | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π formatTimestampToDate wraps non-throwing gmtime/put_time in try/catch, contrary to Status-based error handling used elsewhere In π€ Prompt for AI agentsfix confidence: π’ 90 high β react π/π to teach the reviewer |
||
| try { | ||
| // Convert the timestamp to a tm structure | ||
| std::tm* timeInfo = std::gmtime(×tamp); | ||
|
|
||
| // Format the date as YYYYMMDD | ||
| std::ostringstream oss; | ||
| oss << std::put_time(timeInfo, "%Y%m%d"); | ||
| return oss.str(); | ||
| } catch (...) { | ||
| // Convert the timestamp to a tm structure | ||
| std::tm* timeInfo = std::gmtime(×tamp); | ||
| if (timeInfo == nullptr) { | ||
| return ""; | ||
| } | ||
|
|
||
| // Format the date as YYYYMMDD | ||
| std::ostringstream oss; | ||
| oss << std::put_time(timeInfo, "%Y%m%d"); | ||
| return oss.str(); | ||
| } | ||
|
|
||
| std::string packageFamilyNameFromPackageFullName( | ||
|
|
@@ -457,3 +456,4 @@ QueryData genPrograms(QueryContext& context) { | |
| } | ||
| } // namespace tables | ||
| } // namespace osquery | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
𦩠π΄ carve() swallows partial-block POST failures without aborting the upload
In Carver::postCarve, added
anyBlockFailedbool andblockFailureStatusStatus tracked inside the per-block continue-request loop; whencontRequest.call(params)fails, these are now set instead of only logging andcontinueing. After the loop, ifanyBlockFailedis true, the function now callsupdateCarveValue(carveGuid_, "status", "DATA POST FAILED")and returns a failureStatus(instead of unconditionally marking success), soCarver::carve()'s caller correctly sees the post as failed. Removed the stale "TODO: Error sending files." comment since it's now addressed. Behavior for the fully-successful path is unchanged.(Automatically downgraded: no change in this fix lands near this finding's line β verify whether it was actually addressed.)
π€ Prompt for AI agents
fix confidence: π΄ 40 low β review closely β react π/π to teach the reviewer