Skip to content

No guardrail against string-editing post_content — silently corrupts block attributes #22

Description

@Schmandarine

The problem

An agent driving a brmbh theme will sooner or later change a field value on a live page — swap an image ID, fix a typo, reorder a repeater. Nothing in the suite tells it how, so the obvious approach is to treat post_content as a string and str_replace the bit that changes.

That silently corrupts every escape in the block it touches, and there is no guardrail, no verify step, and no error.

Why it corrupts

An ACF block stores its whole field set as JSON inside an HTML comment:

<!-- wp:acf/events-grid {"name":"acf/events-grid","data":{"events_0_body":"…Main &\r\nProf. Dr. …"}} /-->

So serialize_block_attributes() (wp-includes/blocks.php) hex-escapes anything that could break out of that comment — &&, </>, -- (would end the comment), \" — plus \r\n for newlines typed into a textarea field.

Strip one backslash level and every escape degrades into literal on-page text:

Stored Means After the strip
& & u0026
\r\n newline rn
< / > < / > u003c / u003e

The usual culprit is the write, not the read: wp_update_post() and wp_insert_post() call wp_unslash() on their input (magic-quotes-era legacy — they expect raw $_POST). Hand them clean content and a backslash level dies. Shell round-trips (--post_content="$(…)", heredocs, sed, jq) do the same.

Nothing warns you. u0026 is still valid JSON, just the wrong string. parse_blocks() parses it, ACF returns it, the template prints it. No checksum, no validation.

It already happened

On a client site built with this theme (Megaherz / Alfasigma), a one-line event-thumbnail image-ID swap corrupted the acf/events-grid block on 2026-07-30. Pinned to a 28-minute window by revision history: rev 259 (11:35:54) clean, rev 264 (12:03:41) corrupt. It shipped to production the same day via db push and the client found it six weeks later, in a PDF review.

The follow-on damage was worse than the bug: someone then hand-deleted the junk tokens in the ACF field, which destroyed the original & and the line breaks outright, with nothing left on the page to show anything had ever been there.

Proposed fix (docs + skill, no code)

  1. New /edit-block-content skill in packages/cli/AGENTS/ — snapshot → parse_blocks() → modify → serialize_blocks()wp_slash() → verify → diff, plus recovery steps for already-corrupted content.
  2. Hard rule in AGENTS.md (operating contract + What NOT to do).
  3. Hard rule in skills/wordpress/SKILL.md, so it ships via npx skills add brmbh/wordpress.

The verify step is the part that actually prevents recurrence — a rule an agent can check beats one it can only remember:

wp post get <ID> --field=content | grep -oE '[^\\]u00[0-9a-f]{2}|[a-zäöüß]rn[A-ZÄÖÜ]'   # must print nothing

Out of scope

A doctor check that scans all posts for these artifacts would catch existing damage across a site — worth a separate issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    agenticAgent-facing surfaceblocksACF block factorybugSomething isn't workingdocumentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions