{"record":{"id":"04328ac20e21ce81","repo":"CloakHQ/CloakBrowser","slug":"cloakbrowser-malformed-socks5-proxy-url-passing","errorCode":null,"errorMessage":"[cloakbrowser] Malformed SOCKS5 proxy URL, passing through unchanged: invalid port","messagePattern":"\\[cloakbrowser\\] Malformed SOCKS5 proxy URL, passing through unchanged: invalid port","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"js/src/proxy.ts","lineNumber":127,"sourceCode":"  // Python urlparse's rpartition('@') behavior.\n  const schemeMatch = urlStr.match(/^([a-z][a-z0-9+\\-.]*):\\/\\/(.*)$/i);\n  if (!schemeMatch) return urlStr;\n  const [, scheme, rest] = schemeMatch;\n  const hostStart = rest.search(/[/?#]/);\n  const authority = hostStart === -1 ? rest : rest.slice(0, hostStart);\n  const suffix = hostStart === -1 ? \"\" : rest.slice(hostStart);\n  const atIdx = authority.lastIndexOf(\"@\");\n  if (atIdx === -1) return urlStr;  // no creds\n  const userinfo = authority.slice(0, atIdx);\n  const hostPart = authority.slice(atIdx + 1);\n  // Validate port (matches Python's urlparse().port ValueError guard).\n  // Extract port after last ':' — but skip IPv6 brackets (e.g. [::1]:1080).\n  const bracketEnd = hostPart.lastIndexOf(\"]\");\n  const portColonIdx = hostPart.indexOf(\":\", Math.max(bracketEnd, 0));\n  if (portColonIdx !== -1) {\n    const portStr = hostPart.slice(portColonIdx + 1);\n    if (portStr && !/^\\d+$/.test(portStr)) {\n      console.warn(`[cloakbrowser] Malformed SOCKS5 proxy URL, passing through unchanged: invalid port`);\n      return urlStr;\n    }\n  }\n  const hostAndRest = hostPart + suffix;\n  const colonIdx = userinfo.indexOf(\":\");\n  const rawUserEnc = colonIdx === -1 ? userinfo : userinfo.slice(0, colonIdx);\n  const hasPassword = colonIdx !== -1;\n  const rawPassEnc = hasPassword ? userinfo.slice(colonIdx + 1) : \"\";\n  try {\n    const encUser = rawUserEnc ? encodeURIComponent(lenientDecodeURIComponent(rawUserEnc)) : \"\";\n    const encPass = hasPassword\n      ? (rawPassEnc ? encodeURIComponent(lenientDecodeURIComponent(rawPassEnc)) : \"\")\n      : null;\n    const normalized = assembleSocksUrl(scheme, encUser, encPass, hostAndRest);\n    // Compare credentials, not the full URL: keeps the log condition focused\n    // on real encoding work, not cosmetic differences (parity with the Python\n    // implementation, which has to skip urlparse's hostname lowercasing).\n    const credsChanged = encUser !== rawUserEnc","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/CloakHQ/CloakBrowser/blob/d6bad5de261bedf025280ace1d14e800aee13923/js/src/proxy.ts#L109-L145","documentation":"The SOCKS5 proxy URL normalizer found a non-numeric port segment (e.g. socks5://user:pass@host:abc) and cannot parse it safely. Rather than mangling the URL, it logs this warning and returns the string unchanged, so whatever you passed is handed to Chromium as-is and will likely fail at connection time.","triggerScenarios":"Passing proxy: 'socks5://host:1080x' or 'socks5://host:notaport' to resolveProxyConfig/launch. The regex /^\\d+$/ on the substring after the last colon (post IPv6-bracket handling) fails, e.g. also 'socks5://host:1080/path' with a suffix misparsed as port.","commonSituations":"Typos in proxy strings, pasting URLs with trailing paths or whitespace, templating bugs that inject undefined into the port position, credentials containing ':' shifting the parse.","solutions":["Fix the proxy URL so the port is purely digits: socks5://user:pass@host:1080.","Verify no trailing path, query, or whitespace after the port; strip the string before passing.","If using IPv6, wrap the host in brackets: socks5://[::1]:1080.","URL-encode credentials containing special characters (or the auto-encoder handles it once the port is valid)."],"exampleFix":"// before\nconst proxy = 'socks5://user:p@ss@proxy.example.com:10abc';\n\n// after\nconst proxy = 'socks5://user:p%40ss@proxy.example.com:1080';","handlingStrategy":"validation","validationCode":"function isValidSocksUrl(u: string): boolean {\n  try {\n    const parsed = new URL(u);\n    if (!/^socks5h?:$/.test(parsed.protocol)) return false;\n    return parsed.port === '' || /^\\d+$/.test(parsed.port);\n  } catch { return false; }\n}\nif (!isValidSocksUrl(proxy)) throw new Error(`bad SOCKS5 proxy URL: ${proxy}`);","typeGuard":"const isWellFormedSocksUrl = (u: string): boolean =>\n  /^socks5h?:\\/\\/[^\\s]+@?\\[[^\\]]+\\]|[^:@\\s]+:\\d+(\\/)?$/.test(u.trim());","tryCatchPattern":null,"preventionTips":["Build proxy URLs from components (host, numeric port, encoded credentials) instead of string concatenation.","Bracket IPv6 hosts; trim env-var values.","Validate with new URL() in a preflight check in test suites."],"tags":["proxy","socks5","url-parsing"],"backgroundTag":"malformed-proxy-url","analyzedSha":"d6bad5de261bedf025280ace1d14e800aee13923","analyzedAt":"2026-08-28T14:13:12.918Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}