Fix macOS software titles mis-named from embedded helper bundles (#44199)#47831
Fix macOS software titles mis-named from embedded helper bundles (#44199)#47831mostlikelee wants to merge 9 commits into
Conversation
…es under parent Reproduces #44199 by emitting embedded-helper paths (/some/path/Common_N.app/Contents/Library/LoginItems/<name>.app) when the new flag is set, enabling load tests of the ingestion filter and title backfill migration that follow. Default off — existing duplicate-bundle behavior unchanged.
…uery osquery's apps table reports both a parent app and any embedded login helper under Contents/Library/LoginItems as separate rows, often sharing a bundle identifier. The helper's name would clobber the software title's display name (e.g. AmphetamineLoginHelper instead of Amphetamine). Exclude paths nested under .app/Contents/ so only top-level bundles are ingested. Fixes #44199 prospectively. Existing mis-named titles are addressed by the follow-up backfill migration.
For macOS app titles whose software_titles.name was set from an
embedded helper bundle (e.g. AmphetamineLoginHelper) rather than the
parent app, recompute the name from the title's sibling software rows
using the same precedence as title creation:
1. Fleet-maintained app canonical name (if bundle id matches), else
2. longest-common-prefix of sibling names (trailing non-word chars
trimmed), else
3. shortest sibling name.
The migration drives off the indexed software_titles JOIN software
join (title_id) and only UPDATEs titles whose name actually changes —
deliberately not path-based, since host_software_installed_paths has
no global per-software source of truth and would force a full
unindexed TEXT scan inside the startup-blocking migration
transaction.
Pairs with the queries.go filter that prevents new mis-named titles
from forming.
|
@coderabbitai full review |
✅ Action performedFull review finished. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThis PR fixes a macOS software title naming bug where a login-helper app nested inside another app's bundle (e.g., The fix has two parts: the 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
server/datastore/mysql/migrations/tables/20260618124430_FixEmbeddedBundleTitleNames.go (1)
105-120: 💤 Low valueConsider deterministic tie-breaking for equal-length names.
The slice at line 105 is built from map iteration, which is non-deterministic in Go. If two sibling names have identical length, the "shortest" selection depends on iteration order.
For this one-shot migration with typical helper naming patterns, the practical impact is minimal, but sorting
nameslexicographically before the shortest-selection loop would make results reproducible.♻️ Optional fix for deterministic selection
+import "sort" + func fixEmbeddedPickTitleName(siblings map[string]struct{}, bundleID string, fmaNames map[string]string) string { if name, ok := fmaNames[bundleID]; ok && name != "" { return name } names := make([]string, 0, len(siblings)) for n := range siblings { names = append(names, n) } + sort.Strings(names) prefix := fixEmbeddedLongestCommonPrefix(names)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@server/datastore/mysql/migrations/tables/20260618124430_FixEmbeddedBundleTitleNames.go` around lines 105 - 120, The names slice is built from non-deterministic map iteration over the siblings map, which means when multiple sibling names have identical length, the shortest name selection depends on the iteration order. Sort the names slice lexicographically before the loop that finds the shortest name by calling sort.Strings(names) after the prefix check and before the loop that iterates through names[1:] to select the shortest, ensuring deterministic results regardless of map iteration order.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@server/datastore/mysql/migrations/tables/20260618124430_FixEmbeddedBundleTitleNames.go`:
- Around line 105-120: The names slice is built from non-deterministic map
iteration over the siblings map, which means when multiple sibling names have
identical length, the shortest name selection depends on the iteration order.
Sort the names slice lexicographically before the loop that finds the shortest
name by calling sort.Strings(names) after the prefix check and before the loop
that iterates through names[1:] to select the shortest, ensuring deterministic
results regardless of map iteration order.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: cfb47ebb-5c84-4c09-90ca-4bffb1a89949
⛔ Files ignored due to path filters (1)
docs/Contributing/product-groups/orchestration/understanding-host-vitals.mdis excluded by!**/*.md
📒 Files selected for processing (5)
changes/44199-embedded-bundle-title-namecmd/osquery-perf/agent.goserver/datastore/mysql/migrations/tables/20260618124430_FixEmbeddedBundleTitleNames.goserver/datastore/mysql/migrations/tables/20260618124430_FixEmbeddedBundleTitleNames_test.goserver/service/osquery_utils/queries.go
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #47831 +/- ##
==========================================
- Coverage 67.23% 67.23% -0.01%
==========================================
Files 3638 3640 +2
Lines 230034 230253 +219
Branches 11942 11781 -161
==========================================
+ Hits 154670 154816 +146
- Misses 61473 61526 +53
- Partials 13891 13911 +20
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Refactor Up_20260618124430 to delegate the title scan to fixEmbeddedScanTitles, where defer rows.Close() satisfies sqlclosecheck without the manual error-path close.
There was a problem hiding this comment.
Warning
- Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.
Pull request overview
This PR fixes incorrect macOS software title names caused by embedded helper bundles (e.g., LoginItems) sharing the parent app’s bundle identifier, ensuring the parent app name wins both for new ingests and for existing data.
Changes:
- Filter macOS
appsrows whosepathindicates an embedded bundle under*.app/Contents/*during osquery ingestion. - Add a one-time MySQL migration to recompute affected
software_titles.namevalues using FMA name override → longest common prefix → shortest fallback. - Extend
cmd/osquery-perfto optionally generate embedded-bundle installed paths so the scenario is reproducible at scale.
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| server/service/osquery_utils/queries.go | Excludes embedded *.app/Contents/* paths from the macOS apps software query to prevent future mis-naming. |
| server/datastore/mysql/schema.sql | Advances migration_status_tables seed data / AUTO_INCREMENT to include the new migration. |
| server/datastore/mysql/migrations/tables/20260618124430_FixEmbeddedBundleTitleNames.go | Implements the backfill migration that recomputes software_titles.name for affected app titles. |
| server/datastore/mysql/migrations/tables/20260618124430_FixEmbeddedBundleTitleNames_test.go | Adds coverage validating the migration’s name-picking precedence and out-of-scope behavior. |
| cmd/osquery-perf/agent.go | Adds --embedded_bundle_paths option to generate nested Contents/Library/LoginItems/... paths for duplicate-bundle scenarios. |
| changes/44199-embedded-bundle-title-name | User-visible change entry (content excluded from review by policy). |
| docs/Contributing/product-groups/orchestration/understanding-host-vitals.md | Documentation update (content excluded from review by policy). |
Files excluded by content exclusion policy (2)
- changes/44199-embedded-bundle-title-name
- docs/Contributing/product-groups/orchestration/understanding-host-vitals.md
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
fixEmbeddedLoadFMANamesDarwin now wraps query/scan/iteration errors with descriptive messages, matching the sibling fixEmbeddedScanTitles helper. Makes migration failure traces pinpoint the failing step.
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
Related issue: Resolves #44199
osquery reports an app's embedded login helper under
Contents/Library/LoginItems/as a separateappsrow sharing the parent's bundle identifier; whichever row created thesoftware_titlesrow wins its name, often the helper. Two changes pair:queries.go): drop rows whosepathmatches%.app/Contents/%. Prospective.appstitles from sibling software names (FMA → longest-common-prefix → shortest), UPDATE only on diff.cmd/osquery-perfgains--embedded_bundle_pathsto nest duplicate-bundle paths so the bug is reproducible at scale.Migration perf (osquery-perf library, the largest realistic dataset available)
EXPLAIN ANALYZE: PK scan onsoftware_titles+title_id-indexed lookups onsoftware. No table scans, no filesort. Linear extrapolation to ~5× scale stays well under 1s.Checklist for submitter
Changes file added for user-visible changes in
changes/Input data is properly validated,
SELECT *is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters.Testing
For unreleased bug fixes in a release candidate, one of:
Database migrations
COLLATE utf8mb4_unicode_ci).Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Contents.Database / Migration