DEV Community

SybilGambleyyu
SybilGambleyyu

Posted on Originally published at sybilgambleyyu.github.io

One Word image link can be two stored markers

One Word image link can be two stored markers

“This image has a hyperlink” sounds like one fact. In a Word OOXML package, it
can be more than one stored action marker. That matters in CI: a package
relationship is not enough evidence, and a visible-link count is not the same
thing as the markup stored in the file.

DocFence 0.19.0
adds a privacy-safe inventory for direct DrawingML a:hlinkClick,
a:hlinkHover, and a:hlinkMouseOver markers inside supported Word stories.

A real image has two click markers

LibreOffice’s public
tdf78657_picture_hyperlink.docx regression fixture
is identified by its commit as a Microsoft Word 2016 test file. Its one image
hyperlink relationship is referenced by two stored a:hlinkClick elements:
one on WordprocessingDrawing’s wp:docPr, and another on the picture’s
non-visual properties.

That does not mean a user sees two links. It means the package contains two
action markers. A review tool should preserve that stored evidence rather than
silently deduplicating it into a rendered-link guess. One marker can be changed
or removed while the other remains; that package-level change is precisely what
a controlled review needs to see.

Count the stored action, keep its material private

The inventory reports only aggregate marker/story counts; click/hover/mouse-over
kinds; external/internal/unsupported relationship classes; missing-r:id
markers; and the presence of action and invalidUrl attributes. A package
relationship does not count unless a direct marker references it.

Targets, invalid URLs, action strings, tooltips, frame names, history settings,
relationship IDs, story paths, and fingerprints remain private. The private
signature catches a same-count target or attribute rewrite while a
relationship-ID renumbering with identical resolved semantics remains quiet.

The OOXML a:hlinkClick definition
documents the relationship target and action-related attributes; its
hover counterpart
and the Open XML SDK’s
mouse-over contract
complete the family. DocFence records direct stored elements in supported Word
stories, but does not select a Markup Compatibility branch, resolve a target,
associate markers with a rendered object, validate a URL, or execute an action.

Two policy choices

For a handoff that must carry no stored DrawingML action markup:

rules:
  require_no_word_drawing_hyperlinks: true
Enter fullscreen mode Exit fullscreen mode

This produces DFP051. For a governed template that intentionally retains
image or shape actions:

rules:
  no_word_drawing_hyperlink_changes: true
Enter fullscreen mode Exit fullscreen mode

DFP052 protects the private marker baseline. These rules complement the
generic relationship gate, direct w:hyperlink markup gate, and HYPERLINK
field gate because each represents different stored evidence.

Release evidence

The 0.19 suite has 45 tests. It covers click, hover, and mouse-over kinds;
relationship modes/type mismatch; missing IDs; action and invalid-URL attribute
presence; body/header and Strict encodings; orphaned-relationship exclusion;
same-count target/action mutations; relationship-ID renumbering; policy/SARIF
output; and redaction.

The released wheel profiles the public Word 2016 image fixture and reports two
click markers and two external relationship-backed marker references without
emitting its target. Hosted Python 3.11/3.13 CI, reproducible builds, fresh
release-download checksums, package checks, and an isolated-wheel fixture smoke
test all passed.

python -m pip install https://github.com/SybilGambleyyu/docfence/releases/download/v0.19.0/docfence-0.19.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
Enter fullscreen mode Exit fullscreen mode

The canonical release note
has the detailed evidence, policy reference, and threat-model links.

Top comments (0)