{"record":{"id":"c041527cd8f53b77","repo":"joewalnes/websocketd","slug":"origin-list-matches-were-not-found","errorCode":null,"errorMessage":"origin list matches were not found","messagePattern":"origin list matches were not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libwebsocketd/http.go","lineNumber":385,"sourceCode":"\t\tif err != nil {\n\t\t\tlog.Access(\"session\", \"Origin hostname parsing error: %s\", err)\n\t\t\treturn err\n\t\t}\n\t\tif config.SameOrigin {\n\t\t\tlocalServer, localPort, err := tellHostPort(req.Host, req.TLS != nil)\n\t\t\tif err != nil {\n\t\t\t\tlog.Access(\"session\", \"Request hostname parsing error: %s\", err)\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif originServer != localServer || originPort != localPort {\n\t\t\t\tlog.Access(\"session\", \"Same origin policy mismatch\")\n\t\t\t\treturn fmt.Errorf(\"same origin policy violated\")\n\t\t\t}\n\t\t}\n\t\tif config.AllowOrigins != nil {\n\t\t\tif !matchOrigin(originServer, originPort, originParsed.Scheme, config.AllowOrigins) {\n\t\t\t\tlog.Access(\"session\", \"Origin is not listed in allowed list\")\n\t\t\t\treturn fmt.Errorf(\"origin list matches were not found\")\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// matchOrigin checks if the given origin server/port/scheme matches any entry\n// in the allowed origins list. Extracted for testability.\n//\n// Port semantics (issue #473): an entry with an explicit port matches that\n// port only. A portless entry matches only the scheme's default port (80 for\n// http, 443 for https — both, if the entry carries no scheme). Appending\n// \":*\" opts back in to matching any port, e.g. --origin=trusted.com:*, for\n// setups where every service on the host is trusted. Portless entries used\n// to match any port implicitly, so a single allowlisted host also vouched\n// for whatever else happened to listen on its other ports.\nfunc matchOrigin(originServer, originPort, originScheme string, allowedOrigins []string) bool {\n\tfor _, allowed := range allowedOrigins {","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/joewalnes/websocketd/blob/7a8683dc7f9778dc615945aaed2a8dc77290227b/libwebsocketd/http.go#L367-L403","documentation":"Raised when config.AllowOrigins is non-nil (the operator passed --origin entries) but matchOrigin finds no entry matching the request's origin host, port, and scheme. Like the same-origin violation, it causes the WebSocket handshake to be answered with 403 by gorilla's Upgrader. It is the allow-list counterpart of the implicit same-origin policy.","triggerScenarios":"Client's Origin header (scheme, host, port) does not match any entry in --origin: wrong port, http vs https scheme mismatch, subdomain not listed, wildcard pattern not covering the actual origin, or trailing-slash/scheme-case differences.","commonSituations":"Typo or stale port in --origin after redeploying the frontend; switching the frontend to https while the allow-list still says http; wildcard misconfigured so *.example.com doesn't match example.com itself; multi-environment deployments sharing one origin list.","solutions":["Compare the browser console / access log's reported origin against each --origin entry and correct scheme, host, and port.","Use a wildcard pattern in --origin (e.g. --origin=*.example.com) if the frontend moves between subdomains or ports.","Include both http and https variants during a TLS migration.","Verify no proxy strips or alters the Origin header before it reaches websocketd."],"exampleFix":"// before\nwebsocketd --port=8080 --origin=http://localhost:3000 ./chat.sh\n// after (frontend migrated to https:3001)\nwebsocketd --port=8080 --origin=http://localhost:3000 --origin=https://localhost:3001 ./chat.sh","handlingStrategy":"validation","validationCode":"function originAllowed(origin, allowList) {\n  return allowList.some(pattern => pattern === origin || matchGlob(pattern, origin));\n}\nif (!originAllowed('https://localhost:3001', ['http://localhost:3000'])) console.warn('origin not in --origin list');","typeGuard":null,"tryCatchPattern":"const ws = new WebSocket(url);\nws.onerror = () => fetch(url.replace('ws','http')).then(r => {\n  if (r.status === 403) console.error('origin not allowed: check --origin entries');\n});","preventionTips":["Keep the --origin list in the same deploy artifact/config as the frontend URL so they move together.","Include both scheme variants (http/https) during TLS migrations.","Test the handshake with the exact browser origin string shown in the console after every frontend URL change.","Remember scheme and port are significant: https://example.com ≠ http://example.com ≠ https://example.com:8443."],"tags":["websocket","security","cors","origin","configuration"],"backgroundTag":"websocket-origin-not-allowed","analyzedSha":"7a8683dc7f9778dc615945aaed2a8dc77290227b","analyzedAt":"2026-09-03T13:52:22.309Z","contentChangedAt":"2026-09-03T13:52:22.309Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}