Repository navigation
Conversation
…16775) ALLOWED_EXTENSIONS omitted .xlsx/.pptx/.odt/.ods/.odp even though DocumentParser has carried working parsers for them all along, so a user could not upload a file the backend could already read by another path. Owner decision on the ingestion review: every format in it is to be handled. - api/knowledge_office_upload.py: the routing, and no new extraction logic. - Dispatch resolves the format from content first (#16773), so widening the allowlist does not reintroduce the extension-trust that issue just removed. A renamed .xlsx reaches the workbook parser, not the one its name claims. - utils/document_parser.parse_document_text: the sync entry point for a caller already off the event loop. The upload route runs inside asyncio.to_thread, so it needs the same dispatch without a second thread hop, and without a second copy of the parser table — which is how these two routes drifted before. Left out deliberately: .doc and .ppt are OLE2, and python-docx/python-pptx read only the OOXML ones, so advertising them would accept a valid file and then call it corrupt (#16786, an owner call). .odg is left out too — a drawing carries almost no extractable text and this endpoint stores flattened text only. api/knowledge.py is at its size ceiling, so its edits are net-zero: the routing lives in the new module, and three added lines are paid for by rewrapping three comments. Closes #16775 Refs #16772
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
`normalise_hooks_path()` returned early when core.hooksPath already resolved to the default hooks dir, on the reasoning that such a key changes nothing. That is true for git and fatal for pre-commit, which refuses to install while the key exists at all — "Cowardly refusing to install hooks with `core.hooksPath` set" — whatever its value. So a redundant key pointing at git's own default silently disabled every hook declared in .pre-commit-config.yaml: flake8, autoflake, mypy and the local guards. It reads as configuration hygiene and the old equal-to-default test scored exactly that state as clean, so the commit-time suite was absent with nothing reporting its absence. An F401 reaching CI on #16788 is what exposed it. Removing the key is also what #15961 concluded on independent grounds: a core.hooksPath override is a `--no-verify` that leaves no trace, and the premise for adding one is false because git already shares hooks with worktrees. The lookup moves to --get-all and the removal to --unset-all: --get exits non-zero on a multi-valued key and prints nothing, so a doubled entry read as "unset", and --unset fails on the same key while `|| true` swallowed it. One surviving value is as disqualifying to pre-commit as two. Tests assert the key is ABSENT afterwards rather than equal to the default, because equal-to-default is the state under test — a test accepting it would pass on the bug.
|
Review verdict: BLOCK. Three substantive findings plus a structural one. The format matching is genuinely well done — the allowlist matches what the parser can actually read, and the exclusions are deliberate and documented — but this cannot merge yet. 0. Structural — this is stacked, and not evaluable against
|
|
Carried by vehicle #17077, which includes this PR's approved head |
Thinking Path
ALLOWED_EXTENSIONSlisted.txt .md .pdf .docx .json .csv .html.DocumentParserhas carried working, tested parsers for.xlsx .pptx .odt .ods .odpall along, so a user could not upload a file the backend could already read if it arrived by any other path. The owner decision on the ingestion review is that every format in it is handled.The trap worth naming: five more
elif ext == ...branches on a function that trusts the filename would have widened the attack surface and reintroduced the extension-trust #16773 just removed — and would have done it on exactly the formats that share thePKprefix. So the dispatch resolves format from content first, name second, using the same helper this stack already introduced. A file uploaded asnotes.txtthat is really a workbook reaches the workbook parser; a.xlsxthat is really a presentation reaches the presentation parser.Two formats are deliberately left out, and the tests pin both so the next audit does not re-flag them:
.docand.pptare OLE2 containers. python-docx and python-pptx read only the OOXML ones, so advertising these would accept a valid file and then report it corrupt — that is bug(knowledge): .doc is advertised as supported and always fails as 'invalid or corrupted' #16786, which needs an owner call on whether to add a real OLE2 reader or stop advertising the format..odgis a drawing: it carries almost no extractable text, and this endpoint stores flattened text only. Say the word and it is a one-line change.What Changed
api/knowledge_office_upload.py(new)verified_upload_extension(content first) andextract_office_upload(temp file →DocumentParser). No new extraction logic.api/knowledge.pyALLOWED_EXTENSIONSgains the five;_extract_file_contentdispatches on the verified extension and routes the office set. Net-zero — see below.utils/document_parser.pyparse_document_text: the sync entry point for a caller already off the event loop._extract_file_contentalready runs insideasyncio.to_thread, so the blocking parse belongs there — butDocumentParser.extract_textis async and hands work to a thread itself.parse_document_textgives that caller the same dispatch without a second thread hop and without a second copy of the parser table, which is how these two routes drifted apart before (#14333).Verification
api/knowledge.pyis at its size ceiling (3414) and is still at exactly 3414: the routing lives in the new module, and the three added lines are paid for by rewrapping three comments — same words, fewer lines..txt,.md,.csv,.json,.html,.pdfand.docxrouting is untouched, and covered by a test that a plain text upload still comes back verbatim.Model Used
Claude Opus 5 (
claude-opus-5)Closes #16775
Refs #16772
Single-issue rationale: widening the upload allowlist is a different risk from the content verification it depends on (#16773), which is why it is stacked on that PR rather than batched with it.
🤖 Generated with Claude Code