Release note · August 1, 2026

The anchors behind Word's embedded controls

By SybilGambleyyu · DocFence 0.26.0

“This Word package contains ActiveX parts” and “this document has a direct control anchor” are different review facts. A package-level relationship or payload count can reveal stored persistence material, but it cannot say where a document records the markup that represents an embedded control. Conversely, a direct marker is not proof that a client has a control installed, will load its persistence data, or will permit active content.

DocFence 0.26 adds a narrow, privacy-safe inventory for that direct WordprocessingML surface: w:control only when it is a direct child of w:object or w:pict. It gives document CI a stable review signal for the stored anchor without uploading package material or pretending a parser can forecast Word runtime behavior.

Two standardized anchor positions

The Open XML SDK documents w:control as Office 2007+ markup with two Word parents: w:object for an embedded control and w:pict for a floating embedded control. The ISO 29500 schema definitions make the shape precise: r:id is optional on CT_Control, while both parent containers permit a control child.

That direct parent relationship is the important boundary. DocFence records every matching direct child in supported body, header, footer, footnote, endnote, comment, and glossary stories. Duplicates and Markup Compatibility branches remain separate stored evidence. An arbitrary w:control elsewhere does not become an anchor merely because it has the same local name.

The element contract says that a supplied r:id must identify a control relationship. The OOXML Embedded Control Persistence Part contract requires that relationship to have an internal target. The inventory therefore reports a standard control relationship with an internal target, a separately reviewable external standard relationship (stored but nonconforming), an unsupported relationship, or an anchor with no r:id. Those are descriptions of package state, not labels for a usable, safe, or active control.

Direct markup is complementary to package evidence

The release deliberately leaves generic embedded-control relationship and payload totals intact. It does not fold in arbitrary w:control markup, w:objectLink, w:objectEmbed, VML image or linked-OLE markup, fields, or ActiveX-control-binary relationships. A generic relationship can also be orphaned from a visible document marker; a direct anchor can have no relationship ID. Those are exactly the cases a single total erases.

The two inventories can look very different on the same real package. In docx4j’s public LegacyForms.docx fixture, the installed release reports five direct anchors, all under w:object in the main document and all with internal standard control relationships. The existing broader inventory reports ten recognized control relationships and ten control parts. Neither number is a substitute for the other.

Private semantics, concrete gates

JSON, Markdown, and SARIF expose aggregate anchor, story, direct-parent, and relationship-classification counts only. Control names and shape identifiers, relationship IDs and targets, XML markup, story paths, and fingerprints remain private. The complete direct marker is privately fingerprinted, so a same-count name, shape, or target rewrite stays review-visible while relationship-ID renumbering with unchanged relationship semantics stays quiet.

A handoff that must carry no direct embedded-control anchor can state that policy directly:

rules:
  require_no_word_embedded_controls: true

That candidate-state gate emits DFP065. A controlled template that deliberately retains approved anchors can protect its private baseline instead:

rules:
  no_word_embedded_control_changes: true

DFP066 detects a material private-inventory change. These gates complement the broader embedded-object rule; they do not replace checks for orphaned relationships or stored payloads.

Evidence, including what it cannot show

The 52-test release suite covers both direct parents, internal and external standard relationships, unsupported and unavailable relationships, optional IDs, duplicates, body/header stories, Transitional and Strict namespaces, orphan and unparented-marker exclusion, target and marker-name rewrites, relationship-ID stability, privacy redaction, and JSON/Markdown/SARIF policy output. Hosted CI passed on Python 3.11 and 3.13 for both the release commit and the tag. The wheel and source archive were independently rebuilt from the tag with a fixed source date and matched byte-for-byte; fresh public downloads passed checksum verification, and an isolated installed wheel profiled the public fixture with the expected aggregate contract.

The public corpus evidence is intentionally limited. A scan of 141 Word packages in the cited docx4j tree found one positive package: LegacyForms.docx. A separate scan of 503 readable Open XML SDK candidate packages found no direct w:control marker (two of 505 candidates produced read errors). This is evidence for a standards-shaped stored-XML boundary and a useful real fixture—not a claim about how commonly contemporary Word authors create these controls or how clients will interoperate with them.

DocFence does not resolve, retrieve, instantiate, load, activate, evaluate, render, or execute a control. It does not establish that Word will select a Markup Compatibility branch, associate a marker with a visual object, have a compatible control installed, permit active content, or honor the markup. Use it as a bounded local review signal alongside rendering, security, and domain-specific review.

python -m pip install https://github.com/SybilGambleyyu/docfence/releases/download/v0.26.0/docfence-0.26.0-py3-none-any.whl

docfence profile candidate.docx --format markdown
docfence check approved.docx candidate.docx --policy docfence.yml --format sarif --output docfence.sarif

The public release includes the wheel, source archive, and SHA-256 manifest. The tagged policy reference, threat model, and validation notes define the exact behavior, privacy contract, and limits.