Excel exposes at least four different things called “passwords” — sheet protection, workbook structure protection, the modify-on-open password, and the open password. Three of them are not protection at all in any cryptographic sense; they are a flag in the XML asking Excel to please be polite. The fourth is real AES encryption. Almost everyone confuses them, and almost every workbook stamped “protected” ships out the door wide open. This post walks through what each mechanism actually does, where the password hashes live inside an XLSX, how trivially the weak ones break, and how to use the one that actually works.
The dialog labels are nearly identical, and the menus that surface them are scattered across Review, File → Info, and the Save As options panel. From the outside they all look like “put a password on the file.” Internally they are completely different mechanisms with completely different threat models.
| Name | Where It Lives | What It Actually Does |
|---|---|---|
| Sheet protection | xl/worksheets/sheet*.xml → <sheetProtection> | A flag asking Excel’s UI to refuse certain edits. No encryption. |
| Workbook structure protection | xl/workbook.xml → <workbookProtection> | A flag asking Excel’s UI to forbid renaming, hiding, or rearranging sheets. No encryption. |
| Modify password | CFB stream / <fileSharing> in workbook.xml | A flag asking Excel to open the file read-only. The file content is plaintext. |
| Open password | Compound File Binary container (replaces the XLSX entirely) | Real AES-128 or AES-256 encryption of the entire package. Strong if the password is strong. |
The first three mechanisms do not encrypt anything. The cell values, formulas, hidden sheets, defined names, comments, and embedded objects are all readable as plaintext XML inside the ZIP. The “password” on a protected sheet is a hash stored in the same plaintext XML — a recipient can delete it with a text editor in fifteen seconds. Only the open password on a fully encrypted XLSX provides real cryptographic protection.
The legacy sheet protection algorithm dates from Excel 95 and survived essentially unchanged into the XLSX era. When a user clicks Review → Protect Sheet and types a password, Excel runs the password through a small bit-shifting routine that produces a single 16-bit value — a number between 0 and 65,535 — and writes it as a four-character hex string into the worksheet XML.
// Excerpt from xl/worksheets/sheet1.xml after a legacy Protect Sheet
<sheetProtection
password="CC1A"
sheet="1"
objects="1"
scenarios="1"
selectLockedCells="1"
selectUnlockedCells="1"/>
The password attribute in that block is not the password — it is the entire 16-bit hash. The output space is so small that the hash collides constantly: many different passwords produce the same four-character value. To bypass the protection, a recipient does not need to recover the original password. They need any password — or any string at all — that hashes to the same value, and the protection accepts it.
xl/worksheets/sheet1.xml in a text editor, remove the entire <sheetProtection> element, save, repack. Excel opens the file with no protection at all.As and Bs ending in a single visible character. The famous “AAAAAAAAAAAAAAAB” family unlocks an enormous fraction of legacy-protected sheets because so few hash buckets exist.Both methods take well under a minute and require no specialist tooling. The legacy sheet protection password is a stop sign at an empty intersection.
Recent Excel versions use a modernized password hashing scheme for sheet and workbook protection. The new format derives a salted SHA-512 hash with a configurable iteration count (the spinCount), modeled on PBKDF2-style stretching. The XML attributes change accordingly:
// Excerpt from xl/worksheets/sheet1.xml with the modern algorithm
<sheetProtection
algorithmName="SHA-512"
hashValue="3VnH7y...truncated...=="
saltValue="Wq8Lz9...=="
spinCount="100000"
sheet="1"
objects="1"
scenarios="1"/>
The salt and spin count make a brute-force recovery of the original password meaningfully harder than the legacy 16-bit case. That is irrelevant. The hash, the salt, and the spin count are all sitting in the same plaintext XML alongside every cell value the protection was meant to guard. A recipient does not need to crack the hash; they delete the entire <sheetProtection> element and the file opens without any protection. The cryptography is irrelevant when the cipher text is right next to the lock.
The modern algorithm exists because the legacy 16-bit hash was so weak it embarrassed the format. It was never intended to make sheet protection a real access control. Microsoft’s own documentation describes sheet protection as a UI convenience — preventing accidental edits by trusted users — and explicitly disclaims it as a security boundary. The salted SHA-512 simply makes the polite request a little politer.
The <sheetProtection> element carries a long list of boolean attributes that tell Excel which UI actions to refuse: formatCells, insertColumns, deleteRows, sort, and so on. These flags govern the user interface, not the file contents.
| Action | Blocked by Sheet Protection? |
|---|---|
| Editing locked cells in Excel’s UI | Yes (until protection removed) |
| Reading every cell value as plaintext XML | No |
| Reading every formula, including hidden ones | No |
| Reading hidden rows, columns, and sheets | No (the data is in the XML) |
| Editing the file by re-zipping modified XML | No |
| Removing protection by deleting the XML element | No |
Programmatic access via openpyxl, ExcelJS, etc. | No |
The hidden attribute on a column or row, the veryHidden state on a sheet, and the password attribute on a sheet protection block all live in the same XML and are visible to any reader of that XML. None of them constitutes confidentiality. Sheet protection is a permissions hint, not a wall.
Review → Protect Workbook writes a different element — <workbookProtection> — into xl/workbook.xml. Its job is to prevent the user from renaming, hiding, unhiding, inserting, deleting, or reordering sheets. It uses the same legacy or modern hashing as sheet protection, with the same disclaimer: the hash is in the XML next to the protection it is meant to guard.
// xl/workbook.xml
<workbookProtection
workbookAlgorithmName="SHA-512"
workbookHashValue="..."
workbookSaltValue="..."
workbookSpinCount="100000"
lockStructure="1"
lockWindows="0"/>
The most common use of workbook structure protection is to hide a sheet with state veryHidden — a sheet that is invisible from the Excel UI even via Unhide, because the Unhide menu lists only hidden sheets. Adding workbook structure protection prevents a casual user from changing the sheet’s state through the UI. The sheet’s contents are still in the XLSX as plaintext XML, the veryHidden attribute is visible in the XML, and a programmatic reader sees the whole sheet without ever consulting the protection element.
A common pattern: a financial model has a veryHidden sheet named “assumptions_internal” with cost-of-capital, head-count plans, and base-case discount tiers. The author protects the workbook structure with a password and ships the file. The recipient unzips the XLSX, opens xl/worksheets/sheet5.xml, and reads every assumption directly. The protection prevented the recipient from clicking Unhide in the UI; it did nothing to prevent reading.
In Save As → Tools → General Options, Excel exposes two password fields: Password to open and Password to modify. They look symmetrical; they are not.
The modify password sets a flag (<fileSharing readOnlyRecommended="1" userName="..."/> in the modern format, or a stream value in the legacy CFB header) that tells Excel to open the workbook read-only unless the password is supplied. The file content itself is not encrypted. A recipient who renames the file to .zip and re-saves a copy without the flag has full read-write access; a recipient using openpyxl never sees the flag at all.
A modeler ships a workbook with a strong “modify password” and tells the counterparty it cannot be edited without authorization. The counterparty’s analyst opens the file in Excel, sees the read-only banner, and gives up. A different analyst at the same firm opens it with openpyxl.load_workbook("file.xlsx"), edits any value, and saves. Both Excel installations on both desks then load the modified file without complaint — the read-only flag was respected only by the original session, not by the file.
When a developer right-clicks a VBA project in the Visual Basic Editor and sets a password, the project is marked as locked-for-viewing. This is a separate mechanism from sheet or workbook protection, and it is among the easiest to bypass of all the Office password schemes.
The VBA project password is stored in the DPB (or CMG/GC) entry of the xl/vbaProject.bin compound file’s PROJECT stream. Two well-known bypass routes:
DPB="..." entry, and replace it with a known DPB hash whose password is known. Save, reopen the workbook, and the VBA project unlocks with that known password. Documented in countless forum posts since at least 2003.olevba from the oletools suite) ignore the DPB entirely and dump the executable code. The “protection” was on the source view, not the source itself.For VBA code that contains hard-coded credentials, internal API keys, or business logic the author considered proprietary, the project password is not a safeguard. Anyone with five minutes and oletools reads the code in full.
The single Excel password mechanism that actually protects data is the password to open. When set, Excel writes the workbook into a Compound File Binary container (the same format as legacy .xls, used here as an envelope) with the contents encrypted by AES-128 in older defaults, AES-256 in modern Office. The XLSX ZIP, with all its plaintext XML, is encrypted as a single payload. A recipient without the password sees only the CFB envelope and an opaque encrypted blob.
| Office Version | Default Cipher | Key Derivation Iterations |
|---|---|---|
| Office 2007 | AES-128, ECB | 50,000 SHA-1 iterations |
| Office 2010 | AES-128, CBC | 100,000 SHA-1 iterations |
| Office 2013+ | AES-256, CBC | 100,000 SHA-512 iterations |
| Office 2016+ | AES-256, CBC | 100,000 SHA-512 iterations (configurable up to 10M) |
Modern AES-256 with 100,000 SHA-512 iterations is genuinely strong. The cracking economics depend almost entirely on the password the user chose. A six-character dictionary word is recovered in seconds on a single GPU; a long random passphrase takes geological time. The encryption is not the weak link; the password choice and how it is shared are.
An XLSX with only sheet/workbook protection is still a normal ZIP file — file workbook.xlsx reports Microsoft OOXML, and unzip -l workbook.xlsx works. An XLSX with an open password is a Compound File Binary — file reports Composite Document File V2 Document or CDFV2 Encrypted, and unzip refuses with End-of-central-directory signature not found. If unzip -l works, the file is not encrypted.
Two more banners users mistake for protection:
Sets a custom property called _MarkAsFinal. The first time the file is opened in Excel, the user sees a yellow banner suggesting the file is final. One click on Edit Anyway dismisses the banner permanently. The file is not encrypted, not read-only at the filesystem level, and not protected in any other way. Mark as Final is etiquette, not enforcement.
Microsoft Purview Information Protection (formerly AIP) labels can apply real encryption to files via a tenant-managed key. When that label has encryption attached, the file is genuinely encrypted — equivalent to an open password keyed to the user’s tenant identity. When the label is “classification only” (e.g., a header that says Confidential), it is just a property; the file is plaintext. Always check whether the label includes encryption, not just classification.
Before sharing a workbook stamped “protected,” verify what protection the file actually has and what protection the recipient will actually see. Three quick checks:
# 1. Is the file encrypted at all?
file report.xlsx
# "Microsoft OOXML" = ZIP, plaintext inside (sheet protection at most)
# "CDFV2 Encrypted" or "Composite Document File V2" = encrypted with open password
# 2. List every sheet and workbook protection element
unzip -p report.xlsx "xl/worksheets/sheet*.xml" | grep -o 'sheetProtection[^/]*'
unzip -p report.xlsx "xl/workbook.xml" | grep -o 'workbookProtection[^/]*'
# 3. Is there a fileSharing "modify password" flag?
unzip -p report.xlsx "xl/workbook.xml" | grep -o 'fileSharing[^/]*'
# 4. Is there a VBA project? (its protection is bypassable too)
unzip -l report.xlsx | grep vbaProject.bin
If file reports anything other than CDFV2 Encrypted, the file’s contents are plaintext XML to anyone with unzip. Whatever protection the workbook claims, the data inside is readable.
Match the protection mechanism to the threat model, and stop relying on the wrong ones.
Sheet protection is appropriate. The threat is fingers, not adversaries. Use it freely; the password can even be left blank because no real protection is being offered.
Sheet protection is useless. Either remove the confidential data from the workbook before sharing, or apply a real open password (or IRM/sensitivity label with encryption) on the entire file.
The modify password does not enforce this. Print to PDF and ship the PDF, share through a portal that prevents download, or share through a protected SharePoint link with edit permission removed. Do not rely on a flag.
Do not embed sensitive VBA code in workbooks shared externally. The project password does not protect it. Move secrets to a server-side endpoint and have the macro call out, or convert the workbook to a static deliverable.
Use a sensitivity label with encryption tied to the recipient’s identity, not a static password. A leaked file with a static password is a leaked password; a leaked file with an identity-bound label still requires authentication to the issuing tenant.
Run this checklist before relying on any “protection” in a workbook you are about to release:
file workbook.xlsx and confirmed whether the file is encrypted (CDFV2) or just a plaintext ZIP?veryHidden sheets carrying confidential data behind sheet protection alone?Most workbooks marked “protected” in everyday business correspondence are not protected at all. They carry a flag in plaintext XML asking Excel’s UI to be polite about edits. The flag is trivially removed; the cell contents, formulas, hidden sheets, and embedded objects all sit in the same plaintext XML the flag lives in. The legacy 16-bit hash falls in seconds; the modern salted SHA-512 hash is irrelevant because the protection it gates is a hint, not a wall.
The mechanism that actually works is a strong open password (or an IRM-encrypted sensitivity label) on the entire file — AES-256 with a long passphrase or an identity-bound key. Everything else is etiquette. Use sheet protection to keep teammates from breaking your formulas; use real encryption when the data must not be read by someone with the file. Confusing the two is how confidential workbooks routinely walk out of organizations under the impression they were locked.
Use MetaData Analyzer to inspect your XLSX files for sheet protection elements, workbook structure flags, modify-password indicators, hidden sheets, and whether the file is actually encrypted. Find out what your “protected” workbooks really expose before they leave your organization.
Where everything lives inside an XLSX, including the protection elements.
Why VBA project passwords do not protect the compiled p-code.
Hidden sheets and protected workbooks are not the same as hidden data.