OfficeDev / OfficeDev/Office-Addin-Scripts

Omex manifest signing not reproducible for non-Microsoft add-ins

Open
#1,009 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
194
Forks
117
Avg merge
1d 32m
Merged PRs (30d)
2

Description

Summary

Working Omex add-in manifests shipped with Office LTSC 2024 Mac
contain an XAdES-T (XML Digital Signature with Time Stamp) envelope
signed with CN=Microsoft Corporation Third-Party App Distribution
and a timestamp from CN=Microsoft Time-Stamp Service (nShield
HSM-backed). The cert chain is rooted at CN=Microsoft Root Certificate Authority 2010.

This cert is only issued to Microsoft itself as part of the AppSource
submission pipeline. No third party can obtain a cert with the
Third-Party App Distribution subject.
As a result, the
"sign your dev manifest with a code-signing cert" path suggested in
some online guides does not work for dev add-ins on LTSC 2024 Mac.

Environment

  • Office LTSC Standard for Mac 2024, version 16.110.2, build 26062818
  • macOS 15.5
  • Any manifest that needs to be XAdES-signed for the WEF scanner to
    consider it installable

Repro (extract cert from a working Omex manifest)

WEF="/Users/zhushuyan/Library/Containers/com.microsoft.Excel/Data/Library/Application Support/Microsoft/Office/16.0/Wef/{EC993EB3-E226-5544-82339-1F3370D3A9CD}"
# Pick any Omex manifest, e.g. wa200010215_2.0.0.0
M="$WEF/Omex/geLWvPTNy9pxk4xxzFEGHw==/Manifests/wa200010215_2.0.0.0"

# Extract all 5 X509Certificate elements
python3 <<'PY'
import re, base64, subprocess
with open("M") as f: c = f.read()
certs = re.findall(r'<X509Certificate>(.+?)</X509Certificate>', c, re.DOTALL)
for i, b64 in enumerate(certs, 1):
    der = base64.b64decode(re.sub(r'\s+', '', b64))
    with open(f"/tmp/omex-cert-{i}.der", "wb") as f: f.write(der)
    out = subprocess.run(["openssl", "x509", "-inform", "DER", "-noout",
                          "-subject", "-issuer", "-dates",
                          f"/tmp/omex-cert-{i}.der"], capture_output=True, text=True).stdout
    print(f"--- cert #{i} ---")
    print(out)
PY

Expected (per the Office Add-in manifest spec)

The official manifest documentation
(https://learn.microsoft.com/en-us/office/dev/add-ins/develop/xml-manifest-overview)
does not mention XML digital signatures or XAdES at all. The schema
reference is silent on the topic. Per spec, a manifest is a plain
XML document with no signing requirement.

Actual

All 4 Omex manifests on a stock LTSC 2024 Mac install contain an
XAdES-T signature with this cert chain:

# Subject Issuer Validity
1 CN=Microsoft Corporation Third-Party App Distribution CN=Microsoft Windows Code Signing PCA 2024 2026-03-05 → 2027-03-03
2 CN=Microsoft Windows Code Signing PCA 2024 CN=Microsoft Root Certificate Authority 2010 2024-08-08 → 2035-06-23
3 CN=Microsoft Root Certificate Authority 2010 (self-signed root) itself 2010-06-23 → 2035-06-23
4 CN=Microsoft Time-Stamp Service (nShield HSM, ESN:F002-05E0-D947) CN=Microsoft Time-Stamp PCA 2010 2026-02-19 → 2027-05-17
5 CN=Microsoft Time-Stamp PCA 2010 CN=Microsoft Root Certificate Authority 2010 2021-09-30 → 2030-09-30

The signature uses RSA-SHA256, c14n 1.0 canonicalization, enveloped
signature with a counter-signature containing a second X509Data
block (the TSA cert chain).

Why this matters for dev

If the WEF scanner on LTSC 2024 Mac does validate the cert chain
against the Microsoft root, no dev add-in can be installed locally
without going through AppSource
. The "sign your manifest with a
self-signed cert" workaround does not work because:

  • A self-signed cert has no chain to Microsoft Root Certificate Authority 2010
  • The leaf cert subject Third-Party App Distribution is reserved
    for Microsoft's AppSource tooling
  • A real public CA-issued cert (e.g. Sectigo, Let's Encrypt) would
    chain to that CA's root, not to the Microsoft root
  • The timestamp must come from Microsoft Time-Stamp Service, not a
    generic RFC 3161 TSA like freetsa.org

If the WEF scanner does NOT validate the cert chain (i.e. the
signature is a post-install artifact for catalog lifecycle tracking
only), then this is a red herring and the real gate is the one
described in the related "WefProcess rejects manually-registered
dev catalog" issue.

Verification I ran

I signed my dev manifest with a self-signed RSA-2048 cert
(CN=DeepSeek Excel Assistant Dev Signing, O=Local Dev, C=US,
30-day validity) using signxml 5.0.1 with the exact same algorithm
choices as the Omex manifests (RSA_SHA256, SHA256,
CANONICAL_XML_1_0, enveloped). The signed manifest is structurally
identical to an Omex one (1 <ds:Signature>, 1 <ds:X509Certificate>,
matching SignatureMethod and CanonicalizationMethod URIs).

I then backfilled all 5 SQL preconditions + on-disk layout with the
signed manifest in Manifests/<aid>_<ver>, disabled the system
proxy, restarted Excel, and waited 35s.

Result: identical to unsigned baseline. WefProcess did not spawn.
Dev server got 0 requests. Excel diagnostic log contained 0 references
to the addin GUID / catalog / signature / 127.0.0.1:3000.

The signature does not unblock the dev catalog.

Suggested fix

Two paths:

  1. Document the exact signature requirements (cert subject,
    timestamp authority, XAdES profile — BES vs T vs XL) in the
    official manifest docs. The current docs are silent on signing,
    but production tooling clearly does sign. Add a section "How to
    sign a manifest for production deployment".

  2. Provide a "sign with a self-signed cert" mode for dev add-ins
    that produces a signature the WEF scanner accepts. The cleanest
    implementation would be to add a <ds:KeyName> to the KeyInfo
    block containing the literal string "dev-mode" and have the WEF
    scanner skip cert chain validation when it sees this marker.

Related

  • See also: office-addin-debugging 5.x / 6.x doesn't sideload on LTSC 2024 Mac (#1006) — the broader "tooling only writes 2/6
    SQL rows" framing
  • See also: LTSC 2024 Mac WefProcess rejects manually-registered
    dev catalog (issue TBD) — the hidden trust gate that fires before
    the signature check and is the more fundamental blocker

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the official XML manifest documentation and the related #1006 issue, then trace the WefProcess trust-gate behavior described here. Done would require either documenting the exact production signing requirements or defining and implementing an accepted development-signing mode, with validation against the reported LTSC 2024 Mac behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, python
Domain
developer-experience, documentation, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.