can1357/oh-my-pi · error · HTTPException
remote url contains forbidden control bytes
Error message
remote url contains forbidden control bytes
What it means
The proxy rejects remote URLs containing control bytes (\x00-\x1f, \x7f) or their percent-encoded forms (%00, %0a, %0d) with HTTP 400. Control characters in URLs enable argument injection and header/response splitting when passed to git or HTTP layers, so any URL matched by _FORBIDDEN_URL_BYTES_RE is refused before use.
Source
Thrown at python/robomp/src/proxy/server.py:344
raise HTTPException(400, "remote url must not specify a port")
if (parsed.hostname or "").lower() != "github.com":
raise HTTPException(400, f"remote url host must be github.com for repo {expected_repo!r}")
if parsed.params or parsed.query or parsed.fragment:
raise HTTPException(400, "remote url must not contain params, query, or fragment")
path = parsed.path.strip("/")
if path.endswith(".git"):
path = path[:-4]
if path.lower() != expected_repo.lower():
raise HTTPException(400, f"remote url does not match repo {expected_repo!r}")
return _github_url_for_repo(expected_repo)
def _remote_auth_for_url(url: str, expected_repo: str, token: str) -> _RemoteAuth:
raw = url.strip()
if not raw or raw != url:
raise HTTPException(400, "remote url must not be empty or padded")
if _FORBIDDEN_URL_BYTES_RE.search(raw):
raise HTTPException(400, "remote url contains forbidden control bytes")
if raw.startswith("-"):
raise HTTPException(400, "remote url must not start with '-'")
if _REMOTE_HELPER_RE.match(raw):
raise HTTPException(400, "git remote helper transports are disabled")
scheme = (urlparse(raw).scheme or "").lower()
if scheme in ("http", "https"):
normalized = _normalized_github_https_url(raw, expected_repo)
return _RemoteAuth(url=normalized, token=token, auth_url=normalized)
return _RemoteAuth(url=raw, token=None, auth_url=None)
def _clone_remote_auth(clone_url: str, expected_repo: str, token: str) -> _RemoteAuth:
try:
return _remote_auth_for_url(clone_url, expected_repo, token)
except HTTPException:
log.warning(
"gh-proxy: refusing clone — clone_url is not permitted",
extra={"expected_repo": expected_repo},View on GitHub (pinned to 9690622007)
Solutions
- Remove all control characters from the URL; keep it on a single printable line
- If a value may contain them, sanitize: url = re.sub(r'[\x00-\x1f\x7f]', '', url) and re-encode intentionally
- Quote YAML scalar values and use single-line strings for URLs
Example fix
// before const url = `https://github.com/o/r.git\n`; // after const url = "https://github.com/o/r.git".replace(/[\x00-\x1f\x7f]/g, "");
Defensive patterns
Strategy: validation
Validate before calling
if /[\x00-\x1f\x7f]|%(?:00|0a|0d)/i.test(url) throw new Error("control bytes in remote url"); Type guard
function hasNoControlBytes(u: unknown): u is string {
return typeof u === "string" && !/[\x00-\x1f\x7f]/.test(u) && !/%(?:00|0a|0d)/i.test(u);
} Prevention
- Keep URL values on a single line in config files; quote YAML scalars
- Sanitize any value scraped from logs or terminals before use
- Never build URLs by concatenating untrusted raw input
When it happens
Trigger: Supplying a URL containing raw newlines, carriage returns, tabs, NUL bytes, or percent-encoded %0a/%0d/%00 sequences to an endpoint that resolves to _clone_remote_auth or _origin_remote_auth.
Common situations: Multi-line YAML strings folding newlines into a URL value; log-file scraped values with embedded \r\n; crafted URLs from untrusted input testing CRLF injection; copying URLs from terminals that wrapped lines.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Invalid package name: ${name}
- Searching from root directory '/' is not allowed
- missing/invalid 'slot_uid'
- invalid '{field}': must be array of strings
- missing/invalid 'comments'
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/b3399b9819049b7a.
Report an issue: GitHub.