{"record":{"id":"f77a88d5979a2540","repo":"can1357/oh-my-pi","slug":"git-remote-helper-transports-are-disabled","errorCode":null,"errorMessage":"git remote helper transports are disabled","messagePattern":"git remote helper transports are disabled","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"python/robomp/src/proxy/server.py","lineNumber":348,"sourceCode":"        raise HTTPException(400, \"remote url must not contain params, query, or fragment\")\n    path = parsed.path.strip(\"/\")\n    if path.endswith(\".git\"):\n        path = path[:-4]\n    if path.lower() != expected_repo.lower():\n        raise HTTPException(400, f\"remote url does not match repo {expected_repo!r}\")\n    return _github_url_for_repo(expected_repo)\n\n\ndef _remote_auth_for_url(url: str, expected_repo: str, token: str) -> _RemoteAuth:\n    raw = url.strip()\n    if not raw or raw != url:\n        raise HTTPException(400, \"remote url must not be empty or padded\")\n    if _FORBIDDEN_URL_BYTES_RE.search(raw):\n        raise HTTPException(400, \"remote url contains forbidden control bytes\")\n    if raw.startswith(\"-\"):\n        raise HTTPException(400, \"remote url must not start with '-'\")\n    if _REMOTE_HELPER_RE.match(raw):\n        raise HTTPException(400, \"git remote helper transports are disabled\")\n    scheme = (urlparse(raw).scheme or \"\").lower()\n    if scheme in (\"http\", \"https\"):\n        normalized = _normalized_github_https_url(raw, expected_repo)\n        return _RemoteAuth(url=normalized, token=token, auth_url=normalized)\n    return _RemoteAuth(url=raw, token=None, auth_url=None)\n\n\ndef _clone_remote_auth(clone_url: str, expected_repo: str, token: str) -> _RemoteAuth:\n    try:\n        return _remote_auth_for_url(clone_url, expected_repo, token)\n    except HTTPException:\n        log.warning(\n            \"gh-proxy: refusing clone — clone_url is not permitted\",\n            extra={\"expected_repo\": expected_repo},\n        )\n        raise\n\n","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/robomp/src/proxy/server.py#L330-L366","documentation":"The proxy disables git remote-helper transports. Any URL matching _REMOTE_HELPER_RE (r\"^[A-Za-z][A-Za-z0-9+.-]*::\", e.g. 'ext::sh -c ...') is refused with HTTP 400, because remote helpers can execute arbitrary commands and are a known git attack vector.","triggerScenarios":"Supplying a URL with a '<transport>::' prefix (e.g. 'ext::', 'git-remote-ext::') to an endpoint that resolves to _clone_remote_auth or _origin_remote_auth.","commonSituations":"Security research or exploit attempts using ext:: remote helpers; accidentally copying a documented helper URL into a repo field; tooling that emits transport-prefixed URLs.","solutions":["Use a normal transport (https:// or ssh) URL instead of a '<helper>::' URL","Remove the helper prefix and clone the underlying real remote directly","If you genuinely need a helper transport, do it locally with plain git outside the proxy"],"exampleFix":"// before\nclone({ repo: \"ext::sh -c git clone src dst\" })\n// after\nclone({ repo: \"https://github.com/org/repo.git\" })","handlingStrategy":"validation","validationCode":"if (/^[A-Za-z][A-Za-z0-9+.-]*::/.test(url)) throw new Error(\"remote helper transports are not allowed\");","typeGuard":"function isPlainTransportUrl(u: unknown): u is string {\n  return typeof u === \"string\" && /^(https?|ssh|git):\\/\\//.test(u) && !/^[A-Za-z][A-Za-z0-9+.-]*::/.test(u);\n}","tryCatchPattern":null,"preventionTips":["Use standard https/ssh remote URLs only","Reject any '<word>::' prefix at input boundaries","Do not pass user-supplied URLs straight into git clone without scheme allowlisting"],"tags":["http-400","security","git-remote-helper"],"backgroundTag":"url-validation-rejected","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}