Security and Integrity¶
File integrity principles¶
- Minimize file-surface changes during modify workflows
- Validate critical workbook outputs after save
- Keep regression tests for high-risk edit paths
Signed OOXML packages¶
Signature presence is separate from encryption and workbook protection.
Workbook.vba_signature_status() reports the effective inner VBA project,
including any queued replacement, plus outer OOXML signature artifacts in the
loaded source package. Workbook.vba_source_signature_status() reports both
scopes from the originally loaded package. Neither API verifies the signature,
certificate, signer identity, or trust chain.
Modify mode uses a safe default for outer package signatures:
- A no-op save copies the source package byte-for-byte.
- Any queued mutation is rejected before output replacement while
package_signature_policyis"reject". - Call
set_package_signature_policy("remove")before the mutation to opt in to removing outer signature parts, relationships, and content-type metadata.
wb = wolfxl.load_workbook("signed.xlsm", modify=True)
wb.set_package_signature_policy("remove")
wb.active["A1"] = "edited"
wb.save("unsigned-edited.xlsm")
The "remove" policy produces an unsigned output. WolfXL does not create or
cryptographically verify digital signatures.
Sanitization and removal verification¶
wolfxl-ops sanitize and wolfxl.operations.sanitize_workbook remove only the
categories a version-1 request names, and they report what they did not remove.
wolfxl-ops sanitize-inspect reports the same inventory while writing nothing.
- The source is read once, bounded by the package admission limits, and the
request's
source_sha256is verified against exactly those bytes. The original path is hashed again immediately before the no-replace rename, so a source whose bytes differ at that check refuses withsource_changedand publishes nothing. That check observes the path at that instant and claims no more: it cannot guarantee the pathname is unchanged until the rename, and nothing here promises it. - The destination directory must not exist and must not resolve to the source. The sanitized bytes are staged privately and published with one atomic no-replace rename, so an existing destination is preserved, an interrupted run leaves no output behind, and only the staging that call created is removed. The workspace records the identity of the directory that call created, and cleanup removes it only while the name still holds that directory, without following a symbolic link; a workspace that was renamed away or rebound, or replaced by a file or a symbolic link, is preserved and the success path refuses before publication.
- Both commands require a source path and a destination parent directory that the caller controls. The workspace-identity, replacement, and final-source checks detect a concurrent same-UID writer and refuse; they are not a defense against one, and no blanket hostile-namespace guarantee is offered.
- The published artifact is named and typed from the sanitized package itself,
from its workbook main-part content type, so a package whose macros were
retained is published as a macro-enabled workbook and never as a macro-free
.xlsx; a workbook type outside that admitted vocabulary refuses withunsupported_featureand writes nothing. The source file name and extension never decide either one. - A package carrying outer OOXML signature material is never republished with
those signatures invalidated: a requested removal that would change such a
package refuses with
policy_rejectedand writes nothing. Strip the signature through the existing save path before requesting a removal.inspect_sanitizationreports signature presence from package metadata only; it verifies no signature, certificate, signer, or trust chain, and no signature payload is read. - The redacted report is count-only. Recognized categories carry the disposition
the caller's own allowlist selected, and every residual category that was not
removed carries its own
retainedentry — media payloads, printer-settings and revision metadata, opaque non-XML payloads, cell data and hidden rows or columns inside retained worksheets, signature scopes, and orphan relationship parts. Those entries state what was retained; they are never a confidentiality statement about the output, and no part name, relationship target, host path, or content value appears in a report.
Reporting an integrity issue¶
Include:
- input workbook (or minimal repro)
- exact code used
- expected output vs actual output
- WolfXL version and environment
Safe rollout suggestions¶
- Use side-by-side comparison in early rollout stages.
- Keep fallback path to existing engine until confidence is established.
- Track regressions explicitly in changelog.