Skip to content

fix(classic): minimise payload source escaping before the CDATA wrap - #311

Merged
neilmartin83 merged 1 commit into
mainfrom
fix/classic-payload-minimize-escaping
Jul 30, 2026
Merged

fix(classic): minimise payload source escaping before the CDATA wrap#311
neilmartin83 merged 1 commit into
mainfrom
fix/classic-payload-minimize-escaping

Conversation

@neilmartin83

Copy link
Copy Markdown
Member

Follow-up to #310, mirroring Jamf-Concepts/jamfplatform-go-sdk#45.

Problem

The update path re-serialises the plist for UUID injection via howett.net/plist, whose encoding/xml backend escapes quotes, apostrophes, and value newlines/tabs as numeric references (", ', 
). Verbatim-stored payload types preserve the wire representation with zero decodes (PI-827), so those avoidable references surfaced as literal text in stored values — a TCC CodeRequirement updated through the CLI came back as identifier "com..." (breaking the signing requirement) and tripped the post-write verification warning.

Fix

normalizeClassicProfilePayloadsForSend now minimises source escaping before guarding and escaping: every character/entity reference except those encoding & and < is decoded to its literal character. Both representations parse to identical values — only the wire form changes — but the wire form is what verbatim storage preserves. Ordering is load-bearing: the ]]> guard runs after minimising (decoding &gt; can resurrect the terminator).

Side benefit: the unavoidable verbatim-storage corruption shrinks to genuine &/< characters — entity-form >, quotes, and apostrophes in user mobileconfigs now store value-correct on the mobile endpoint and in verbatim macOS payload types, not just in MCX-family payloads.

Verification

Wire-verified live: an entity-free TCC profile survives create and update byte-exact with zero verification warnings — quotes in CodeRequirement stay literal through the howett re-serialisation (previously corrupted on every update). Unit tests cover the minimisation table (decoded vs must-preserve references, unknown entities, bare ampersands, terminator resurrection); full suite green, lint clean.

🤖 Generated with Claude Code

The update path re-serialises the plist for UUID injection via
howett.net/plist, whose encoding/xml backend escapes quotes, apostrophes,
and value newlines/tabs as numeric references. Verbatim-stored payload
types preserve the wire representation with zero decodes (PI-827), so
those avoidable references surfaced as literal text in stored values — a
TCC CodeRequirement updated through the CLI came back as
identifier &#34;com...&#34; and tripped the post-write verification.

normalizeClassicProfilePayloadsForSend now decodes every character
reference except those encoding "&" and "<" before guarding and escaping
(both representations parse to identical values; only the wire form
changes). Side benefit: the unavoidable verbatim-storage corruption
shrinks to genuine "&"/"<" characters — entity-form ">", quotes, and
apostrophes in user files now store value-correct everywhere.

Wire-verified: an entity-free TCC profile now survives create + update
byte-exact with zero verification warnings; quotes in CodeRequirement
stay literal through the howett re-serialisation.

Mirrors jamfplatform-go-sdk#45 (same fix in PayloadsXMLText).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@neilmartin83
neilmartin83 merged commit ead645d into main Jul 30, 2026
1 check passed
@neilmartin83
neilmartin83 deleted the fix/classic-payload-minimize-escaping branch July 30, 2026 16:32
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.

2 participants