{"record":{"id":"3917b84b7820bc54","repo":"docling-project/docling","slug":"invalid-tesseract-language-identifier-lang-r-l","errorCode":null,"errorMessage":"Invalid Tesseract language identifier: {lang!r}. Language identifiers must only contain alphanumeric characters, underscores, hyphens, forward slashes, and plus signs.","messagePattern":"Invalid Tesseract language identifier: (.+?)\\. Language identifiers must only contain alphanumeric characters, underscores, hyphens, forward slashes, and plus signs\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/models/stages/ocr/tesseract_ocr_cli_model.py","lineNumber":98,"sourceCode":"                self._set_languages_and_prefix()\n\n            except Exception as exc:\n                raise RuntimeError(\n                    f\"Tesseract is not available, aborting: {exc} \"\n                    \"Install tesseract on your system and the tesseract binary is discoverable. \"\n                    \"The actual command for Tesseract can be specified in `pipeline_options.ocr_options.tesseract_cmd='tesseract'`. \"\n                    \"Alternatively, Docling has support for other OCR engines. See the documentation.\"\n                )\n\n    @staticmethod\n    def _sanitize_lang(lang: str) -> str:\n        \"\"\"Validate and sanitize a Tesseract language identifier to prevent argument injection.\n\n        Valid identifiers (e.g. ``eng``, ``script/Latin``, ``eng+deu``) contain only\n        alphanumeric characters, underscores, hyphens, forward slashes, and plus signs.\n        \"\"\"\n        if not _VALID_LANG_RE.match(lang):\n            raise ValueError(\n                f\"Invalid Tesseract language identifier: {lang!r}. \"\n                \"Language identifiers must only contain alphanumeric characters, \"\n                \"underscores, hyphens, forward slashes, and plus signs.\"\n            )\n        return lang\n\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:","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/models/stages/ocr/tesseract_ocr_cli_model.py#L80-L116","documentation":"Before passing language tokens to the Tesseract CLI, Docling validates each one against _VALID_LANG_RE (alphanumerics, underscores, hyphens, forward slashes, plus signs — e.g. 'eng', 'script/Latin', 'eng+deu'). Any character outside that set raises this ValueError; this guard prevents argument injection into the tesseract command line.","triggerScenarios":"TesseractOcrOptions(lang=[...]) containing tokens with spaces, quotes, shell metacharacters, semicolons, or other invalid characters. Validation also runs for any configured lang token other than 'auto'.","commonSituations":"Language lists loaded from user input, JSON/YAML config, or LLM-generated configs; tokens like 'eng deu' (space instead of '+'), 'eng;rm -rf' (injection attempt), or trailing punctuation.","solutions":["Use clean BCP-47/Tesseract language tokens: 'eng', 'deu', 'eng+deu', 'script/Latin'.","Sanitize config-sourced language strings before passing them (strip whitespace, split multi-language tokens with '+').","If you dynamically build lang lists, validate each token with the same rule: ^[A-Za-z0-9_/+\\-]+$."],"exampleFix":"# before\nTesseractOcrOptions(lang=[\"eng deu\"])\n\n# after\nTesseractOcrOptions(lang=[\"eng+deu\"])","handlingStrategy":"validation","validationCode":"import re\n_VALID_LANG_RE = re.compile(r\"^[A-Za-z0-9_/+\\-]+$\")\n\ndef sanitize_langs(langs: list[str]) -> list[str]:\n    bad = [l for l in langs if not _VALID_LANG_RE.match(l)]\n    if bad:\n        raise ValueError(f\"invalid tesseract language tokens: {bad}\")\n    return langs","typeGuard":"import re\n\ndef is_valid_tesseract_lang(token: str) -> bool:\n    return bool(re.fullmatch(r\"[A-Za-z0-9_/+\\-]+\", token))","tryCatchPattern":"try:\n    TesseractOcrCliModel(options=TesseractCliOcrOptions(lang=lang_list))\nexcept ValueError as e:\n    if \"Invalid Tesseract language identifier\" in str(e):\n        lang_list = [t for t in lang_list if is_valid_tesseract_lang(t)] or [\"eng\"]\n    else:\n        raise","preventionTips":["Never pass raw user input as tesseract lang tokens; validate with a whitelist regex.","Split multi-language specs with '+' rather than spaces or commas.","Log rejected tokens to detect injection attempts early."],"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"}