{"record":{"id":"405399816676d68b","repo":"docling-project/docling","slug":"invalid-tesseract-command-contains-null-byte","errorCode":null,"errorMessage":"Invalid Tesseract command: contains null byte.","messagePattern":"Invalid Tesseract command: contains null byte\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/models/stages/ocr/tesseract_ocr_cli_model.py","lineNumber":122,"sourceCode":"\n    @staticmethod\n    def _sanitize_path(path: str) -> str:\n        \"\"\"Validate and sanitize a Tesseract data directory path to prevent argument injection.\n\n        Rejects paths containing null bytes and resolves the path to an absolute form.\n        \"\"\"\n        if \"\\x00\" in path:\n            raise ValueError(\"Invalid Tesseract data path: contains null byte.\")\n        return str(Path(path).resolve())\n\n    @staticmethod\n    def _sanitize_cmd(cmd: str) -> str:\n        \"\"\"Validate and sanitize the Tesseract executable name/path to prevent injection.\n\n        Rejects values containing null bytes.\n        \"\"\"\n        if \"\\x00\" in cmd:\n            raise ValueError(\"Invalid Tesseract command: contains null byte.\")\n        return cmd\n\n    @staticmethod\n    def _sanitize_filename(filename: str) -> str:\n        \"\"\"Validate and sanitize a filename passed to the Tesseract CLI.\n\n        Rejects paths containing null bytes and resolves to an absolute path.\n        \"\"\"\n        if \"\\x00\" in filename:\n            raise ValueError(\"Invalid filename: contains null byte.\")\n        return str(Path(filename).resolve())\n\n    def _get_name_and_version(self) -> Tuple[str, str]:\n        if self._name is not None and self._version is not None:\n            return self._name, self._version  # type: ignore\n\n        cmd = [self._safe_tesseract_cmd, \"--version\"]\n","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/models/stages/ocr/tesseract_ocr_cli_model.py#L104-L140","documentation":"The tesseract_cmd option (name or path of the tesseract executable) is validated before being used to spawn the CLI process. A value containing a NUL byte is rejected with this ValueError, because NUL bytes cannot appear in real executable paths and indicate malformed or malicious input.","triggerScenarios":"Setting pipeline_options.ocr_options.tesseract_cmd to a string containing \\x00, typically from unsanitized configuration or user-supplied settings.","commonSituations":"Config strings sourced from untrusted input or from decodes of binary data; rarely a hand-typed mistake, more often an injection probe against the subprocess call.","solutions":["Set tesseract_cmd to a clean executable name or absolute path, e.g. 'tesseract' or '/usr/bin/tesseract'.","Strip control characters from any externally sourced value before assigning it to tesseract_cmd.","Confirm with repr() that the value contains no \\x00."],"exampleFix":"# before\nocr_options.tesseract_cmd = \"tesseract\\x00\"\n\n# after\nocr_options.tesseract_cmd = \"/usr/bin/tesseract\"","handlingStrategy":"validation","validationCode":"def safe_cmd(cmd: str) -> str:\n    if \"\\x00\" in cmd:\n        raise ValueError(\"tesseract_cmd contains NUL byte\")\n    return cmd\n\nocr_options.tesseract_cmd = safe_cmd(settings[\"tesseract_cmd\"])","typeGuard":"def is_nul_free_cmd(cmd: str) -> bool:\n    return \"\\x00\" not in cmd and bool(cmd.strip())","tryCatchPattern":"try:\n    TesseractOcrCliModel(options=opts)\nexcept ValueError as e:\n    if \"Invalid Tesseract command\" in str(e):\n        opts.tesseract_cmd = \"tesseract\"  # reset to default binary\n    else:\n        raise","preventionTips":["Source tesseract_cmd only from trusted configuration, not request data.","Prefer an absolute path resolved via shutil.which() over free-form strings.","Add a NUL/control-character check to config schema validation."],"tags":["ocr","tesseract","validation","security","injection"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}