{"record":{"id":"3e1ba3bdc8b95a4f","repo":"phacility/phabricator","slug":"uri-s-is-not-a-valid-fetchable-resource-a-vali-3e1ba3","errorCode":null,"errorMessage":"URI \"%s\" is not a valid fetchable resource. A valid fetchable resource URI must use one of these protocols: %s.","messagePattern":"URI \"(.+?)\" is not a valid fetchable resource\\. A valid fetchable resource URI must use one of these protocols: (.+?)\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/infrastructure/env/PhabricatorEnv.php","lineNumber":806,"sourceCode":"   */\n  public static function requireValidRemoteURIForFetch(\n    $raw_uri,\n    array $protocols) {\n\n    $uri = new PhutilURI($raw_uri);\n\n    $proto = $uri->getProtocol();\n    if (!strlen($proto)) {\n      throw new Exception(\n        pht(\n          'URI \"%s\" is not a valid fetchable resource. A valid fetchable '.\n          'resource URI must specify a protocol.',\n          $raw_uri));\n    }\n\n    $protocols = array_fuse($protocols);\n    if (!isset($protocols[$proto])) {\n      throw new Exception(\n        pht(\n          'URI \"%s\" is not a valid fetchable resource. A valid fetchable '.\n          'resource URI must use one of these protocols: %s.',\n          $raw_uri,\n          implode(', ', array_keys($protocols))));\n    }\n\n    $domain = $uri->getDomain();\n    if (!strlen($domain)) {\n      throw new Exception(\n        pht(\n          'URI \"%s\" is not a valid fetchable resource. A valid fetchable '.\n          'resource URI must specify a domain.',\n          $raw_uri));\n    }\n\n    $addresses = gethostbynamel($domain);\n    if (!$addresses) {","sourceCodeStart":788,"sourceCodeEnd":824,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/env/PhabricatorEnv.php#L788-L824","documentation":"Second gate of requireValidRemoteURIForFetch(): the URI's protocol must be in the caller-provided protocol list (array_fuse turns it into a lookup map). Even syntactically valid schemes like 'ftp://' or 'file://' are refused because the fetching code path only speaks the protocols it declared. The message prints the accepted list to make the mismatch obvious.","triggerScenarios":"requireValidRemoteURIForFetch($uri, array('https')) called with 'http://example.com/x' (http not in list), or repository/image URLs using git://, ftp://, or file:// schemes where only http/https are allowed by the call site.","commonSituations":"Hardening a call site from array('http','https') down to https-only and older stored http:// URLs now failing; users pasting ftp:// or file:// links into fields that trigger server-side fetching; custom fetchers forgetting to include their scheme in the allowed list.","solutions":["Change the URI to a scheme the call site allows (usually https).","If the scheme is legitimately fetchable, widen the caller's protocol argument - this is per-call-site in code, not config - after confirming the downstream HTTP client actually supports it.","Normalize stored http:// URLs to https:// when the destination supports TLS rather than widening the whitelist."],"exampleFix":"// before: call site allows https only\nPhabricatorEnv::requireValidRemoteURIForFetch('http://cdn.example.com/a.png', array('https'));\n// throws\n\n// after: upgrade the target or widen deliberately\nPhabricatorEnv::requireValidRemoteURIForFetch('https://cdn.example.com/a.png', array('https'));","handlingStrategy":"validation","validationCode":"$proto = (new PhutilURI($url))->getProtocol();\nif (!in_array($proto, array('http', 'https'), true)) {\n  // reject or upgrade before the fetch validator throws\n  $url = preg_replace('#^http:#', 'https:', $url);\n}","typeGuard":null,"tryCatchPattern":"try {\n  PhabricatorEnv::requireValidRemoteURIForFetch($url, $allowed);\n} catch (Exception $ex) {\n  return array('err' => $ex->getMessage()); // graceful per-item failure in bulk imports\n}","preventionTips":["Centralize the allowed-protocol list per feature instead of ad-hoc arrays at each call site.","When tightening http->https, migrate stored URLs in the same deploy.","Log the rejected protocol so users can self-correct their links."],"tags":["phabricator","uri","protocol-whitelist","fetch","ssrf","security"],"backgroundTag":"uri-protocol-not-allowed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}