{"record":{"id":"ba391b62833ac5ce","repo":"ComposioHQ/composio","slug":"refusing-to-build-a-path-from-a-reserved-device-na","errorCode":null,"errorMessage":"Refusing to build a path from a reserved device name as {label}: {value!r}","messagePattern":"Refusing to build a path from a reserved device name as (.+?): (.+?)","errorType":"validation","errorClass":"UnsafePathComponentError","httpStatus":null,"severity":"critical","filePath":"python/composio/utils/safe_path.py","lineNumber":137,"sourceCode":"            f\"({len(value)} characters)\"\n        )\n\n    # `.` and `..` are excluded by the regex (no `.` in the character class),\n    # as are NUL bytes and every separator. The explicit checks above exist to\n    # produce a precise error message rather than a generic pattern mismatch.\n    #\n    # `fullmatch`, not `match`: in a `match`, `$` also matches just before a\n    # single trailing newline, so `\"GMAIL\\n\"` would satisfy `^[A-Za-z0-9_-]+$`\n    # and reach the filesystem with a control character in the name.\n    if not SAFE_COMPONENT_REGEX.fullmatch(value):\n        raise UnsafePathComponentError(\n            f\"Refusing to build a path from an unsafe {label}: {value!r}. \"\n            f\"Expected only letters, digits, underscores, and hyphens \"\n            f\"(pattern {SAFE_COMPONENT_REGEX.pattern}).\"\n        )\n\n    if value.upper() in WINDOWS_RESERVED_NAMES:\n        raise UnsafePathComponentError(\n            f\"Refusing to build a path from a reserved device name as {label}: {value!r}\"\n        )\n\n    return value\n\n\ndef safe_basename(name: str, *, label: str = \"filename\") -> str:\n    \"\"\"Collapse an untrusted filename to a bare, writable basename.\n\n    Filenames need their own validator: :func:`assert_safe_path_component`\n    forbids ``.``, which nearly every real filename contains. This applies the\n    remaining checks — no separators, no traversal, no NUL, bounded length, no\n    reserved device name — to the one component a server most directly controls.\n\n    ``PureWindowsPath`` treats both ``/`` and ``\\\\`` as separators, so a name\n    crafted for a Windows target (``..\\\\..\\\\evil``) is stripped even when the\n    SDK runs on POSIX, where ``Path(...).name`` would return it intact.\n","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/python/composio/utils/safe_path.py#L119-L155","documentation":"assert_safe_path_component rejects Windows reserved DOS device names (CON, PRN, AUX, NUL, COM1-9, LPT1-9, superscript variants) case-insensitively, because writing to one on Windows targets the device instead of a file — on every platform, not just Windows.","triggerScenarios":"secure_join(root, 'NUL'), secure_join(root, 'com1'), secure_join(root, 'AUX') — an untrusted component matching a reserved device name in any case.","commonSituations":"Malicious or unlucky IDs/downloads named after devices; tests exercising the guardrail; cross-platform code where a POSIX-only check would let these through.","solutions":["Rename the component (prefix or suffix it, e.g. 'NUL_file' → 'upload_NUL')","Reject/ignore the untrusted value rather than trying to write it"],"exampleFix":"# before\nsecure_join(root, \"nul\")\n# after\nsecure_join(root, \"download_nul\")","handlingStrategy":"validation","validationCode":"from composio.utils.safe_path import WINDOWS_RESERVED_NAMES\ndef not_reserved(v):\n    return v.upper() not in WINDOWS_RESERVED_NAMES","typeGuard":"from composio.utils.safe_path import WINDOWS_RESERVED_NAMES\ndef is_non_device_name(v: str) -> bool:\n    return v.upper() not in WINDOWS_RESERVED_NAMES","tryCatchPattern":"from composio.exceptions import UnsafePathComponentError\ntry:\n    p = secure_join(root, name)\nexcept UnsafePathComponentError:\n    p = secure_join(root, 'dl_' + name)","preventionTips":["Prefix device-like names ('nul', 'com1') before using them as components","Remember the check is case-insensitive and cross-platform"],"tags":["windows","reserved-names","security","python"],"backgroundTag":"windows-reserved-device-name","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}