{"record":{"id":"aa6974f1237fa2c7","repo":"XX-net/XX-Net","slug":"web-control-ref-s-host-s","errorCode":null,"errorMessage":"web control ref:%s host:%s","messagePattern":"web control ref:(.+?) host:(.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"code/default/launcher/web_control.py","lineNumber":132,"sourceCode":"                \"Access-Control-Allow-Origin\": origin,\n                \"Access-Control-Allow-Methods\": \"GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS\",\n                \"Access-Control-Allow-Headers\": \"Authorization,Content-Type\",\n            }\n            return self.send_response(headers=header)\n        except Exception as e:\n            xlog.exception(\"options fail:%r\", e)\n            return self.send_not_found()\n\n    def do_POST(self):\n        self.headers = utils.to_str(self.headers)\n        self.path = utils.to_str(self.path)\n\n        refer = self.headers.get('Referer')\n        if refer:\n            refer_loc = urlparse(refer).netloc\n            host = self.headers.get('Host')\n            if refer_loc != host and refer_loc not in config.allowed_refers:\n                xlog.warn(\"web control ref:%s host:%s\", refer_loc, host)\n                return\n\n            self.set_CORS(CORS_header)\n\n        try:\n            content_type = self.headers.get('Content-Type', \"\")\n            ctype, pdict = cgi.parse_header(content_type)\n            if ctype == 'multipart/form-data':\n                self.postvars = cgi.parse_multipart(self.rfile, pdict)\n            elif ctype == 'application/x-www-form-urlencoded':\n                length = int(self.headers.get('Content-Length'))\n                content = self.rfile.read(length)\n                self.postvars = parse_qs(content, keep_blank_values=True)\n                self.postvars = self.unpack_reqs(self.postvars)\n            elif ctype == 'application/json':\n                length = int(self.headers.get('Content-Length'))\n                content = self.rfile.read(length)\n                self.postvars = json.loads(content)","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/XX-net/XX-Net/blob/cfa5bc17b67676e467f37ec50766127e0ab5f0aa/code/default/launcher/web_control.py#L114-L150","documentation":"CSRF-style check in the POST handler of the web control console: if a Referer header is present and its netloc differs from the Host header and is not in config.allowed_refers, the request is dropped with this warning.","triggerScenarios":"POSTing to the control API from a page served on a different origin (different host/port) that isn't whitelisted in allowed_refers.","commonSituations":"Accessing the SWUI via 127.0.0.1 while the page was loaded from localhost (or vice versa), a changed control_port, or third-party pages attempting cross-origin requests.","solutions":["Use the exact same host:port in the browser address bar as the page/posts target.","Add the referring origin to allowed_refers in config.","Send requests without a Referer header or from the served UI itself."],"exampleFix":"// config\n\"allowed_refers\": [\"localhost:8085\", \"127.0.0.1:8085\"]","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\nref = urlparse(referer).netloc if referer else ''\nif ref and ref != host and ref not in config.allowed_refers:\n    raise PermissionError('cross-origin POST rejected')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Access the console via one canonical host:port.","Whitelist legitimate origins in allowed_refers.","Expect silent request drops when the check fails."],"tags":["security","csrf","web-ui","http"],"backgroundTag":"csrf-referer-rejected","analyzedSha":"cfa5bc17b67676e467f37ec50766127e0ab5f0aa","analyzedAt":"2026-08-27T19:28:28.225Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}