Skip to content

fix(privacy): redact invalid XLSX worksheet names from errors #193

Description

@seonghobae

Current authoritative state

This buyer-visible XLSX diagnostic-privacy defect is repaired on the existing canonical single-writer Draft PR #192 / branch fix/docx-image-size-preflight-191. Protected shipped truth is exact main@3b38ead2d00f44eb578d0689087b9293b3dabe1e; current exact Draft head is b3080d81e3dc6fcd49c7669422746ac9c5463559.

Current office/src/inkspan_office/renderer.py preserves the worksheet structural path/category but no longer reflects the caller-controlled invalid worksheet name. An otherwise-valid XLSX request with a private worksheet name that is too long or contains an Excel-forbidden character now fails as OfficeDocumentError('<path>.name is invalid for Excel') without copying the supplied name into the ordinary diagnostic. The repair does not normalize, truncate, hash, or partially echo the rejected value.

The same canonical lane also contains adjacent strict-renderer privacy and DOCX PNG preflight repairs. It preserves Excel's existing worksheet-name validity semantics, case-insensitive uniqueness checks, schema/type validation, deterministic accepted XLSX output, literal formula-string handling, payload-redacted diagnostics, and no-partial-publication behavior.

Test-first lineage

A dedicated public render_office_document() RED exercised an invalid worksheet name containing a distinctive private marker and proved the predecessor diagnostic reflected the complete rejected name. The narrow GREEN changes only that diagnostic payload: current regression office/tests/test_xlsx_sheet_name_redaction.py requires the structural category to remain present while both the complete private name and its distinctive marker remain absent.

The branch later consolidated strict-renderer structural-token redaction and a DOCX PNG pre-allocation boundary without weakening this worksheet-name contract. A separate exploratory mapping-breadth probe proved that broad request traversal is first owned by the public safe_renderer.py safety facade and was correctly moved to canonical Draft #246 rather than creating a competing renderer.py writer.

Exact-current-head evidence

Fresh exact-head refetch for unchanged b3080d81e3dc6fcd49c7669422746ac9c5463559 confirms:

  • CI 32181095807: completed / success;
  • Security Scan 32181095622: completed / success;
  • SAST Semgrep 32181095642: completed / success;
  • formal submitted reviews: 0;
  • unresolved inline review threads: 0;
  • GitHub reports the Draft mechanically mergeable.

Repository exact-head success is technical evidence only. It does not substitute for separately applicable central workflows, qualifying independent approval, or live governance. Intentional RED/predecessor/model/status evidence does not transfer.

Scope / authority

This remains Inkspan-owned local diagnostic privacy. It adds no logging backend, persistence, transport, authentication/authorization, tenancy, credentials, model/provider, network, deployment, migration, retention or durable-audit authority.

Integration boundary

The defect is repaired on active Draft #192 but is not protected-main shipped behavior. Keep this issue open until #192 integrates under then-live governance. Keep #192 Draft/unmerged while #118 owns the frozen protected v0.6.0 publication/provenance/digest boundary. Before any lifecycle transition refetch exact head/live base, ancestry/mergeability, formal reviews/threads, live governance and every applicable repository/central workflow. Do not create a competing renderer.py writer, transfer predecessor evidence, self-approve, weaken gates, move protected main or fabricate release identity.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: apiAPI, protocol, event, or external contractarea: authAuthentication, authorization, identity, or tenant isolationarea: ci-cdCI, GitHub Actions, checks, release, or supply chainarea: securitySecurity boundary, hardening, or vulnerability preventionpriority: mediumNormal-priority or P2 workstatus: triagedOpen issue has an organization taxonomy assignmenttype: bugDefect or incorrect behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions