{"record":{"id":"52f9116e6ab694fd","repo":"phacility/phabricator","slug":"unable-to-test-remote-address-against-cluster-whit","errorCode":null,"errorMessage":"Unable to test remote address against cluster whitelist: REMOTE_ADDR is not defined or not valid.","messagePattern":"Unable to test remote address against cluster whitelist: REMOTE_ADDR is not defined or not valid\\.","errorType":"exception","errorClass":"Exception","httpStatus":500,"severity":"error","filePath":"src/infrastructure/env/PhabricatorEnv.php","lineNumber":873,"sourceCode":"   *\n   * @param string IP address.\n   * @return bool True if the address is blacklisted.\n   */\n  public static function isBlacklistedOutboundAddress($address) {\n    $blacklist = self::getEnvConfig('security.outbound-blacklist');\n\n    return PhutilCIDRList::newList($blacklist)->containsAddress($address);\n  }\n\n  public static function isClusterRemoteAddress() {\n    $cluster_addresses = self::getEnvConfig('cluster.addresses');\n    if (!$cluster_addresses) {\n      return false;\n    }\n\n    $address = self::getRemoteAddress();\n    if (!$address) {\n      throw new Exception(\n        pht(\n          'Unable to test remote address against cluster whitelist: '.\n          'REMOTE_ADDR is not defined or not valid.'));\n    }\n\n    return self::isClusterAddress($address);\n  }\n\n  public static function isClusterAddress($address) {\n    $cluster_addresses = self::getEnvConfig('cluster.addresses');\n    if (!$cluster_addresses) {\n      throw new Exception(\n        pht(\n          'This server is not configured to serve cluster requests. '.\n          'Set `cluster.addresses` in the configuration to whitelist '.\n          'cluster hosts before sending requests that use a cluster '.\n          'authentication mechanism.'));\n    }","sourceCodeStart":855,"sourceCodeEnd":891,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/infrastructure/env/PhabricatorEnv.php#L855-L891","documentation":"PhabricatorEnv::isClusterRemoteAddress() decides whether the current client is a cluster node: if `cluster.addresses` is configured it must classify the peer, which requires a remote address. getRemoteAddress() reads REMOTE_ADDR (honoring trusted proxy headers); when it is absent or unparseable - typically in CLI/daemon contexts where no HTTP peer exists - classification is impossible and the method throws instead of guessing. Failing closed here is deliberate: cluster auth decisions must not default to trust.","triggerScenarios":"Calling PhabricatorEnv::isClusterRemoteAddress() from a script, daemon, or worker (no REMOTE_ADDR), or from a web request where a misconfigured load balancer strips REMOTE_ADDR and no trusted X-Forwarded-For handling recovers it, while `cluster.addresses` is non-empty.","commonSituations":"Running bin scripts on a clustered install (cluster.addresses set) after an upgrade introduced cluster-auth checks into that code path; load balancers in TCP mode not setting REMOTE_ADDR; unit tests invoking cluster auth logic outside a request.","solutions":["Only invoke cluster-auth paths within a real web request; for CLI code, branch on php_sapi_name() !== 'cli' before calling isClusterRemoteAddress().","Fix the edge network: ensure REMOTE_ADDR reaches PHP (LB in HTTP mode, or configure trusted-proxy headers so getRemoteAddress() can recover the client address).","Check `cluster.addresses` is actually intended - if this host is not part of a cluster, removing the config removes the requirement."],"exampleFix":"// before\n$is_cluster = PhabricatorEnv::isClusterRemoteAddress(); // throws in CLI\n\n// after\nif (php_sapi_name() === 'cli') {\n  $is_cluster = false; // no remote peer exists on the command line\n} else {\n  $is_cluster = PhabricatorEnv::isClusterRemoteAddress();\n}","handlingStrategy":"type-guard","validationCode":"if (php_sapi_name() === 'cli' && PhabricatorEnv::getEnvConfig('cluster.addresses')) {\n  // no REMOTE_ADDR exists on the CLI; do not call isClusterRemoteAddress()\n  return false;\n}","typeGuard":"function hasClassifiableRemoteAddress() {\n  if (php_sapi_name() === 'cli') {\n    return false;\n  }\n  return (bool) PhabricatorEnv::getRemoteAddress();\n}","tryCatchPattern":"try {\n  $trusted = PhabricatorEnv::isClusterRemoteAddress();\n} catch (Exception $ex) {\n  // fail closed: unknown peer is never treated as cluster\n  $trusted = false;\n  phlog($ex); // but surface the misconfiguration loudly\n}","preventionTips":["Gate cluster-auth code on web context; daemons and scripts have no peer address.","Ensure your load balancer terminates HTTP and always sets REMOTE_ADDR, or configure trusted proxies.","Fail closed and log when classification is impossible - never default to trusted."],"tags":["phabricator","cluster","remote-addr","load-balancer","cli","security"],"backgroundTag":"missing-remote-addr","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}