{"record":{"id":"b9c67db58a131cbc","repo":"OpenBMB/ChatDev","slug":"flags-are-not-allowed-in-packages-list-pkg","errorCode":null,"errorMessage":"flags are not allowed in packages list: {pkg}","messagePattern":"flags are not allowed in packages list: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"functions/function_calling/uv_related.py","lineNumber":75,"sourceCode":"        absolute = candidate if candidate.is_absolute() else self.workspace_root / candidate\n        absolute = absolute.expanduser().resolve()\n        if self.workspace_root not in absolute.parents and absolute != self.workspace_root:\n            raise ValueError(\"script path is outside workspace root\")\n        return absolute\n\n\ndef _validate_packages(packages: Sequence[str]) -> List[str]:\n    normalized: List[str] = []\n    for pkg in packages:\n        if not isinstance(pkg, str):\n            raise ValueError(\"package entries must be strings\")\n        stripped = pkg.strip()\n        if not stripped:\n            raise ValueError(\"package names cannot be empty\")\n        if not _SAFE_PACKAGE_RE.match(stripped):\n            raise ValueError(f\"unsafe characters detected in package spec {pkg}\")\n        if stripped.startswith(\"-\"):\n            raise ValueError(f\"flags are not allowed in packages list: {pkg}\")\n        normalized.append(stripped)\n    if not normalized:\n        raise ValueError(\"at least one package is required\")\n    return normalized\n\n\ndef _coerce_timeout_seconds(timeout_seconds: Any) -> float | None:\n    if timeout_seconds is None:\n        return None\n    if isinstance(timeout_seconds, bool):\n        raise ValueError(\"timeout_seconds must be a number\")\n    if isinstance(timeout_seconds, (int, float)):\n        value = float(timeout_seconds)\n    elif isinstance(timeout_seconds, str):\n        raw = timeout_seconds.strip()\n        if not raw:\n            raise ValueError(\"timeout_seconds cannot be empty\")\n        try:","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/functions/function_calling/uv_related.py#L57-L93","documentation":"After character-safety checks, _validate_packages rejects specs that begin with '-', since a leading dash would be interpreted as a command-line flag by uv (e.g. -e, --help, --requirement). This blocks argument-injection where a package entry smuggles an option into the subprocess. Note the check runs on the stripped spec, so ' -e' is caught but entries like 'pkg>-x' pattern checks happen earlier via the regex.","triggerScenarios":"Passing packages=[\"-e ./pkg\"] or [\"--requirement\", \"reqs.txt\"]; user input like \"--help\" supplied as a package name; specs beginning with a dash after whitespace stripping.","commonSituations":"Users trying to reuse pip/uv CLI flags (-e editable installs, -r requirements files) as package entries; injection attempts through unsanitized package fields; copy-pasting a uv pip install command and splitting all tokens into the packages list.","solutions":["Remove flag-style entries; express editable/requirements installs via a proper uv project (pyproject.toml) or the supported code path","Whitelist package names (alphanumerics plus limited constraint characters) before passing user input","Never interpolate raw CLI tokens into the packages list"],"exampleFix":"# before\ninstall_python_packages(packages=[\"-e\", \".\"])\n# after\n# editable install handled by project setup; only real specs passed\ninstall_python_packages(packages=[\"numpy\", \"pandas\"])","handlingStrategy":"validation","validationCode":"packages = [p.strip() for p in packages if not p.strip().startswith(\"-\")]\ninstall_python_packages(packages=packages, _context=ctx)","typeGuard":"def no_flag_entries(packages) -> bool:\n    return all(isinstance(p, str) and not p.strip().startswith(\"-\") for p in packages)","tryCatchPattern":"try:\n    install_python_packages(packages=packages, _context=ctx)\nexcept ValueError as e:\n    if \"flags are not allowed\" in str(e):\n        raise ValueError(f\"attempted CLI flag in packages: {e}\") from e\n    raise","preventionTips":["Never split a full 'uv pip install ...' command into the packages list","Handle -e/-r style installs through project tooling, not package entries","Treat leading-dash user input as hostile and reject it early"],"tags":["security","uv","packages","argument-injection"],"backgroundTag":"command-injection-guard","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}