Release note · August 4, 2026

A timestamp declaration needs its shape

By SybilGambleyyu · DocFence 0.47.0

An OPC package signature carries a claimed signing time in a very specific place. Once a static review tool treats the package-specific Object as the carrier of coverage declarations, it should not treat a malformed, unrelated, or internally inconsistent time property as if that carrier were conforming. The timestamp is not proof of time or trust—but its stored structure is part of the standard declaration.

Correction, August 4, 2026: 0.47 established the required timestamp-property shape, but it did not yet validate the XMLDSIG child order and transform boundary of the SignedInfo Reference binding the package Object. DocFence 0.48 closes that separate declaration gap before static coverage is credited.

One fixed property below the package object

The current ECMA-376 Part 2 rules require a SignatureProperty below the OPC-specific Object to use the fixed idSignatureTime ID, point either nowhere or to the root Signature ID, and contain a SignatureTime element and no other elements. The accompanying official schema bundle fixes SignatureTime to an ordered Format/Value pair.

ds:Object Id="idPackageObject"
  └─ ds:SignatureProperties
       └─ ds:SignatureProperty
            Id="idSignatureTime"
            Target="" or "#<root Signature Id>"
            └─ opc:SignatureTime
                 ├─ opc:Format
                 └─ opc:Value

DocFence 0.47 accepts coverage only after that direct shape holds: one property, no unexpected attributes, an empty or exact root-signature fragment target, one attribute-free SignatureTime child, then attribute-free Format and Value leaves. It recognizes every OPC schema precision—year, month, date, minute, second, and one decimal-second digit—and requires the stored Value to match the declared Format.

Fail closed on a malformed claim

A missing timestamp property, a different ID, an absent or misdirected target, duplicate properties, unexpected attributes or children, an unknown Format, or a Value that does not match its Format now leaves static package coverage unavailable. No Manifest references are combined or partly credited after that failure.

This is intentionally narrow. DocFence does not decide whether a claimed time is accurate, validate a timestamp authority, recompute a digest, execute a transform, verify XMLDSIG, inspect a certificate, establish trust, or predict an Office client. It recognizes the stored OPC declaration it is prepared to report—and says no more.

version: 1
rules:
  require_complete_package_signature_coverage: true
  no_package_signature_coverage_changes: true

DFP092 and DFP093 therefore remain bounded review controls. They are useful precisely because they do not recast a static declaration check as a security verdict.

Compatibility was part of the change

The 68-test suite now exercises all six accepted time formats and the permitted empty Target form, alongside missing, duplicate, misidentified, mis-targeted, attribute-bearing, missing-child, extra-child, nonstandard-format, and format/value-mismatched declarations. DCAB’s full adapter suite also passed against a fresh DocFence wheel.

A signed baseline from the public OOXML Signature Security artifacts retained its complete bounded declaration: six Word parts, one root-document relationship, and five Word relationships. The published content-injection, universal-signature-forgery, duplicate-document, and evil-type variants still expose uncovered or unavailable declaration surfaces. This tests stored compatibility only; it is not a trust or safety verdict about any sample.

Main and tagged CI both passed. Wheel and source archives were independently rebuilt under the commit timestamp and matched byte-for-byte; fresh wheel and source installations profiled the signed baseline, and the public GitHub release downloads were byte-compared with those verified artifacts.

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

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

The tagged policy reference, threat model, and validation notes define the exact boundary. Useful static review is not about making every package look trustworthy; it is about refusing to call a declaration complete when its required structure is not there.