fix(libreoffice): report an encrypted .xlsb as password-protected (#1655)

Uploading a password-protected .xlsb workbook without its password
answered 500 with the unattributable-failure message instead of 400 with
the remedy.

DetectPasswordProtection in pkg/modules/libreoffice/api/protection.go
infers encryption from a compound-file header carried by an extension
whose unencrypted form is always a ZIP package. The ooxmlExtensions map
listed .xlsx, .xlsm, .xltx and .xltm but not .xlsb, so an encrypted
workbook under that extension fell through to PasswordProtectionUnknown.
The convert route in pkg/modules/libreoffice/routes.go then matched
neither password branch of its exit-code switch and returned the 500
default.

An Excel Binary Workbook is an Open Packaging Conventions ZIP holding
binary parts, so a compound file under that extension is encrypted for
the same reason .xlsx is. Adding .xlsb to the map restores the 400 that
names the 'password' form field.
This commit is contained in:
Max Freedom Pollard
2026-09-06 07:05:20 -04:00
committed by GitHub
parent ac825a2c03
commit c21ceacd4b
2 changed files with 10 additions and 4 deletions

View File

@@ -35,12 +35,13 @@ var (
zipMagic = []byte{0x50, 0x4b, 0x03, 0x04}
// An unencrypted OOXML document is always a ZIP package, so any of these
// extensions over a compound file means the payload is encrypted. Legacy
// binary formats (.doc, .xls, .ppt) are compound files either way and are
// deliberately absent.
// extensions over a compound file means the payload is encrypted. A .xlsb
// workbook stores binary parts inside that same ZIP package, so it belongs
// here too. Legacy binary formats (.doc, .xls, .ppt) are compound files
// either way and are deliberately absent.
ooxmlExtensions = map[string]struct{}{
".docx": {}, ".docm": {}, ".dotx": {}, ".dotm": {},
".xlsx": {}, ".xlsm": {}, ".xltx": {}, ".xltm": {},
".xlsx": {}, ".xlsm": {}, ".xltx": {}, ".xltm": {}, ".xlsb": {},
".pptx": {}, ".pptm": {}, ".potx": {}, ".potm": {},
".ppsx": {}, ".ppsm": {},
}

View File

@@ -76,6 +76,11 @@ func TestDetectPasswordProtection(t *testing.T) {
path: ole2("encrypted.xlsx"),
want: PasswordProtectionRequired,
},
{
name: "encrypted binary workbook",
path: ole2("encrypted.xlsb"),
want: PasswordProtectionRequired,
},
{
name: "legacy binary document is inconclusive",
path: ole2("legacy.doc"),