Back to Blog
Technical

Excel Custom XML Parts and Sensitivity Labels: How SharePoint Content Types and Microsoft Information Protection Tags Hide Inside Your Workbooks

Every workbook touched by SharePoint, OneDrive for Business, or a Microsoft 365 tenant with Microsoft Information Protection enabled carries a folder almost nobody opens: xl/customXml/. Inside it sit one or more custom XML parts — arbitrary XML payloads attached to the workbook by the platform that produced it. The two most common payloads are SharePoint content type properties (the document-library column values that travel with the file when it leaves the library) and the Microsoft Information Protection sensitivity-label metadata that names the corporate tenant, the label GUID, the encryption protector, and the user who applied the classification. Document Inspector touches some of this and leaves the rest behind. This post walks through where custom XML parts live in the XLSX, how to decode the SharePoint and MIP payloads, what they reveal about your organisation, and how to actually strip every classification artefact before shipping a workbook externally.

Technical Team
May 10, 2026
22 min read

What Custom XML Parts Actually Are

The Office Open XML specification defines a generic extensibility hook called a custom XML part: any application can attach an arbitrary XML payload to a workbook, name it with a content type, and reference it through the package’s relationship graph. Excel itself uses very few custom XML parts — it has dedicated parts for nearly everything — but the surrounding Microsoft 365 platform uses them heavily. Two large families of metadata ride this hook into every workbook the platform touches:

  • SharePoint content type metadata. When a workbook lives in a SharePoint or Teams document library, the values of its custom columns (Department, Project Code, Confidentiality, Retention, anything the library schema defines) travel with the file as a custom XML part. Move the file out of SharePoint and the metadata travels with it.
  • Microsoft Information Protection (MIP) sensitivity labels. Applied through Office’s Sensitivity dropdown or through Microsoft Purview policies, these labels store the tenant ID, the label GUID, the label name, the protector’s template ID, and the user who set the label as a custom XML part. Even when the file is not encrypted, the classification metadata is recorded.
  • Third-party document-management tags. iManage, NetDocuments, OpenText, M-Files, and similar platforms each publish their own custom XML parts when they save a workbook. They follow the same structural pattern.

Custom XML parts are designed to be opaque to Excel: the application stores them and ships them but does not interpret their contents. That design decision is exactly what makes them a metadata leak. The platform that wrote them knows what is inside; everyone downstream who unzips the file does too.

Where Custom XML Parts Live in the XLSX

An XLSX is a ZIP archive. Custom XML parts cluster inside xl/customXml/ (Excel’s convention) and occasionally at the package root in customXml/ when written by older tools. Each payload comes as a triplet of files.

// XLSX layout fragment showing custom XML part storage

workbook.xlsx (zip)

├── [Content_Types].xml // declares customXml content types

├── _rels/.rels // package-root relationship to customXml/item1.xml

├── xl/

│ ├── workbook.xml

│ └── customXml/

│ ├── item1.xml // <-- the actual payload

│ ├── itemProps1.xml // <-- schema reference + datastoreItem ID

│ ├── _rels/

│ │ └── item1.xml.rels // links item1 to itemProps1

│ ├── item2.xml // <-- second payload (often the MIP label)

│ ├── itemProps2.xml

│ └── _rels/item2.xml.rels

└── docProps/

The triplet matters. itemN.xml carries the data. itemPropsN.xml carries a stable datastoreItem ID (a GUID that identifies the part across edits) and a list of namespace URIs that the data uses, which is how SharePoint figures out which schema the payload belongs to. The relationships file links the two, plus any embedded XSL or XSD if the platform shipped one. Strip item1.xml alone and you leave behind a dangling relationship; strip the props alone and SharePoint round-trips refuse to round-trip; strip neither and the whole metadata layer ships intact.

Why The Numbering Goes 1, 2, 3

Each platform that wants to attach metadata grabs the next free itemN.xml slot. A workbook from a heavily integrated tenant routinely carries three or four custom XML parts: one for SharePoint content type properties, one for the MIP sensitivity label, one for a Purview retention label, and sometimes a fourth for an enterprise DLP scanner’s classification result. The numbering itself is meaningful only locally; the namespace URIs inside itemPropsN.xml are what disambiguate the payload type.

The SharePoint Content Type Payload

When a workbook is uploaded to a SharePoint or Teams document library and edited there, SharePoint serialises the values of every custom column on the file’s content type into a custom XML part. The namespace is consistent: it is rooted at http://schemas.microsoft.com/office/2006/metadata/properties, and the inner element is documentManagement.

// xl/customXml/item1.xml — SharePoint content type properties

<p:properties xmlns:p="http://schemas.microsoft.com/office/2006/metadata/properties">

<documentManagement>

<Department>Corporate Finance — M&A</Department>

<ProjectCode>PROJECT-ATLAS-2026</ProjectCode>

<Confidentiality>Restricted — Deal Team Only</Confidentiality>

<DealStage>LOI Drafted</DealStage>

<TargetCompany>Acme Industrial Holdings</TargetCompany>

<ContentTypeId>0x010100A1F2C3D4E5F60718293A4B5C6D7E8F9A</ContentTypeId>

<_dlc_DocId>CONTOSO-CFM-12849</_dlc_DocId>

<TaxKeywordTaxHTField0>L0|#valuation;diligence;synergy-model</TaxKeywordTaxHTField0>

</documentManagement>

</p:properties>

Every element name is a column on the document library. Every value is the column value at the moment the file was last saved into SharePoint. The internal column names are unedited — they retain the words the library administrator originally chose, including project codenames, deal nicknames, and classification taxonomies that your organisation may consider internal. Move the file to a USB stick and open it in a text editor; the column values are still there.

FieldWhat it carriesWhat it reveals
ContentTypeIdHexadecimal IDNames the content type and its parent chain. The first 32 bytes after 0x0101 identify the site collection’s document content type, which lets a reader infer the SharePoint site the file came from.
_dlc_DocIdDocument ID Service tokenThe site-collection prefix (here CONTOSO-CFM) names the SharePoint site collection. The trailing integer is a sequential document number that hints at total document volume.
TaxKeyword*Managed metadata termsThe pipe-delimited string carries term-store IDs that resolve against the tenant’s managed metadata service. Frequently used for retention, jurisdiction, or matter-number tagging.
Custom columnsFree-text or choice-field valuesWhatever the library admin decided to track: deal codenames, target company names, project IDs, confidentiality tiers, even “OwnerOfRecord” columns that name a specific employee.

Document Library Column Names Are Often Themselves Confidential

The element name itself is metadata. A library schema with columns called DealCodename, TargetCompany, and DealStage tells a reader they are looking at an M&A workbook even before they read the values. Renaming the file does nothing — the schema travels in the XML.

The Microsoft Information Protection Sensitivity Label Payload

Microsoft Information Protection (MIP — the platform that powers Office Sensitivity labels and Microsoft Purview Information Protection) writes a separate custom XML part. The namespace is rooted at http://schemas.microsoft.com/office/2020/mipLabelMetadata, and inside is a single labelList element with one or more labels.

// xl/customXml/item2.xml — MIP sensitivity label

<clbl:labelList xmlns:clbl="http://schemas.microsoft.com/office/2020/mipLabelMetadata">

<clbl:label

id="{87867195-f2b8-4ac2-b0b6-6bb73cb33afd}"

enabled="1"

method="Privileged"

siteId="{3a1b6b0c-9e44-4a2d-9f17-4e1c8b8a6c01}"

contentBits="0"

removed="0"

/>

</clbl:labelList>

The label payload looks small but every attribute is meaningful, and several of them resolve to organisation-identifying values through public Microsoft Graph endpoints.

AttributeWhat it carriesWhat it reveals
idLabel GUIDA tenant-scoped identifier for the specific label (“Confidential — Deal Team”, “Internal”, etc.). Reusing the GUID across many files lets a reader cluster files by classification without reading any cell content.
siteIdTenant ID GUIDThe Microsoft 365 tenant ID. A single Graph call (/v1.0/tenantRelationships/findTenantInformationByTenantId) maps it to the company name and primary domain.
methodApplication methodCommon values: Standard (user picked), Privileged (admin/policy), Auto (DLP rule). Tells a reader whether the file was classified by hand, by policy, or by a scanner — which itself reveals organisational maturity and tooling.
contentBitsVisual-marking bitmaskIndicates which marking types are applied: header, footer, watermark. Even without seeing the document, a reader knows what visual markings should be on every page.
removedDowngrade flagSet to 1 if the label was removed, with a justification recorded in core.xml. The presence of a downgrade is itself a forensic event — someone reduced the protection.

The siteId Is Your Microsoft 365 Tenant GUID

The MIP siteId attribute is, by design, your tenant’s Azure AD directory ID. It is the same GUID that appears in OAuth flows, Graph calls, and federation metadata for the tenant. A workbook with no author name, no UPN, and no SharePoint properties still names the corporate tenant by GUID the moment a sensitivity label is applied. Stripping core.xml alone does nothing.

Labels With Encryption: The MSIP_Label_*_Enabled Custom Property

MIP labels can do two things: classify (a metadata tag) or protect (encrypt the file with a tenant-controlled key). The classification half lives in the custom XML part above. The protection half adds a parallel set of custom document properties in docProps/custom.xml, with names that follow a strict template:

// docProps/custom.xml — MIP classification mirror in Custom Properties

<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties">

<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"

pid="2" name="MSIP_Label_87867195-f2b8-4ac2-b0b6-6bb73cb33afd_Enabled">

<vt:lpwstr>true</vt:lpwstr>

</property>

<property pid="3" name="MSIP_Label_87867195-f2b8-4ac2-b0b6-6bb73cb33afd_SetDate">

<vt:lpwstr>2026-04-19T08:14:32Z</vt:lpwstr>

</property>

<property pid="4" name="MSIP_Label_87867195-f2b8-4ac2-b0b6-6bb73cb33afd_Method">

<vt:lpwstr>Privileged</vt:lpwstr>

</property>

<property pid="5" name="MSIP_Label_87867195-f2b8-4ac2-b0b6-6bb73cb33afd_Name">

<vt:lpwstr>Confidential — Deal Team Only</vt:lpwstr>

</property>

<property pid="6" name="MSIP_Label_87867195-f2b8-4ac2-b0b6-6bb73cb33afd_SiteId">

<vt:lpwstr>3a1b6b0c-9e44-4a2d-9f17-4e1c8b8a6c01</vt:lpwstr>

</property>

<property pid="7" name="MSIP_Label_87867195-f2b8-4ac2-b0b6-6bb73cb33afd_ActionId">

<vt:lpwstr>{d4e5f607-1829-3a4b-5c6d-7e8f9a0b1c2d}</vt:lpwstr>

</property>

</Properties>

The custom-properties mirror exists for backwards compatibility: older Office builds and third-party tools that do not understand the labelList namespace can still read the label name, the set date, the method, and the tenant ID through the well-known property naming convention. The label name is plain text. The label-applied date has second precision. The action ID is a per-application GUID that ties this specific label application to a record in the Microsoft Purview activity feed.

  • _Name is the human-readable label. Reading it gives you the organisation’s classification taxonomy verbatim — “Confidential — Deal Team Only”, “Restricted — Legal Hold”, “Public — Press Release”.
  • _SetDate records when the label was applied. If a workbook was downgraded, you see both the old label’s set date and the new label’s, allowing reconstruction of the classification history.
  • _SiteId is the tenant GUID. Same beacon as the custom XML payload, and now it lives in two places.
  • _ActionId ties to Purview audit logs. An adversary cannot read your audit log, but the GUID is itself unique enough to fingerprint a specific user-action event across files.

The itemPropsN.xml File: Schema Reference and Datastore IDs

Each itemN.xml has a sibling itemPropsN.xml that names the schemas the payload uses and assigns it a stable datastore ID.

// xl/customXml/itemProps1.xml

<ds:datastoreItem

ds:itemID="{c5b1e6a7-3f2d-4a8b-9e3a-4c5d6e7f8091}"

xmlns:ds="http://schemas.openxmlformats.org/officeDocument/2006/customXml">

<ds:schemaRefs>

<ds:schemaRef ds:uri="http://schemas.microsoft.com/office/2006/metadata/properties"/>

<ds:schemaRef ds:uri="http://schemas.microsoft.com/sharepoint/v3"/>

<ds:schemaRef ds:uri="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms"/>

</ds:schemaRefs>

</ds:datastoreItem>

The datastore item ID is stable across SharePoint round-trips, which means a workbook that leaves the platform, gets edited, and is uploaded back can still be matched to its original library entry by GUID. From a privacy perspective the schema reference list is also informative: an analyst sees sharepoint/v3 URIs and immediately knows the file lived in SharePoint Online, regardless of whether any data values give it away.

What an External Reader Reconstructs

A motivated reader who unzips an XLSX with custom XML parts can reconstruct, with no special tooling, an unusually complete picture of the file’s organisational origin.

  • The corporate Microsoft 365 tenant. Either the MIP siteId, the _SiteId custom property, or the SharePoint _dlc_DocId prefix names the tenant unambiguously.
  • The classification taxonomy verbatim. Every label name is plain text in the custom-properties mirror. Reading them tells the reader your full sensitivity-label hierarchy.
  • The library schema. Column names like DealCodename, MatterNumber, ResearchProjectId reveal which library the file lived in and what kind of work the library tracks.
  • The classification history. If a label was removed or downgraded, both old and new label IDs appear, with timestamps.
  • The user who applied the label. The action ID and method together let a forensic reader correlate against any audit log they have access to. Some MIP versions also persist the applying user’s UPN as _Owner.
  • The visual markings the file should carry. The contentBits bitmask names the watermark, header, and footer text the document is supposed to display, even if the file has no header at all.
  • Tooling hints. The schemaRefs in itemPropsN.xml identify which platforms and applications wrote the parts, including third-party systems like iManage or NetDocuments.

Reading Custom XML Parts Without Excel

Three quick recipes pull the SharePoint, MIP, and custom-property data out of a workbook without ever launching Office.

# 1. List every custom XML part and its schema reference

unzip -l workbook.xlsx | grep -E "customXml|docProps/custom"

# 2. Dump every custom XML payload

for f in $(unzip -l workbook.xlsx | awk '/customXml.item[0-9]+\.xml$/{print $4}'); do

echo "### $f ###"

unzip -p workbook.xlsx "$f"

done

# 3. Pull every MSIP_Label_* property

unzip -p workbook.xlsx "docProps/custom.xml" | \

xmlstarlet sel -t -m "//*[contains(@name,'MSIP_Label')]" -v "@name" -o " = " -v "." -n

For programmatic auditing, a small Python script enumerates every payload and decodes the SharePoint and MIP fields:

import zipfile, re

from xml.etree import ElementTree as ET

SP = "{http://schemas.microsoft.com/office/2006/metadata/properties}"

MIP = "{http://schemas.microsoft.com/office/2020/mipLabelMetadata}"

with zipfile.ZipFile("workbook.xlsx") as z:

for name in z.namelist():

if re.match(r"xl/customXml/item\d+\.xml", name):

root = ET.fromstring(z.read(name))

if root.tag.startswith(SP[:-1]):

print("SharePoint payload:", name)

for child in root.iter():

if child.text and child.text.strip():

print(" ", child.tag.split("&rbrace;")[-1], "=", child.text)

elif root.tag.startswith(MIP[:-1]):

print("MIP label payload:", name)

for label in root.iter(MIP + "label"):

print(" label", dict(label.attrib))

The output is a flat dump of every SharePoint column value and every MIP label that ships with the workbook — the layer Document Inspector shows you nothing about.

Document Inspector Coverage Is Selective

Document Inspector exposes a checkbox called Custom XML Data and a separate one called Document Properties and Personal Information. In practice their behaviour is asymmetric.

  • Custom XML Data removes xl/customXml/itemN.xml payloads, but only for parts whose schemaRefs do not match a list of Microsoft-blessed namespaces. SharePoint content type properties are typically caught; the MIP labelList namespace is treated as system metadata and frequently survives.
  • Document Properties and Personal Information removes built-in core properties, but it does not remove the MSIP_Label_* entries from docProps/custom.xml. Office’s logic treats them as system properties because removing them would also remove the encryption protection. So they ship intact.
  • Sensitivity-label removal requires explicit user action. The Sensitivity dropdown in the ribbon includes a Remove option; using it requires the user’s permission level to allow downgrades, prompts for a justification, and writes the removal back to docProps/core.xml. Even after this, the historical _SetDate and _Justification remain.
  • Schema reference files itemPropsN.xml are removed alongside their payloads, but [Content_Types].xml overrides occasionally remain, leaving a structural fingerprint that something was removed.
  • The Mac version of Excel does not expose Custom XML Data as a separate inspector item in many builds. Workbooks shipped from Mac users frequently retain custom XML parts that a Windows colleague’s Document Inspector run would have removed.

How to Actually Strip the Custom XML Layer

A clean removal touches five artefacts: the xl/customXml/ folder, every MSIP_Label_* property in docProps/custom.xml, the package-root and folder-level .rels entries, and the relevant [Content_Types].xml overrides. Four approaches in increasing order of robustness.

1. Remove the sensitivity label, then run Document Inspector

Sensitivity dropdown > Remove (or pick a Public/None label), provide a justification, save. Then File > Info > Check for Issues > Inspect Document and tick both Document Properties and Personal Information and Custom XML Data. Verify by unzipping and confirming xl/customXml/ is empty and docProps/custom.xml contains no MSIP_Label_* entries.

2. Save As → strict OOXML and re-save

Saving the workbook as Strict Open XML Spreadsheet (.xlsx with the strict conformance class) and then converting it back to transitional .xlsx drops most non-conformant custom XML parts. This is a useful sanity step but is not 100 % reliable across Office builds — treat it as a complement, not a replacement.

3. Strip programmatically

A short Python script removes every custom XML artefact and every MIP label custom property in a single pass and rewrites the relationship and content-type files:

import zipfile, re

from pathlib import Path

src, dst = Path("in.xlsx"), Path("out.xlsx")

DROP = ("xl/customXml/", "customXml/")

REL_PAT = rb"<Relationship[^/]*customXml[^/]*/>"

OVR_PAT = rb"<Override[^/]*customXml[^/]*/>"

MIP_PAT = rb"<property[^>]*name=\"MSIP_Label_[^\"]+\"[^>]*>.*?</property>"

with zipfile.ZipFile(src) as zin, \

zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as zout:

for item in zin.infolist():

if any(item.filename.startswith(p) for p in DROP):

continue

data = zin.read(item.filename)

if item.filename.endswith(".rels"):

data = re.sub(REL_PAT, b"", data)

if item.filename == "[Content_Types].xml":

data = re.sub(OVR_PAT, b"", data)

if item.filename == "docProps/custom.xml":

data = re.sub(MIP_PAT, b"", data, flags=re.DOTALL)

zout.writestr(item, data)

Excel reopens the resulting file cleanly. Because no worksheet XML element references custom XML payloads by ID, no further fix-up is required. If the workbook was protected by a MIP encryption template, this script will not remove the encryption itself — you must downgrade the label inside Office first or the file will not open.

4. Pre-share pipeline with classification reconciliation

For organisations sharing workbooks regularly, build a server-side step into the file-sharing pipeline that strips xl/customXml/, removes MSIP_Label_* properties, and verifies no SharePoint or MIP namespaces remain anywhere in the package. This composes well with parallel sanitisation steps for threaded comments and personas, external links, defined names, and printer settings — the same pipeline can clean every layer in one pass.

Stripping Labels Has Compliance Implications

Programmatically removing MIP label metadata from a workbook circumvents the protection your tenant configured for it. Many organisations require the label to remain on the file at all times and instead control redistribution at the protection (encryption) layer. Before deploying a stripping pipeline, confirm with your information-security team that downgrading or removing labels is permitted for the specific use case — and prefer the supported “Remove label” flow inside Office, which records a justification, over a script that silently deletes the metadata.

Pre-Share Checklist

Run this checklist against any workbook leaving your organisation, especially if it has lived in SharePoint or has been touched by a Microsoft 365 Sensitivity workflow.

  • Have I confirmed whether xl/customXml/ contains any itemN.xml payloads?
  • For every payload, have I read the schemaRefs in itemPropsN.xml and identified whether the source is SharePoint, MIP, a third-party DMS, or something custom?
  • Does any SharePoint payload contain column values that name a project codename, deal nickname, target company, matter number, or internal classification taxonomy I do not want disclosed?
  • Does _dlc_DocId reveal the SharePoint site collection prefix, and is that prefix something I would not want a recipient to see?
  • Does any MIP payload include a siteId attribute that names the corporate Microsoft 365 tenant GUID, even if the label name itself is innocuous?
  • Does docProps/custom.xml contain MSIP_Label_* entries with label names that disclose the organisation’s sensitivity taxonomy?
  • Have I checked the _Method attribute and noted whether the label was applied automatically, by policy, or by hand — and confirmed the implication of that channel is acceptable to disclose?
  • Have I scanned [Content_Types].xml for orphan Override entries pointing at customXml content types that no longer exist in the package?
  • For workbooks shipped externally as final deliverables, have I removed both xl/customXml/ and the MIP custom properties entirely, plus their .rels and content-type entries?
  • Have I cross-checked the rest of the metadata layers — defined names, external links, threaded comments, printer settings, calculation chain — that the same workbook may also be carrying invisibly?

Conclusion

Custom XML parts are the metadata layer that ride into your workbooks the moment SharePoint, OneDrive for Business, or a Microsoft 365 sensitivity workflow touches the file. They sit in xl/customXml/ as a triplet of payload, schema reference, and relationship. They are mirrored in docProps/custom.xml as MSIP_Label_* entries with the tenant GUID, the label name, and the application timestamp. Document Inspector handles the SharePoint half competently and the MIP half barely at all, with the result that the average enterprise workbook leaves the organisation carrying a complete classification beacon, the library schema it lived in, and a tenant-naming GUID that any reader can resolve through Microsoft Graph.

For workbooks staying inside an organisation, the layer is exactly what it is supposed to be: a useful classification record that drives DLP, retention, and downstream protection. For workbooks crossing the perimeter, it is a tenant fingerprint, a taxonomy disclosure, and a SharePoint provenance trail rolled into one. The only durable defence is to strip the custom XML folder and the MIP custom properties together — coordinated with the rest of the metadata-layer cleanup — before the workbook ever leaves the trusted boundary. A small ZIP-level operation closes a leak that most security teams never knew was open.

Audit Custom XML Parts and Sensitivity Labels in Your Workbooks

Use MetaData Analyzer to enumerate every custom XML payload, decode SharePoint content type properties, surface MIP sensitivity labels and the tenant GUIDs they encode, and confirm both layers are gone before your workbooks leave the organisation.