From c686f574febb347c2a8f0b29fc9e146cf5780574 Mon Sep 17 00:00:00 2001 From: Jordan Montgomery Date: Wed, 10 Jun 2026 17:31:46 -0400 Subject: [PATCH] Make the plist parser slightly more tolerant (#47371) **Related issue:** Resolves # # Checklist for submitter If some of the following don't apply, delete the relevant line. No changes file, already covered - [x] 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. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [x] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually ## Summary by CodeRabbit * **Bug Fixes** * Improved compatibility with multiple Apple plist format versions for more reliable file handling. * Strengthened validation of plist inputs to reduce false positives and improve security. * Adjusted early bounds checking so very short or malformed plist files are handled more robustly. --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- server/mdm/apple/plist_bounds.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/mdm/apple/plist_bounds.go b/server/mdm/apple/plist_bounds.go index fb3330a957..f4f926869e 100644 --- a/server/mdm/apple/plist_bounds.go +++ b/server/mdm/apple/plist_bounds.go @@ -14,7 +14,9 @@ import ( // dictionary of scalar values. const ( // binaryPlistMagic is the prefix that selects the binary plist decoder. - binaryPlistMagic = "bplist00" + // Apple doesn't fully document all versions, but "bplist00" and "bplist01" are known. + // Using "bplist0" lets us accept any "bplist0" version header. + binaryPlistMagic = "bplist0" plistTrailerSize = 32 maxPlistObjects = 1 << 16 // distinct objects (offset-table size) @@ -42,7 +44,8 @@ func BoundedPlistUnmarshal(data []byte, v any) error { // checkBinaryPlistBounds walks a binary plist's object references, rejecting // input that exceeds the limits or points outside the data region. func checkBinaryPlistBounds(data []byte) error { - if len(data) < len(binaryPlistMagic)+plistTrailerSize { + // See comment on binaryPlistMagic above for why the +1 is needed + if len(data) < len(binaryPlistMagic)+1+plistTrailerSize { return fmt.Errorf("%w: shorter than minimum size", errMalformedPlist) }