Skip to content

gkarr 23242 fe#47754

Merged
georgekarrv merged 12 commits into
mainfrom
gkarr-23242-fe
Jun 29, 2026
Merged

gkarr 23242 fe#47754
georgekarrv merged 12 commits into
mainfrom
gkarr-23242-fe

Conversation

@georgekarrv

@georgekarrv georgekarrv commented Jun 17, 2026

Copy link
Copy Markdown
Member

Related issue: #23242

Frontend changes for Apple BYOD (personal) enrollment, layered on the merged backend work.

  • Adds the "Personal (BYOD)" vs "Company-owned" enrollment choice for iOS/iPadOS and Android on the end-user enroll flow.
  • Reflects per-enrollment access rights in host details (wipe/lock/clear-passcode actions disabled for personal Apple devices).
  • Updates the personal enrollment status label to "On (manual - personal)".

Checklist for submitter

If some of the following don't apply, delete the relevant line.

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
    See Changes files for more information.

  • 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.

  • If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes

Testing

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

Test plan

  • End-user enroll page: confirm the Personal (BYOD) vs Company-owned choice appears and drives the correct enrollment for iOS/iPadOS and Android.
  • Host details for a personal Apple device: wipe, lock, and clear-passcode actions are disabled; enabled for a company-owned device.
  • Enrollment status displays as "On (manual - personal)" for personal enrollments.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for "Personal (BYOD)" vs "Company-owned" enrollment options for iOS/iPadOS and Android devices, allowing organizations to enforce different MDM capabilities per enrollment type.
    • Introduced granular enrollment access rights management for Apple devices, controlling device wipe, lock, and passcode clear permissions based on enrollment profile.
  • Improvements

    • Updated enrollment status labels to clarify manual enrollment types and improve user guidance during device setup.

@georgekarrv georgekarrv marked this pull request as ready for review June 22, 2026 19:29
@georgekarrv georgekarrv requested review from a team as code owners June 22, 2026 19:29
Copilot AI review requested due to automatic review settings June 22, 2026 19:29

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends BYOD support by (1) distinguishing personal manual enrollments in the enrollment status string and (2) enforcing Apple MDM command permissions for personal (BYOD) manual enrollments via stored AccessRights, with corresponding UI updates.

Changes:

  • Add per-host Apple MDM enrollment AccessRights storage and use it to gate wipe/lock/clear-passcode (esp. for BYOD manual enrollments).
  • Rename the personal enrollment status string from On (personal) to On (manual - personal) across backend, migrations, and frontend.
  • Update enrollment flows and UI (/enroll, OTA) to support a “Personal (BYOD) vs Company-owned” selection and propagate byod through to the server URL.

Reviewed changes

Copilot reviewed 41 out of 41 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
server/service/integration_mdm_test.go Updates expected enrollment status string in MDM integration tests.
server/service/integration_mdm_setup_experience_test.go Updates expected enrollment status string for BYOD iOS setup experience test.
server/service/hosts.go Populates new wipe_allowed/lock_allowed/clear_passcode_allowed flags for Apple manual/personal hosts.
server/service/hosts_test.go Updates Android BYOD test fixtures to the renamed status string.
server/service/apple_mdm.go Propagates byod through manual + OTA enrollment flows, persists AccessRights, and uses stored rights in renewal.
server/service/apple_mdm_test.go Updates service tests for new method signatures and AccessRights parameter.
server/mock/service/service_mock.go Updates mock service interface signatures for new params.
server/mock/datastore_mock.go Adds mock datastore functions for Apple enrollment permissions get/set.
server/mdm/lifecycle/lifecycle.go Plumbs IsPersonalEnrollment into Apple lifecycle reset logic.
server/mdm/apple/apple_mdm.go Introduces AccessRights constants, AccessRights computation, and URL helper for personal flag; templates now render AccessRights.
server/mdm/apple/apple_mdm_test.go Updates tests for new enrollment profile generator signature.
server/fleet/service.go Updates Fleet Service interface for new enrollment/OTA method signatures.
server/fleet/hosts.go Adds new MDM permission fields to host payload; renames personal enrollment status constant; adds HostMDMApplePermissions model.
server/fleet/hosts_test.go Updates expected enrollment status for personal enrollment.
server/fleet/datastore.go Adds datastore interface methods for reading/writing stored Apple enrollment permissions.
server/datastore/mysql/schema.sql Updates generated enrollment_status enum value and adds host_mdm_apple_enrollment_permissions table.
server/datastore/mysql/migrations/tables/20260616144538_RenamePersonalEnrollmentStatus.go Migration to rename generated personal enrollment_status value.
server/datastore/mysql/migrations/tables/20260616144538_RenamePersonalEnrollmentStatus_test.go Migration test validating new generated enrollment_status value.
server/datastore/mysql/migrations/tables/20260616144537_AddHostMDMAppleEnrollmentPermissions.go Migration creating + backfilling permissions table for Apple manual enrollments.
server/datastore/mysql/migrations/tables/20260616144537_AddHostMDMAppleEnrollmentPermissions_test.go Migration test validating backfill rules and upsert behavior.
server/datastore/mysql/hosts.go Implements get/set datastore methods and host UUID cleanup mapping for new permissions table.
frontend/utilities/constants.tsx Updates MDM status tooltips for renamed status string.
frontend/templates/enroll-ota.html Adds BYOD/company-owned selector and propagates byod=true into the download URL.
frontend/pages/hosts/details/HostDetailsPage/modals/ClearPasscodeModal/ClearPasscodeModal.tsx Updates Android BYOD detection for renamed status string.
frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx Passes new *_allowed fields through to HostActionsDropdown.
frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tsx Adds props for permission gating and passes them into option generation.
frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx Updates tests for renamed personal enrollment status.
frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.tsx Disables wipe/lock/clear-passcode options when *_allowed is false and adds BYOD-specific tooltips.
frontend/pages/hosts/details/cards/Vitals/Vitals.tests.tsx Updates test fixtures for renamed personal enrollment status.
frontend/pages/hosts/details/cards/Software/SelfService/SelfService.tests.tsx Updates test fixtures for renamed personal enrollment status.
frontend/pages/hosts/details/cards/Software/helpers.tsx Updates iOS personal enrollment string checks for renamed status.
frontend/pages/hosts/details/cards/Software/helpers.tests.ts Updates tests for renamed personal enrollment status.
frontend/pages/DashboardPage/DashboardPage.tsx Updates dashboard MDM status bucket label for renamed personal enrollment status.
frontend/pages/DashboardPage/cards/MDM/MDM.tests.tsx Updates MDM card tests for renamed personal enrollment status.
frontend/interfaces/mdm.ts Updates enrollment status union + helpers to use renamed personal status.
frontend/interfaces/host.ts Adds new optional wipe_allowed/lock_allowed/clear_passcode_allowed fields on host MDM payload.
frontend/components/TableContainer/DataTable/HostMdmStatusCell/HostMdmStatusCell.tests.tsx Updates status cell tests for renamed personal enrollment status.
frontend/components/AddHostsModal/PlatformWrapper/IosIpadosPanel/IosIpadosPanel.tsx Adds BYOD/company-owned selection and includes byod=true in generated enroll URL for personal.
frontend/components/AddHostsModal/PlatformWrapper/AndroidPanel/AndroidPanel.tsx Updates radio label copy to “Personal (BYOD)” / “Company-owned (fully-managed)”.
frontend/components/AddHostsModal/AddHostsModal.tests.tsx Updates AddHostsModal tests for new iOS/iPadOS enrollment instructions UI.
ee/server/service/mdm.go Generates manual enrollment profile with BYOD-aware AccessRights and embeds personal flag into ServerURL.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/service/apple_mdm.go
Comment thread server/service/apple_mdm.go
Comment thread server/service/hosts.go
Comment thread frontend/utilities/constants.tsx
Comment thread frontend/templates/enroll-ota.html
Comment thread frontend/templates/enroll-ota.html
Comment thread frontend/pages/hosts/details/cards/Software/helpers.tsx
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR adds end-to-end BYOD (Personal enrollment) support for Apple MDM. The enrollment status string "On (personal)" is renamed to "On (manual - personal)" across database, backend, and frontend. A new host_mdm_apple_enrollment_permissions table stores per-host MDM access_rights, populated on enrollment check-in and backfilled for existing manually-enrolled Apple hosts. Profile generation functions (GenerateEnrollmentProfileMobileconfig, GenerateACMEEnrollmentProfileMobileconfig, GenerateOTAEnrollmentProfileMobileconfig) now accept access rights or a personal boolean. A byod query parameter propagates through manual enrollment, OTA GET, and OTA POST-back endpoints into mobileconfig generation. Host details now exposes WipeAllowed, LockAllowed, and ClearPasscodeAllowed flags derived from stored access rights, which gate corresponding actions in HostActionsDropdown. The iOS/iPadOS enrollment panel and OTA enrollment HTML page gain BYOD/Company-owned radio/tab UI.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'gkarr 23242 fe' is vague and uses non-descriptive terms that don't convey meaningful information about the changeset. Use a clear, specific title that summarizes the main change, such as 'Add BYOD personal enrollment support with access rights management' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description matches the template well, includes the related issue, summary, checklist, and test plan, with only non-critical items omitted.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch gkarr-23242-fe

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
server/service/apple_mdm.go (1)

3786-3811: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Persist permissions from the effective personal enrollment state.

resetApple treats EnrollmentID account-driven enrollments as personal, but this path stores access rights from only the URL param. That can persist full wipe/lock rights for account-driven BYOD hosts; also, silently continuing after a personal permission write failure leaves renewals/UI gating without the required restricted-rights row.

Proposed fix
-	isPersonal := r.Params != nil && r.Params[apple_mdm.FleetPersonalEnrollmentKey] == "1"
+	isPersonal := r.Params != nil && r.Params[apple_mdm.FleetPersonalEnrollmentKey] == "1"
+	effectivePersonal := isPersonal || m.EnrollmentID != ""

 	if err := svc.mdmLifecycle.Do(r.Context, mdmlifecycle.HostOptions{
 		Action:                mdmlifecycle.HostActionReset,
 		Platform:              platform,
 		UUID:                  m.UDID,
 		HardwareSerial:        m.SerialNumber,
 		HardwareModel:         m.Model,
 		SCEPRenewalInProgress: scepRenewalInProgress,
 		UserEnrollmentID:      m.EnrollmentID,
-		IsPersonalEnrollment:  isPersonal,
+		IsPersonalEnrollment:  effectivePersonal,
 	}); err != nil {
 		svc.logger.WarnContext(r.Context, "could not reset Apple mdm information", "UDID", m.UDID, "EnrollmentID", m.EnrollmentID, "err", err)
 		return err
 	}

 	// Persist the access rights for this host so SCEP/ACME renewal can honour
 	// the monotonic-narrowing invariant (Apple disallows widening on replace).
-	accessRights := apple_mdm.AppleEnrollmentAccessRights(isPersonal)
+	accessRights := apple_mdm.AppleEnrollmentAccessRights(effectivePersonal)
 	if err := svc.ds.SetHostMDMAppleEnrollmentPermissions(r.Context, r.ID, accessRights); err != nil {
+		if effectivePersonal {
+			return ctxerr.Wrap(r.Context, err, "persisting personal enrollment permissions")
+		}
 		svc.logger.ErrorContext(r.Context, "failed to persist enrollment permissions", "host_uuid", r.ID, "err", err)
-		// Non-fatal: worst-case the next SCEP renewal uses MDMAccessRightAll (the pre-feature default).
 	}
🤖 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/service/apple_mdm.go` around lines 3786 - 3811, The code determines
personal enrollment status for the mdmlifecycle.Do call using
IsPersonalEnrollment, which treats account-driven enrollments as personal, but
then uses only the URL parameter isPersonal when calling
AppleEnrollmentAccessRights. Update the logic to pass to
AppleEnrollmentAccessRights the same effective personal enrollment state that
considers both the URL parameter and account-driven enrollment status (based on
EnrollmentID), and remove or change the non-fatal error handling for
SetHostMDMAppleEnrollmentPermissions since silently continuing after a
permission write failure can leave renewals and UI gating without required
restricted-rights rows.
🧹 Nitpick comments (4)
frontend/pages/hosts/details/HostDetailsPage/modals/ClearPasscodeModal/ClearPasscodeModal.tsx (1)

10-10: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Use the shared BYOD enrollment helper instead of a raw status string.

Line 37 hardcodes "On (manual - personal)", which duplicates enrollment-status contract logic in UI code. Prefer the centralized helper to avoid future drift.

Proposed change
-import { MdmEnrollmentStatus } from "interfaces/mdm";
+import { MdmEnrollmentStatus, isAndroidBYO } from "interfaces/mdm";
@@
-  const isAndroidBYO =
-    isAndroidHost && hostMdmEnrollmentStatus === "On (manual - personal)";
+  const isAndroidBYODEnrollment =
+    isAndroidHost && isAndroidBYO(hostMdmEnrollmentStatus);
@@
-    if (isAndroidBYO) {
+    if (isAndroidBYODEnrollment) {

Also applies to: 35-37, 60-60

🤖 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
`@frontend/pages/hosts/details/HostDetailsPage/modals/ClearPasscodeModal/ClearPasscodeModal.tsx`
at line 10, The code contains hardcoded enrollment status strings like "On
(manual - personal)" at lines 35-37 and line 60, which duplicates
enrollment-status contract logic. Replace these hardcoded strings with calls to
a shared BYOD enrollment helper function that centralizes this logic. Import the
necessary helper function from the shared utilities if not already imported, and
refactor the locations where the enrollment status string is used to call the
helper function instead of using the raw hardcoded string.
frontend/components/AddHostsModal/PlatformWrapper/IosIpadosPanel/IosIpadosPanel.tsx (1)

65-82: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Add a legend to the enrollment-type radio group.

At Line 65, the new <fieldset> has no <legend>, so the two radio options lose group context for screen-reader users.

Proposed change
         <fieldset className="form-field">
+          <legend>Enrollment type</legend>
           <Radio
             name="iosIpadosEnrollmentType"
             id="iosIpadosPersonal"
             label="Personal (BYOD)"
🤖 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
`@frontend/components/AddHostsModal/PlatformWrapper/IosIpadosPanel/IosIpadosPanel.tsx`
around lines 65 - 82, The fieldset element in IosIpadosPanel lacks a legend
element, which is required for accessibility. Add a legend element as the first
child inside the fieldset that describes the purpose of the radio group (e.g.,
describing that users are selecting between personal and company-owned
enrollment types). The legend should be placed immediately after the opening
fieldset tag and before the Radio components for iosIpadosPersonal and
iosIpadosCompanyOwned.
server/mdm/apple/apple_mdm_test.go (1)

243-274: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider adding test coverage for the AccessRights value in the generated profile.

The test verifies SCEP and MDM URLs but doesn't assert that the AccessRights integer is correctly embedded in the output. Consider adding a case with AppleEnrollmentAccessRights(true) (personal enrollment) and verifying the resulting plist contains the expected value (8179 instead of 8191).

🤖 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/mdm/apple/apple_mdm_test.go` around lines 243 - 274, The test for
GenerateEnrollmentProfileMobileconfig in the loop starting at line 243 currently
verifies SCEP and MDM URLs but does not assert the AccessRights value in the
generated profile. Add a new test case with AppleEnrollmentAccessRights(true)
for personal enrollment, and within the switch statement for payload type
checking, add a case to verify that the AccessRights integer value in the
profile matches the expected value (8179 for personal enrollment versus 8191 for
MDMAccessRightAll). This can be done by checking the appropriate field in the
profile structure or payload after unmarshaling the plist result.
server/mdm/apple/apple_mdm.go (1)

1726-1744: 🧹 Nitpick | 🔵 Trivial

Inconsistency in byod parameter representation: unify to single format.

The byod parameter is set to "true" in GenerateOTAEnrollmentProfileMobileconfig but to "1" in AddPersonalEnrollmentToFleetURL. While downstream handlers (lines 6675, 6804) already accommodate both formats with explicit checks ("true" || "1"), consolidating to a single representation would improve consistency and reduce the need for defensive parsing logic.

🤖 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/mdm/apple/apple_mdm.go` around lines 1726 - 1744, The byod parameter
is being set inconsistently across functions:
GenerateOTAEnrollmentProfileMobileconfig uses "true" while
AddPersonalEnrollmentToFleetURL uses "1". Unify this parameter to use a single
consistent format across both functions. Choose one representation (either
"true" or "1") and update both GenerateOTAEnrollmentProfileMobileconfig and
AddPersonalEnrollmentToFleetURL to use the same value when setting the byod
query parameter. This will eliminate the need for defensive parsing logic in the
downstream handlers.
🤖 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.

Inline comments:
In `@frontend/templates/enroll-ota.html`:
- Around line 365-367: The buttons with classes byod-tab, byod-tab--personal,
and byod-tab--company are incorrectly marked with role="tab" and aria-selected
attributes without implementing full tab pattern semantics. Replace the tab
roles with proper toggle button semantics by removing role="tab", removing the
aria-selected attributes, and adding aria-pressed="false" for the inactive
button (Personal) and aria-pressed="true" for the active button (Company-owned).
Update the JavaScript logic that switches between these buttons to toggle
aria-pressed instead of aria-selected. Apply the same changes to all occurrences
mentioned in lines 439-440 and 734-739.

In `@server/datastore/mysql/hosts.go`:
- Line 643: The host_mdm_apple_enrollment_permissions table is being removed as
part of a generic UUID-based cleanup that affects all host types. This creates a
risk where deleting a Windows or Linux host with a duplicate UUID could remove
Apple MDM enrollment permissions for a surviving Apple host with the same UUID.
Modify the cleanup logic to scope the deletion of
host_mdm_apple_enrollment_permissions specifically to Apple hosts (verify the
host being deleted is an Apple host) or add a safeguard check to only delete
this table when no other host with that UUID remains in the database, similar to
the duplicate-UUID safeguard mentioned in the comment.
- Around line 4531-4534: In the INSERT...ON DUPLICATE KEY UPDATE statement for
the host_mdm_apple_enrollment_permissions table, the ON DUPLICATE KEY UPDATE
clause currently only updates the access_rights field. Modify this clause to
also refresh the delivered_at column to the current timestamp when a duplicate
key is encountered, so that repeated profile delivery updates reflect the latest
delivery metadata rather than keeping the stale original timestamp.

---

Outside diff comments:
In `@server/service/apple_mdm.go`:
- Around line 3786-3811: The code determines personal enrollment status for the
mdmlifecycle.Do call using IsPersonalEnrollment, which treats account-driven
enrollments as personal, but then uses only the URL parameter isPersonal when
calling AppleEnrollmentAccessRights. Update the logic to pass to
AppleEnrollmentAccessRights the same effective personal enrollment state that
considers both the URL parameter and account-driven enrollment status (based on
EnrollmentID), and remove or change the non-fatal error handling for
SetHostMDMAppleEnrollmentPermissions since silently continuing after a
permission write failure can leave renewals and UI gating without required
restricted-rights rows.

---

Nitpick comments:
In
`@frontend/components/AddHostsModal/PlatformWrapper/IosIpadosPanel/IosIpadosPanel.tsx`:
- Around line 65-82: The fieldset element in IosIpadosPanel lacks a legend
element, which is required for accessibility. Add a legend element as the first
child inside the fieldset that describes the purpose of the radio group (e.g.,
describing that users are selecting between personal and company-owned
enrollment types). The legend should be placed immediately after the opening
fieldset tag and before the Radio components for iosIpadosPersonal and
iosIpadosCompanyOwned.

In
`@frontend/pages/hosts/details/HostDetailsPage/modals/ClearPasscodeModal/ClearPasscodeModal.tsx`:
- Line 10: The code contains hardcoded enrollment status strings like "On
(manual - personal)" at lines 35-37 and line 60, which duplicates
enrollment-status contract logic. Replace these hardcoded strings with calls to
a shared BYOD enrollment helper function that centralizes this logic. Import the
necessary helper function from the shared utilities if not already imported, and
refactor the locations where the enrollment status string is used to call the
helper function instead of using the raw hardcoded string.

In `@server/mdm/apple/apple_mdm_test.go`:
- Around line 243-274: The test for GenerateEnrollmentProfileMobileconfig in the
loop starting at line 243 currently verifies SCEP and MDM URLs but does not
assert the AccessRights value in the generated profile. Add a new test case with
AppleEnrollmentAccessRights(true) for personal enrollment, and within the switch
statement for payload type checking, add a case to verify that the AccessRights
integer value in the profile matches the expected value (8179 for personal
enrollment versus 8191 for MDMAccessRightAll). This can be done by checking the
appropriate field in the profile structure or payload after unmarshaling the
plist result.

In `@server/mdm/apple/apple_mdm.go`:
- Around line 1726-1744: The byod parameter is being set inconsistently across
functions: GenerateOTAEnrollmentProfileMobileconfig uses "true" while
AddPersonalEnrollmentToFleetURL uses "1". Unify this parameter to use a single
consistent format across both functions. Choose one representation (either
"true" or "1") and update both GenerateOTAEnrollmentProfileMobileconfig and
AddPersonalEnrollmentToFleetURL to use the same value when setting the byod
query parameter. This will eliminate the need for defensive parsing logic in the
downstream handlers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f2447533-28a2-4dc6-b69b-724e9c96b0a7

📥 Commits

Reviewing files that changed from the base of the PR and between aa24188 and 9d713af.

📒 Files selected for processing (41)
  • ee/server/service/mdm.go
  • frontend/components/AddHostsModal/AddHostsModal.tests.tsx
  • frontend/components/AddHostsModal/PlatformWrapper/AndroidPanel/AndroidPanel.tsx
  • frontend/components/AddHostsModal/PlatformWrapper/IosIpadosPanel/IosIpadosPanel.tsx
  • frontend/components/TableContainer/DataTable/HostMdmStatusCell/HostMdmStatusCell.tests.tsx
  • frontend/interfaces/host.ts
  • frontend/interfaces/mdm.ts
  • frontend/pages/DashboardPage/DashboardPage.tsx
  • frontend/pages/DashboardPage/cards/MDM/MDM.tests.tsx
  • frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx
  • frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tsx
  • frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.tsx
  • frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx
  • frontend/pages/hosts/details/HostDetailsPage/modals/ClearPasscodeModal/ClearPasscodeModal.tsx
  • frontend/pages/hosts/details/cards/Software/SelfService/SelfService.tests.tsx
  • frontend/pages/hosts/details/cards/Software/helpers.tests.ts
  • frontend/pages/hosts/details/cards/Software/helpers.tsx
  • frontend/pages/hosts/details/cards/Vitals/Vitals.tests.tsx
  • frontend/templates/enroll-ota.html
  • frontend/utilities/constants.tsx
  • server/datastore/mysql/hosts.go
  • server/datastore/mysql/migrations/tables/20260616144537_AddHostMDMAppleEnrollmentPermissions.go
  • server/datastore/mysql/migrations/tables/20260616144537_AddHostMDMAppleEnrollmentPermissions_test.go
  • server/datastore/mysql/migrations/tables/20260616144538_RenamePersonalEnrollmentStatus.go
  • server/datastore/mysql/migrations/tables/20260616144538_RenamePersonalEnrollmentStatus_test.go
  • server/datastore/mysql/schema.sql
  • server/fleet/datastore.go
  • server/fleet/hosts.go
  • server/fleet/hosts_test.go
  • server/fleet/service.go
  • server/mdm/apple/apple_mdm.go
  • server/mdm/apple/apple_mdm_test.go
  • server/mdm/lifecycle/lifecycle.go
  • server/mock/datastore_mock.go
  • server/mock/service/service_mock.go
  • server/service/apple_mdm.go
  • server/service/apple_mdm_test.go
  • server/service/hosts.go
  • server/service/hosts_test.go
  • server/service/integration_mdm_setup_experience_test.go
  • server/service/integration_mdm_test.go

Comment thread frontend/templates/enroll-ota.html
Comment thread server/datastore/mysql/hosts.go Outdated
Comment thread server/datastore/mysql/hosts.go
Aligns the OTA endpoint and the MDM ServerURL query key with the
"byod" param the /enroll page and add-hosts modal already use, so the
URL key is consistent across the personal-enrollment surface area:

- getManualEnrollmentProfileRequest.Personal: query:"personal" -> "byod"
- getOTAProfileRequest.Personal: query:"personal" -> "byod"
- OTA decoder + POST-back decoder read Query().Get("byod")
- GenerateOTAEnrollmentProfileMobileconfig writes "byod=true"
- FleetPersonalEnrollmentKey constant value: "is_personal" -> "byod"

Consumer at apple_mdm.go:3771 reads via the constant, so the rename
propagates through the Authenticate checkin without code changes.
The Authenticate handler runs on every checkin, including the one
triggered by a SCEP cert renewal. The renewed enrollment profile's
ServerURL does not carry byod=1, so isPersonal would be derived as
false during the renewal Authenticate.

Without this guard, SetHostMDMAppleEnrollmentPermissions would
overwrite the previously-stored narrow bitmask (MDMAccessRightAll &^
DeviceLock &^ DeviceErase) with MDMAccessRightAll. The next SCEP
renewal would then generate a profile requesting full rights, which
Apple rejects as a widening violation on replacement.

The rights row is a write-once-at-enrollment value; renewal must
preserve it.
Comment thread frontend/templates/enroll-ota.html Fixed
@codecov

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.47%. Comparing base (b438893) to head (6dc4005).
⚠️ Report is 37 commits behind head on main.

Files with missing lines Patch % Lines
...ls/HostDetailsPage/HostActionsDropdown/helpers.tsx 41.17% 10 Missing ⚠️
.../PlatformWrapper/IosIpadosPanel/IosIpadosPanel.tsx 60.00% 2 Missing ⚠️
...e/modals/ClearPasscodeModal/ClearPasscodeModal.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #47754      +/-   ##
==========================================
- Coverage   67.47%   67.47%   -0.01%     
==========================================
  Files        3672     3673       +1     
  Lines      232703   232973     +270     
  Branches    12405    12421      +16     
==========================================
+ Hits       157025   157193     +168     
- Misses      61588    61657      +69     
- Partials    14090    14123      +33     
Flag Coverage Δ
backend 69.01% <ø> (-0.01%) ⬇️
frontend 59.00% <50.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Apple rejects ServerURL changes on enrollment-profile replacement, so the
URL the renewal generator builds must exactly match the URL the device was
originally enrolled with. The OTA / EE manual-enrollment paths bake byod=1
into the ServerURL for personal devices (AddPersonalEnrollmentToFleetURL),
but the renewal generator at server/service/apple_mdm.go was passing the
raw MDMUrl(), dropping byod=1 on every BYOD renewal and triggering Apple
rejection.

Fix:
- Extend GetHostMDMAppleEnrollmentPermissions to JOIN host_mdm so
  IsPersonalEnrollment (the authoritative BYOD signal) and AccessRights
  are returned together. The lookup is now driven off hosts.uuid so it
  returns a row whenever the device exists, even if the permissions
  persist failed during initial Authenticate (that write is non-fatal).
- Add renewalEnrollmentParams() helper that returns (personal, rights),
  re-narrowing the bitmask when a personal device's stored rights came
  back unrestricted (covers the persist-failure edge case).
- Apply at all three renewal sites:
  * manual SCEP without enroll ref (filteredAssocs)
  * manual SCEP with enroll ref (assocsWithRefs)
  * ACME (defensive; OTA is the only BYOD path and OTA doesn't use ACME,
    but match URL shape in case that combination becomes possible).

Matrix verified:
- Pre-feature device: is_personal_enrollment=0, no permissions row
  -> personal=false, rights=MDMAccessRightAll, URL=MDMUrl. Matches.
- New company-owned: is_personal_enrollment=0, rights=MDMAccessRightAll
  -> personal=false, URL=MDMUrl. Matches.
- New BYOD: is_personal_enrollment=1, rights=narrow
  -> personal=true, URL=MDMUrl?byod=1, rights=narrow. Matches.
- New BYOD with persist-failed permissions row:
  is_personal_enrollment=1, no permissions row -> personal=true,
  rights renarrowed from personal flag, URL=MDMUrl?byod=1. Matches.
- ADUE: uses GenerateAccountDrivenEnrollmentProfileMobileconfig (no byod
  in initial URL) and a different renewal path that does not call
  AddPersonalEnrollmentToFleetURL -> URL unchanged. Matches.
# Conflicts:
#	server/datastore/mysql/hosts.go
#	server/fleet/hosts.go
#	server/service/apple_mdm.go
…al - personal)'

Cosmetic: the actual asserted values already used the renamed status; only two
test/describe description strings still referenced the old label.
CodeQL flagged a high-severity alert: the download link's href, read from the DOM
(data-base-href/href), was string-concatenated back into the href in the catch
fallback, reinterpreting DOM-sourced text unsafely.

The primary path already routes baseHref through the URL constructor (which resolves
relative URLs against the origin and normalizes the value), so the raw-concat
fallback was both unnecessary and the flagged sink. Drop it: if URL parsing ever
fails, leave the server-rendered href untouched rather than reinterpreting it.
Comment on lines +4 to +56
@@ -21,6 +29,11 @@ interface IosIpadosPanelProps {
const IosIpadosPanel = ({ enrollSecret }: IosIpadosPanelProps) => {
const { config, isMacMdmEnabledAndConfigured } = useContext(AppContext);

// Default to "Personal (BYOD)" per #23242 design.
const [enrollmentType, setEnrollmentType] = useState<EnrollmentType>(
"personal"
);

const helpText =
"When the end user navigates to this URL, the enrollment profile " +
"will download in their browser. End users will have to install the profile " +
@@ -40,19 +53,43 @@ const IosIpadosPanel = ({ enrollSecret }: IosIpadosPanelProps) => {
);
}

const url = generateUrl(config.server_settings.server_url, enrollSecret);
const url = generateUrl(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we drop generateUrl and inline getPathWithQueryParams from utilities/url at the call site? It URL-encodes and filters
undefined/null/"" for us, so the byod toggle falls out naturally and we stay consistent with the rest of the frontend (the TODO at
frontend/utilities/url/index.ts:102 calls it out as the preferred helper):

const url = getPathWithQueryParams(
${config.server_settings.server_url}/enroll,
{
enroll_secret: enrollSecret,
byod: enrollmentType === "personal" ? "true" : undefined,
}
);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done in 6dc4005. Dropped generateUrl and inlined getPathWithQueryParams exactly as suggested:

const url = getPathWithQueryParams(
  `${config.server_settings.server_url}/enroll`,
  {
    enroll_secret: enrollSecret,
    byod: enrollmentType === "personal" ? "true" : undefined,
  }
);

The helper URL-encodes and filters out the undefined byod value, so the company-owned case drops the param naturally. (Left the matching generateUrl in AndroidPanel.tsx alone since it's pre-existing on main from #39468 and outside this PR's scope — happy to do that as a follow-up if you'd like.)

const BYOD_DISABLED_TOOLTIPS: Record<string, JSX.Element> = {
wipe: <>Wipe permissions are disabled for this host.</>,
lock: <>Lock permissions are disabled for this host.</>,
clearPasscode: <>Clear passcode permissions are disabled for this host.</>,

@RachelElysia RachelElysia Jun 29, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

styling nit, adding a <br/> halfway through so the tooltip doesn't have weird hanging words, for example this might render like:

Clear passcode permissions are disabled for
this host.

instead of:

Clear passcode permissions
are disabled for this host.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done in 6dc4005 — added a <br/> after "permissions" so it renders as:

Clear passcode permissions
are disabled for this host.

Applied the same break to the wipe and lock tooltips too so the three stay visually consistent in the dropdown.

@RachelElysia RachelElysia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good, just a) replace one helper function with an existing helper function and b) some tooltip styling consideration nit

…YOD tooltips

- IosIpadosPanel: drop the custom generateUrl helper and build the enroll URL with
  getPathWithQueryParams from utilities/url, which URL-encodes and drops
  undefined/null/empty values (the byod toggle falls out naturally) — matches the
  preferred helper called out in utilities/url and stays consistent with the rest
  of the frontend.
- HostActionsDropdown BYOD-disabled tooltips: add a <br/> after "permissions" so the
  copy wraps cleanly instead of leaving hanging words.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: test-go (vuln, mysql:8.0.44) / test

Failed stage: Run Go Tests [❌]

Failed test name: TestIntegrationsSync

Failure summary:

The action failed because a Go test failed in the vulnerabilities package:
- Test failure:
server/vulnerabilities/macoffice TestIntegrationsSync failed with Condition failed! at
server/vulnerabilities/macoffice/integration_sync_test.go:39.
- The test expected to find one of
several Mac Office release notes JSON files (dated 2026_06_23 through 2026_06_29) in the temp
directory /tmp/TestIntegrationsSync494832307/001, but none of those files were present.
- This
caused make test-go to exit non-zero (make[1]: *** [Makefile:291: .run-go-tests] Error 1, make: ***
[Makefile:406: test-go] Error 2), failing the GitHub Actions job (Process completed with exit code
2).

Relevant error logs:
1:  Runner name: 'ubuntu-8core-1000955320'
2:  Runner group name: 'default larger runners'
...

966:  �[36;1mattempt=1�[0m
967:  �[36;1m�[0m
968:  �[36;1mwhile [ $attempt -le $max_attempts ]; do�[0m
969:  �[36;1m  echo "Attempt $attempt of $max_attempts"�[0m
970:  �[36;1m�[0m
971:  �[36;1m  # Try to connect to MySQL�[0m
972:  �[36;1m  if wait_for_mysql "mysql_test"; then�[0m
973:  �[36;1m    # If MySQL is ready, try to connect to MySQL replica�[0m
974:  �[36;1m    if wait_for_mysql "mysql_replica_test"; then�[0m
975:  �[36;1m      # Both are ready, we're done�[0m
976:  �[36;1m      echo "All MySQL connections successful"�[0m
977:  �[36;1m      exit 0�[0m
978:  �[36;1m    fi�[0m
979:  �[36;1m  fi�[0m
980:  �[36;1m�[0m
981:  �[36;1m  # If we get here, at least one connection failed�[0m
982:  �[36;1m  echo "Failed to connect to MySQL on attempt $attempt"�[0m
983:  �[36;1m�[0m
984:  �[36;1m  if [ $attempt -lt $max_attempts ]; then�[0m
985:  �[36;1m    echo "Restarting containers and trying again..."�[0m
986:  �[36;1m    restart_containers�[0m
987:  �[36;1m  else�[0m
988:  �[36;1m    echo "Maximum attempts reached. Failing the job."�[0m
989:  �[36;1m    exit 1�[0m
...

1107:  �[32m✓�[0m Is server core (0.00s)
1108:  �[32m✓�[0m Matches (0.00s)
1109:  �[32m✓�[0m Matches from differect arch (0.00s)
1110:  �[32m✓�[0m Matches from differect products (0.00s)
1111:  �[32m✓�[0m Matches operating system (0.00s)
1112:  �[32m✓�[0m Matches same product but for different architecture (0.00s)
1113:  �[32m✓�[0m Matches same product one with no architecture (0.00s)
1114:  �[32m✓�[0m Matches same product same arch (0.00s)
1115:  �[32m✓�[0m New product from OS (0.00s)
1116:  �[32m✓�[0m Product has display version (0.00s)
1117:  �[32m✓�[0m Security bulletin (0.00s)
1118:  �[32m✓�[0m Security bulletin # merge (0.00s)
1119:  �[32m✓�[0m Security bulletin # merge . products (0.00s)
1120:  �[32m✓�[0m Security bulletin # merge . vendor fixes (0.00s)
1121:  �[32m✓�[0m Security bulletin # merge . vulnerabilities (0.00s)
1122:  �[32m✓�[0m Security bulletin # merge fails if product names don't match (0.00s)
1123:  �[32m✓�[0m Security bulletin # merge with empty bulletins (0.00s)
1124:  �[32m✓�[0m Security bulletin # unmarshal JSON (0.00s)
1125:  �[32m✓�[0m Security bulletin # unmarshal JSON accepts new vulnerabilities key (0.00s)
1126:  �[32m✓�[0m Security bulletin # unmarshal JSON accepts old misspelled vulnerabities key (0.00s)
1127:  �[32m✓�[0m Security bulletin # unmarshal JSON marshal uses correct spelling (0.00s)
1128:  github.com/fleetdm/fleet/v4/server/vulnerabilities/goval_dictionary:
1129:  �[32m✓�[0m Database (0.00s)
1130:  �[32m✓�[0m Database close releases file handle (0.05s)
1131:  �[32m✓�[0m Database fixed version (0.00s)
1132:  �[32m✓�[0m Database multiple packages, fixed version (0.00s)
1133:  �[32m✓�[0m Database multiple packages, multiple vulnerabilities (0.00s)
1134:  �[32m✓�[0m Database newer than fixed version (0.00s)
1135:  �[32m✓�[0m Database non-matching architecture (0.00s)
1136:  �[32m✓�[0m Database non-matching package name (0.00s)
1137:  �[32m✓�[0m Database older than fixed version (0.00s)
1138:  �[32m✓�[0m Database verify returns no errors (0.00s)
1139:  �[32m✓�[0m Sync (0.00s)
1140:  �[32m✓�[0m Sync #what to download (0.00s)
1141:  �[32m✓�[0m Verify (0.00s)
1142:  �[32m✓�[0m Verify verify alerts of error (0.00s)
1143:  github.com/fleetdm/fleet/v4/server/vulnerabilities/msrc:
...

1174:  �[32m✓�[0m Parser (0.26s)
1175:  �[32m✓�[0m Parser map to security bulletins (0.00s)
1176:  �[32m✓�[0m Parser map to security bulletins each bulletin should have the right products (0.00s)
1177:  �[32m✓�[0m Parser map to security bulletins each bulletin should have the right vulnerabilities (0.00s)
1178:  �[32m✓�[0m Parser map to security bulletins should have one bulletin per product (0.00s)
1179:  �[32m✓�[0m Parser map to security bulletins should map the vendor fixes entries correctly (0.00s)
1180:  �[32m✓�[0m Parser map to security bulletins should map the vulnerability entries correctly (0.00s)
1181:  �[32m✓�[0m Parser parse XML (0.10s)
1182:  �[32m✓�[0m Parser parse XML only CVEs for windows products are included (0.00s)
1183:  �[32m✓�[0m Parser parse XML only windows products are included (0.00s)
1184:  �[32m✓�[0m Parser parse XML scores are parsed correctly (0.00s)
1185:  �[32m✓�[0m Parser parse XML should include windows server 2025 from 202 6- feb feed (0.10s)
1186:  �[32m✓�[0m Parser parse XML the remediations are parsed correctly (0.00s)
1187:  �[32m✓�[0m Parser parse XML the revision history is parsed correctly (0.00s)
1188:  �[32m✓�[0m Parser parse feed (0.00s)
1189:  �[32m✓�[0m Parser parse feed errors out if file does not exists (0.00s)
1190:  �[32m✓�[0m Sync (0.00s)
...

1327:  �[32m✓�[0m Extract ubuntu version future version 2 5.04 (0.00s)
1328:  �[32m✓�[0m Extract ubuntu version interim release 2 3.10 (0.00s)
1329:  �[32m✓�[0m Extract ubuntu version interim release 2 4.10 with patch (0.00s)
1330:  �[32m✓�[0m Extract ubuntu version invalid version - single digit (0.00s)
1331:  �[32m✓�[0m Extract ubuntu version ubuntu 1 6.04 with extra spaces (0.00s)
1332:  �[32m✓�[0m Extract ubuntu version ubuntu 1 8.04 (0.00s)
1333:  �[32m✓�[0m Extract ubuntu version ubuntu 2 0.04 LTS (0.00s)
1334:  �[32m✓�[0m Extract ubuntu version ubuntu 2 2.04 LTS (0.00s)
1335:  �[32m✓�[0m Extract ubuntu version ubuntu 2 4.04 no LTS suffix (0.00s)
1336:  �[32m✓�[0m Extract ubuntu version version with codename suffix (0.00s)
1337:  �[32m✓�[0m Extract ubuntu version very old version 1 4.04 (0.00s)
1338:  �[32m✓�[0m Find latest OSV artifact for version (0.00s)
1339:  �[32m✓�[0m Find latest OSV artifact for version finds latest 1 8.04 artifact (0.00s)
1340:  �[32m✓�[0m Find latest OSV artifact for version finds latest 2 0.04 artifact (0.00s)
1341:  �[32m✓�[0m Find latest OSV artifact for version finds latest 2 2.04 artifact (0.00s)
1342:  �[32m✓�[0m Find latest OSV artifact for version returns error for non-existent version (0.00s)
1343:  �[32m✓�[0m Get needed RHEL versions (0.00s)
...

1415:  �[32m✓�[0m Normalize kernel version generic 6 4k kernel (0.00s)
1416:  �[32m✓�[0m Normalize kernel version generic kernel (0.00s)
1417:  �[32m✓�[0m Normalize kernel version kernel with only one part (0.00s)
1418:  �[32m✓�[0m Normalize kernel version lowlatency kernel (0.00s)
1419:  �[32m✓�[0m OSV filename (0.00s)
1420:  �[32m✓�[0m OSV filename 1804 (0.00s)
1421:  �[32m✓�[0m OSV filename 2004 (0.00s)
1422:  �[32m✓�[0m OSV filename 2204 (0.00s)
1423:  �[32m✓�[0m RHELOSV filename (0.00s)
1424:  �[32m✓�[0m RHELOSV filename 10 (0.00s)
1425:  �[32m✓�[0m RHELOSV filename 8 (0.00s)
1426:  �[32m✓�[0m RHELOSV filename 9 (0.00s)
1427:  �[32m✓�[0m Release date from assets (0.00s)
1428:  �[32m✓�[0m Remove old OSV artifacts (0.00s)
1429:  �[32m✓�[0m Remove old OSV artifacts date boundary race (0.00s)
1430:  �[32m✓�[0m Remove old OSV artifacts preserves failed versions (0.00s)
1431:  �[32m✓�[0m Remove old OSV artifacts with skipped versions (0.00s)
1432:  �[32m✓�[0m Remove old RHELOSV artifacts (0.00s)
1433:  �[32m✓�[0m Sync OSV checksum match (0.00s)
1434:  �[32m✓�[0m Sync OSV fault tolerance (0.00s)
1435:  �[32m✓�[0m Sync OSV partial failure not returned as error (0.00s)
1436:  �[32m✓�[0m Version from asset name (0.00s)
...

1469:  �[32m✓�[0m CVE use existing sync cve-2. 0 .xml.gz (0.01s)
1470:  �[32m✓�[0m CVE use existing sync cve-2. 0 .xml.zip (0.01s)
1471:  �[33m∅�[0m End to end (0.00s)
1472:  �[32m✓�[0m Response not OK (0.00s)
1473:  github.com/fleetdm/fleet/v4/server/vulnerabilities/oval/input:
1474:  github.com/fleetdm/fleet/v4/server/vulnerabilities/oval/parsed:
1475:  �[32m✓�[0m Dpkg info test eval no host list (0.00s)
1476:  �[32m✓�[0m Dpkg info test eval no host list # eval (0.00s)
1477:  �[32m✓�[0m Dpkg info test eval no host list # eval test matches n objects (0.00s)
1478:  �[32m✓�[0m Dpkg info test eval no host list # eval test matches n states (0.00s)
1479:  �[32m✓�[0m Dpkg info test eval no host list # eval with no packages (0.00s)
1480:  �[32m✓�[0m Eval (0.00s)
1481:  �[32m✓�[0m Eval alt pattern match (0.00s)
1482:  �[32m✓�[0m Eval equal (0.00s)
1483:  �[32m✓�[0m Eval greater than (0.00s)
1484:  �[32m✓�[0m Eval higher version fails pattern match (0.00s)
1485:  �[32m✓�[0m Eval kernel (0.00s)
1486:  �[32m✓�[0m Eval less than (0.00s)
1487:  �[32m✓�[0m Eval lower version fails pattern match (0.00s)
1488:  �[32m✓�[0m Eval suffix doesn't match (0.00s)
...

1500:  �[32m✓�[0m Object info state # eval OS version name (0.00s)
1501:  �[32m✓�[0m Object info state # eval OS version version (0.00s)
1502:  �[32m✓�[0m Object info state # eval software (0.00s)
1503:  �[32m✓�[0m Object info state # eval software arch (0.00s)
1504:  �[32m✓�[0m Object info state # eval software evr (0.00s)
1505:  �[32m✓�[0m Object info state # eval software name (0.00s)
1506:  �[32m✓�[0m Object info state # eval software release (0.00s)
1507:  �[32m✓�[0m Object info state # eval software signature key id (0.00s)
1508:  �[32m✓�[0m Object info state # eval software version (0.00s)
1509:  �[32m✓�[0m Object match type (0.00s)
1510:  �[32m✓�[0m Object match type # eval (0.00s)
1511:  �[32m✓�[0m Object match type new object match type (0.00s)
1512:  �[32m✓�[0m Object state evr string (0.00s)
1513:  �[32m✓�[0m Object state evr string # eval (0.00s)
1514:  �[32m✓�[0m Object state evr string # eval evaluates an evr string (0.00s)
1515:  �[32m✓�[0m Object state evr string # eval it errors out if operation can not be computed (0.00s)
1516:  �[32m✓�[0m Object state simple value (0.00s)
1517:  �[32m✓�[0m Object state simple value # eval (0.00s)
1518:  �[32m✓�[0m Object state simple value # eval compares simple data types (0.00s)
1519:  �[32m✓�[0m Object state simple value # eval compares simple data types booleans (0.00s)
1520:  �[32m✓�[0m Object state simple value # eval compares simple data types floats (0.00s)
1521:  �[32m✓�[0m Object state simple value # eval compares simple data types ints (0.00s)
1522:  �[32m✓�[0m Object state simple value # eval compares simple data types strings (0.00s)
1523:  �[32m✓�[0m Object state simple value # eval it errors out if complex type used (0.00s)
1524:  �[32m✓�[0m Object state simple value #unpack (0.00s)
1525:  �[32m✓�[0m Object state simple value new object state simple value (0.00s)
1526:  �[32m✓�[0m Object state string (0.00s)
1527:  �[32m✓�[0m Object state string # eval (0.00s)
1528:  �[32m✓�[0m Object state string # eval it errors out if operation can not be computed (0.00s)
1529:  �[32m✓�[0m Object state string # eval it errors out if regexp can not be parsed (0.00s)
1530:  �[32m✓�[0m Object state string # eval it evaluates string values (0.00s)
...

1561:  �[32m✓�[0m Version parts (0.00s)
1562:  �[32m✓�[0m Vulns delta (0.00s)
1563:  �[32m✓�[0m Vulns delta existing differ from found (0.00s)
1564:  �[32m✓�[0m Vulns delta existing match found (0.00s)
1565:  �[32m✓�[0m Vulns delta no existing vulnerabilities (0.00s)
1566:  �[32m✓�[0m Vulns delta nothing found but vulns exist (0.00s)
1567:  github.com/fleetdm/fleet/v4/server/vulnerabilities/macoffice:
1568:  �[32m✓�[0m Analyzer (0.00s)
1569:  �[32m✓�[0m Analyzer analyze (0.00s)
1570:  �[32m✓�[0m Analyzer analyze when no release notes on path (0.00s)
1571:  �[32m✓�[0m Analyzer analyze when release notes contain no valid security updates (0.00s)
1572:  �[32m✓�[0m Analyzer analyze when using wrong path (0.00s)
1573:  �[32m✓�[0m Analyzer collect vulnerabilities (0.00s)
1574:  �[32m✓�[0m Analyzer collect vulnerabilities no release notes (0.00s)
1575:  �[32m✓�[0m Analyzer get stored vulnerabilities (0.00s)
1576:  �[32m✓�[0m Analyzer get stored vulnerabilities on error (0.00s)
1577:  �[32m✓�[0m Analyzer latest release notes (0.00s)
1578:  �[32m✓�[0m Analyzer latest release notes returns release notes in order (0.00s)
1579:  �[32m✓�[0m Analyzer latest release notes when the JSON file is invalid (0.00s)
1580:  �[32m✓�[0m Analyzer latest release notes when vuln path does not exists (0.00s)
1581:  �[32m✓�[0m Analyzer latest release notes when vuln path exists (0.00s)
1582:  �[32m✓�[0m Analyzer update vulns in DB (0.00s)
1583:  �[32m✓�[0m Analyzer update vulns in DB on error when deleting vulns (0.00s)
1584:  �[32m✓�[0m Analyzer update vulns in DB on error when inserting vulns (0.00s)
1585:  �[32m✓�[0m Build number (0.00s)
...

1591:  �[32m✓�[0m Integrations parse release HTML (0.91s)
1592:  �[32m✓�[0m Integrations parse release HTML should parse dates (0.00s)
1593:  �[32m✓�[0m Integrations parse release HTML should parse release versions (0.00s)
1594:  �[32m✓�[0m Integrations parse release HTML should parse security updates (0.01s)
1595:  �[31m✖�[0m Integrations sync (1.01s)
1596:  �[32m✓�[0m Release note (0.00s)
1597:  �[32m✓�[0m Release note # cmp version (0.00s)
1598:  �[32m✓�[0m Release note # cmp version when release version is newer than (0.00s)
1599:  �[32m✓�[0m Release note # cmp version when release version is older than (0.00s)
1600:  �[32m✓�[0m Release note # cmp version when the same (0.00s)
1601:  �[32m✓�[0m Release note # collect vulnerabilities (0.00s)
1602:  �[32m✓�[0m Release note # office product from bundle id (0.00s)
1603:  �[32m✓�[0m Short version format (0.00s)
1604:  �[32m✓�[0m Sync (0.00s)
1605:  �[32m✓�[0m Sync #sync (0.00s)
1606:  �[32m✓�[0m Sync #sync on FS error (0.00s)
1607:  �[32m✓�[0m Sync #sync on GH error (0.00s)
1608:  �[32m✓�[0m Sync #sync on error when deleting (0.00s)
1609:  �[32m✓�[0m Sync #sync on error when downloading GH asset (0.00s)
1610:  �[32m✓�[0m Sync #sync removes multiple out of date copies (0.00s)
...

1613:  �[32m✓�[0m Sync #sync when nothing published on GH (0.00s)
1614:  �[32m✓�[0m Sync #sync when there are no local files (0.00s)
1615:  �[32m✓�[0m Sync #sync when there are no remote rel notes (0.00s)
1616:  github.com/fleetdm/fleet/v4/server/vulnerabilities/oval:
1617:  �[32m✓�[0m Oval analyzer (0.00s)
1618:  �[32m✓�[0m Oval analyzer #load (0.00s)
1619:  �[32m✓�[0m Oval analyzer #load invalid vuln path (0.00s)
1620:  �[32m✓�[0m Oval analyzer #load rejects empty definition file (0.00s)
1621:  �[32m✓�[0m Oval analyzer analyzing RHEL software (11.70s)
1622:  �[32m✓�[0m Oval analyzer analyzing ubuntu software (7.45s)
1623:  �[32m✓�[0m Oval download definitions matching host info (0.00s)
1624:  �[32m✓�[0m Oval download definitions platform not found (0.00s)
1625:  �[32m✓�[0m Oval mapper (0.00s)
1626:  �[32m✓�[0m Oval mapper #extract id (0.00s)
1627:  �[32m✓�[0m Oval mapper #map criteria (0.00s)
1628:  �[32m✓�[0m Oval mapper #map criteria errors out if id can not be parsed on any criterion (0.00s)
1629:  �[32m✓�[0m Oval mapper #map criteria errors out if no criteriums or nested criterias (0.00s)
1630:  �[32m✓�[0m Oval mapper #map criteria maps criteriums (0.00s)
1631:  �[32m✓�[0m Oval mapper #map criteria maps nested criterias (0.00s)
1632:  �[32m✓�[0m Oval mapper #map definition (0.00s)
1633:  �[32m✓�[0m Oval mapper #map definition errors out if no vulnerabilities (0.00s)
1634:  �[32m✓�[0m Oval mapper #map dpkg info state (0.00s)
1635:  �[32m✓�[0m Oval mapper #map dpkg info state errors out if one of non-supported state information is provided (0.00s)
1636:  �[32m✓�[0m Oval mapper #map dpkg info test (0.00s)
1637:  �[32m✓�[0m Oval mapper #map dpkg info test errors out if id can not be parsed (0.00s)
1638:  �[32m✓�[0m Oval mapper #map dpkg info test maps a dpkg info test XML (0.00s)
1639:  �[32m✓�[0m Oval mapper #map package info test object (0.00s)
1640:  �[32m✓�[0m Oval mapper #map package info test object name defined in var ref (0.00s)
1641:  �[32m✓�[0m Oval mapper #map package info test object name defined inline (0.00s)
1642:  �[32m✓�[0m Oval mapper #map package info test object name not defined inline nor using a variable ref (0.00s)
1643:  �[32m✓�[0m Oval mapper #map rpm info state (0.00s)
1644:  �[32m✓�[0m Oval mapper #map rpm info state errors out if not supported state is provided (0.00s)
1645:  �[32m✓�[0m Oval mapper #map rpm info state maps a rpm info state XML (0.00s)
1646:  �[32m✓�[0m Oval mapper #map rpm info state maps the operator, if any (0.00s)
1647:  �[32m✓�[0m Oval mapper #map rpm info test (0.00s)
1648:  �[32m✓�[0m Oval mapper #map rpm info test errors out if id can not be parsed (0.00s)
1649:  �[32m✓�[0m Oval mapper #map rpm info test maps a rpm info test XML (0.00s)
1650:  �[32m✓�[0m Oval mapper #map rpm verify file object (0.00s)
1651:  �[32m✓�[0m Oval mapper #map rpm verify file object errors out if invalid children provided (0.00s)
1652:  �[32m✓�[0m Oval mapper #map rpm verify file object maps to a filepath (0.00s)
1653:  �[32m✓�[0m Oval mapper #map rpm verify file state (0.00s)
1654:  �[32m✓�[0m Oval mapper #map rpm verify file state errors out if not supported state is provided (0.00s)
1655:  �[32m✓�[0m Oval mapper #map rpm verify file state maps a rpm verify file state XML (0.00s)
...

1737:  �[32m✓�[0m Integration check version unknown version returns no vulnerabilities (0.00s)
1738:  �[32m✓�[0m Integration check version version not in bulletin returns empty (0.00s)
1739:  �[32m✓�[0m Parse office version (0.00s)
1740:  �[32m✓�[0m Parse office version invalid version - no prefix (0.00s)
1741:  �[32m✓�[0m Parse office version invalid version - too few parts (0.00s)
1742:  �[32m✓�[0m Parse office version invalid version - wrong prefix (0.00s)
1743:  �[32m✓�[0m Parse office version valid version (0.00s)
1744:  �[32m✓�[0m Parse security markdown (0.00s)
1745:  �[32m✓�[0m Parse security markdown keeps minimum build suffix for same version (0.00s)
1746:  �[32m✓�[0m Parse security markdown parses LTSC versions (0.00s)
1747:  �[32m✓�[0m Parse security markdown parses multiple releases (0.00s)
1748:  �[32m✓�[0m Parse security markdown parses single release with multiple versions (0.00s)
1749:  �[32m✓�[0m Parse security markdown skips releases without CVEs (0.00s)
1750:  �[32m✓�[0m Parse security markdown skips retail versions (0.00s)
1751:  �[32m✓�[0m Sync bulletin (0.00s)
1752:  �[32m✓�[0m Sync bulletin on FS error (0.00s)
1753:  �[32m✓�[0m Sync bulletin on GH error (0.00s)
1754:  �[32m✓�[0m Sync bulletin on error when deleting (0.00s)
1755:  �[32m✓�[0m Sync bulletin on error when downloading GH asset (0.00s)
1756:  �[32m✓�[0m Sync bulletin removes multiple out of date copies (0.00s)
...

1883:  �[32m✓�[0m FS client (0.00s)
1884:  �[32m✓�[0m FS client #MSRC bulletins (0.00s)
1885:  �[32m✓�[0m FS client #MSRC bulletins directory does not exists (0.00s)
1886:  �[32m✓�[0m FS client #MSRC bulletins returns a list of file matching the MSRC file prefix (0.00s)
1887:  �[32m✓�[0m FS client delete (0.00s)
1888:  �[32m✓�[0m FS client delete file does not exists (0.00s)
1889:  �[32m✓�[0m FS client mac office release notes (0.00s)
1890:  �[32m✓�[0m FS client mac office release notes directory does not exists (0.00s)
1891:  �[32m✓�[0m FS client mac office release notes returns a list of file matching the mac office file prefix (0.00s)
1892:  �[32m✓�[0m FS client mac office release notes when files contain the wrong date format (0.00s)
1893:  �[32m✓�[0m Integrations github client (270.45s)
1894:  �[32m✓�[0m Integrations github client # download (270.45s)
1895:  �[32m✓�[0m Integrations github client # download with invalid URL (270.45s)
1896:  �[32m✓�[0m Integrations github client #MSRC bulletins (0.00s)
1897:  �[32m✓�[0m Integrations github client mac office release notes (0.00s)
1898:  �[32m✓�[0m Integrations github client mac office release notes on error (0.00s)
1899:  �[32m✓�[0m Integrations github client mac office release notes with HTTP error code (0.00s)
1900:  �[32m✓�[0m Integrations github client mac office release notes with a single release note asset (0.00s)
...

1907:  �[32m✓�[0m Security bulletin name # before when b is empty (0.00s)
1908:  �[32m✓�[0m Security bulletin name # product name (0.00s)
1909:  �[32m✓�[0m Security bulletin name #date (0.00s)
1910:  �[32m✓�[0m Security bulletin name MSRC file name (0.00s)
1911:  �[32m✓�[0m Security bulletin name date not included in filename (0.00s)
1912:  �[32m✓�[0m Security bulletin name mac office rel notes file name (0.00s)
1913:  �[32m✓�[0m Security bulletin name product name not included in filename (0.00s)
1914:  �[32m✓�[0m Security bulletin name string (0.00s)
1915:  �[32m✓�[0m Security bulletin name validates timestamp on filename at construction time (0.00s)
1916:  �[32m✓�[0m Security bulletin name win office file name (0.00s)
1917:  === �[33mSkipped�[0m
1918:  === �[33mSKIP�[0m: server/vulnerabilities/nvd/tools/providers/nvd TestEndToEnd (0.00s)
1919:  e2e_test.go:45: e2e tests not enabled
1920:  === �[33mSKIP�[0m: server/vulnerabilities/vulntest TestGenerateVulnFixtures (0.00s)
1921:  gen_fixture_test.go:123: set GENERATE_FIXTURES=1 to run this test
1922:  === �[31mFailed�[0m
1923:  === �[31mFAIL�[0m: server/vulnerabilities/macoffice TestIntegrationsSync (1.01s)
1924:  nettest.go:33: network test start: TestIntegrationsSync
1925:  integration_sync_test.go:39: 
1926:  Error Trace:	/home/runner/work/fleet/fleet/server/vulnerabilities/macoffice/integration_sync_test.go:39
1927:  Error:      	Condition failed!
1928:  Test:       	TestIntegrationsSync
1929:  Messages:   	Expected to find one of [fleet_macoffice_release_notes_macoffice-2026_06_29.json fleet_macoffice_release_notes_macoffice-2026_06_28.json fleet_macoffice_release_notes_macoffice-2026_06_27.json fleet_macoffice_release_notes_macoffice-2026_06_26.json fleet_macoffice_release_notes_macoffice-2026_06_25.json fleet_macoffice_release_notes_macoffice-2026_06_24.json fleet_macoffice_release_notes_macoffice-2026_06_23.json] in /tmp/TestIntegrationsSync494832307/001
1930:  nettest.go:36: network test done: TestIntegrationsSync
1931:  DONE 832 tests, 2 skipped, 1 failure in 271.757s
1932:  make[1]: *** [Makefile:291: .run-go-tests] Error 1
1933:  make[1]: Leaving directory '/home/runner/work/fleet/fleet'
1934:  make: *** [Makefile:406: test-go] Error 2
1935:  ##[error]Process completed with exit code 2.
1936:  Node 20 is being deprecated. This workflow is running with Node 24 by default. If you need to temporarily use Node 20, you can set the ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true environment variable. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
1937:  ##[group]Run actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a
1938:  with:
1939:  name: vuln-mysql8.0.44-coverage
1940:  path: ./coverage.txt
1941:  if-no-files-found: error
1942:  compression-level: 6
...

1945:  RACE_ENABLED: false
1946:  GO_TEST_TIMEOUT: 20m
1947:  DOCKER_COMMAND: docker compose -f docker-compose.yml -f docker-compose-redis-cluster.yml up -d mysql_test mysql_replica_test redis redis-cluster-1 redis-cluster-2 redis-cluster-3 redis-cluster-4 redis-cluster-5 redis-cluster-6 redis-cluster-setup s3 saml_idp mailhog mailpit smtp4dev_test
1948:  RUN_TESTS_ARG: 
1949:  CI_TEST_PKG: vuln
1950:  NEED_DOCKER: 1
1951:  ARTIFACT_PREFIX: vuln-mysql8.0.44
1952:  GOTOOLCHAIN: local
1953:  ##[endgroup]
1954:  (node:21271) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
1955:  (Use `node --trace-deprecation ...` to show where the warning was created)
1956:  With the provided path, there will be 1 file uploaded
1957:  Artifact name is valid!
1958:  Root directory input is valid!
1959:  Beginning upload of artifact content to blob storage
1960:  (node:21271) [DEP0169] DeprecationWarning: `url.parse()` behavior is not standardized and prone to errors that have security implications. Use the WHATWG URL API instead. CVEs are not issued for `url.parse()` vulnerabilities.
1961:  Uploaded bytes 2042906
1962:  Finished uploading artifact content to blob storage!
1963:  SHA256 hash of uploaded artifact zip is 6402eb0ccc7ac7f3c57737b5a382e77022f1e8a0d9b26d4895bf7199aeec476c
1964:  Finalizing artifact upload
1965:  Artifact vuln-mysql8.0.44-coverage.zip successfully finalized. Artifact ID 7955643114
1966:  Artifact vuln-mysql8.0.44-coverage has been successfully uploaded! Final size is 2042906 bytes. Artifact ID is 7955643114
1967:  Artifact download URL: https://github.com/fleetdm/fleet/actions/runs/28380721746/artifacts/7955643114
1968:  ##[group]Run c1grep() { grep "$@" || test $? = 1; }
1969:  �[36;1mc1grep() { grep "$@" || test $? = 1; }�[0m
1970:  �[36;1mc1grep -oP 'FAIL: .*$' /tmp/gotest.log > /tmp/summary.txt�[0m
1971:  �[36;1mc1grep 'test timed out after' /tmp/gotest.log >> /tmp/summary.txt�[0m
1972:  �[36;1mc1grep 'fatal error:' /tmp/gotest.log >> /tmp/summary.txt�[0m
1973:  �[36;1mc1grep -A 10 'panic: runtime error: ' /tmp/gotest.log >> /tmp/summary.txt�[0m
1974:  �[36;1mc1grep ' FAIL\t' /tmp/gotest.log >> /tmp/summary.txt�[0m
1975:  �[36;1mGO_FAIL_SUMMARY=$(head -n 5 /tmp/summary.txt | sed ':a;N;$!ba;s/\n/\\n/g')�[0m
1976:  �[36;1mecho "GO_FAIL_SUMMARY=$GO_FAIL_SUMMARY"�[0m
1977:  �[36;1mif [[ -z "$GO_FAIL_SUMMARY" ]]; then�[0m
1978:  �[36;1m  GO_FAIL_SUMMARY="unknown, please check the build URL"�[0m
1979:  �[36;1mfi�[0m
1980:  �[36;1mGO_FAIL_SUMMARY=$GO_FAIL_SUMMARY envsubst < .github/workflows/config/slack_payload_template.json > ./payload.json�[0m
1981:  shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
1982:  env:
1983:  RACE_ENABLED: false
1984:  GO_TEST_TIMEOUT: 20m
1985:  DOCKER_COMMAND: docker compose -f docker-compose.yml -f docker-compose-redis-cluster.yml up -d mysql_test mysql_replica_test redis redis-cluster-1 redis-cluster-2 redis-cluster-3 redis-cluster-4 redis-cluster-5 redis-cluster-6 redis-cluster-setup s3 saml_idp mailhog mailpit smtp4dev_test
1986:  RUN_TESTS_ARG: 
1987:  CI_TEST_PKG: vuln
1988:  NEED_DOCKER: 1
1989:  ARTIFACT_PREFIX: vuln-mysql8.0.44
1990:  GOTOOLCHAIN: local
1991:  ##[endgroup]
1992:  GO_FAIL_SUMMARY=
1993:  Node 20 is being deprecated. This workflow is running with Node 24 by default. If you need to temporarily use Node 20, you can set the ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true environment variable. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
1994:  ##[group]Run actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a
1995:  with:
1996:  name: vuln-mysql8.0.44-test-log
1997:  path: /tmp/gotest.log
1998:  if-no-files-found: error
1999:  compression-level: 6
...

2002:  RACE_ENABLED: false
2003:  GO_TEST_TIMEOUT: 20m
2004:  DOCKER_COMMAND: docker compose -f docker-compose.yml -f docker-compose-redis-cluster.yml up -d mysql_test mysql_replica_test redis redis-cluster-1 redis-cluster-2 redis-cluster-3 redis-cluster-4 redis-cluster-5 redis-cluster-6 redis-cluster-setup s3 saml_idp mailhog mailpit smtp4dev_test
2005:  RUN_TESTS_ARG: 
2006:  CI_TEST_PKG: vuln
2007:  NEED_DOCKER: 1
2008:  ARTIFACT_PREFIX: vuln-mysql8.0.44
2009:  GOTOOLCHAIN: local
2010:  ##[endgroup]
2011:  (node:21293) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
2012:  (Use `node --trace-deprecation ...` to show where the warning was created)
2013:  With the provided path, there will be 1 file uploaded
2014:  Artifact name is valid!
2015:  Root directory input is valid!
2016:  Beginning upload of artifact content to blob storage
2017:  (node:21293) [DEP0169] DeprecationWarning: `url.parse()` behavior is not standardized and prone to errors that have security implications. Use the WHATWG URL API instead. CVEs are not issued for `url.parse()` vulnerabilities.
2018:  Uploaded bytes 9186
...

2034:  RACE_ENABLED: false
2035:  GO_TEST_TIMEOUT: 20m
2036:  DOCKER_COMMAND: docker compose -f docker-compose.yml -f docker-compose-redis-cluster.yml up -d mysql_test mysql_replica_test redis redis-cluster-1 redis-cluster-2 redis-cluster-3 redis-cluster-4 redis-cluster-5 redis-cluster-6 redis-cluster-setup s3 saml_idp mailhog mailpit smtp4dev_test
2037:  RUN_TESTS_ARG: 
2038:  CI_TEST_PKG: vuln
2039:  NEED_DOCKER: 1
2040:  ARTIFACT_PREFIX: vuln-mysql8.0.44
2041:  GOTOOLCHAIN: local
2042:  ##[endgroup]
2043:  (node:21305) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
2044:  (Use `node --trace-deprecation ...` to show where the warning was created)
2045:  With the provided path, there will be 1 file uploaded
2046:  Artifact name is valid!
2047:  Root directory input is valid!
2048:  Beginning upload of artifact content to blob storage
2049:  (node:21305) [DEP0169] DeprecationWarning: `url.parse()` behavior is not standardized and prone to errors that have security implications. Use the WHATWG URL API instead. CVEs are not issued for `url.parse()` vulnerabilities.
2050:  Uploaded bytes 138
...

2066:  RACE_ENABLED: false
2067:  GO_TEST_TIMEOUT: 20m
2068:  DOCKER_COMMAND: docker compose -f docker-compose.yml -f docker-compose-redis-cluster.yml up -d mysql_test mysql_replica_test redis redis-cluster-1 redis-cluster-2 redis-cluster-3 redis-cluster-4 redis-cluster-5 redis-cluster-6 redis-cluster-setup s3 saml_idp mailhog mailpit smtp4dev_test
2069:  RUN_TESTS_ARG: 
2070:  CI_TEST_PKG: vuln
2071:  NEED_DOCKER: 1
2072:  ARTIFACT_PREFIX: vuln-mysql8.0.44
2073:  GOTOOLCHAIN: local
2074:  ##[endgroup]
2075:  (node:21318) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
2076:  (Use `node --trace-deprecation ...` to show where the warning was created)
2077:  With the provided path, there will be 1 file uploaded
2078:  Artifact name is valid!
2079:  Root directory input is valid!
2080:  Beginning upload of artifact content to blob storage
2081:  (node:21318) [DEP0169] DeprecationWarning: `url.parse()` behavior is not standardized and prone to errors that have security implications. Use the WHATWG URL API instead. CVEs are not issued for `url.parse()` vulnerabilities.
2082:  Uploaded bytes 57355
...

2115:  RACE_ENABLED: false
2116:  GO_TEST_TIMEOUT: 20m
2117:  DOCKER_COMMAND: docker compose -f docker-compose.yml -f docker-compose-redis-cluster.yml up -d mysql_test mysql_replica_test redis redis-cluster-1 redis-cluster-2 redis-cluster-3 redis-cluster-4 redis-cluster-5 redis-cluster-6 redis-cluster-setup s3 saml_idp mailhog mailpit smtp4dev_test
2118:  RUN_TESTS_ARG: 
2119:  CI_TEST_PKG: vuln
2120:  NEED_DOCKER: 1
2121:  ARTIFACT_PREFIX: vuln-mysql8.0.44
2122:  GOTOOLCHAIN: local
2123:  ##[endgroup]
2124:  (node:21331) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
2125:  (Use `node --trace-deprecation ...` to show where the warning was created)
2126:  With the provided path, there will be 1 file uploaded
2127:  Artifact name is valid!
2128:  Root directory input is valid!
2129:  Beginning upload of artifact content to blob storage
2130:  (node:21331) [DEP0169] DeprecationWarning: `url.parse()` behavior is not standardized and prone to errors that have security implications. Use the WHATWG URL API instead. CVEs are not issued for `url.parse()` vulnerabilities.
2131:  Uploaded bytes 133

@georgekarrv georgekarrv merged commit 065a52c into main Jun 29, 2026
38 of 40 checks passed
@georgekarrv georgekarrv deleted the gkarr-23242-fe branch June 29, 2026 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants