{"record":{"id":"a0ef064c73b4e468","repo":"XTLS/Xray-core","slug":"scheme-must-be-https","errorCode":null,"errorMessage":"scheme must be https","messagePattern":"scheme must be https","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/geodata.go","lineNumber":37,"sourceCode":"\tif err := validateHTTPS(c.URL); err != nil {\n\t\treturn nil, errors.New(\"invalid geodata asset url: \", c.URL).Base(err)\n\t}\n\tif _, err := filesystem.StatAsset(c.File); err != nil {\n\t\treturn nil, errors.New(\"invalid geodata asset file: \", c.File).Base(err)\n\t}\n\treturn &geodata.Asset{\n\t\tUrl:  c.URL,\n\t\tFile: c.File,\n\t}, nil\n}\n\nfunc validateHTTPS(s string) error {\n\tu, err := url.ParseRequestURI(s)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif u.Scheme != \"https\" || u.Host == \"\" {\n\t\treturn errors.New(\"scheme must be https\")\n\t}\n\treturn nil\n}\n\ntype GeodataConfig struct {\n\tCron     *string               `json:\"cron\"`\n\tOutbound string                `json:\"outbound\"`\n\tAssets   []*GeodataAssetConfig `json:\"assets\"`\n}\n\nfunc (c *GeodataConfig) Build() (proto.Message, error) {\n\tconfig := &geodata.Config{}\n\n\tif c.Cron != nil {\n\t\tif _, err := cron.ParseStandard(*c.Cron); err != nil {\n\t\t\treturn nil, errors.New(\"invalid geodata cron\").Base(err)\n\t\t}\n\t\tconfig.Cron = *c.Cron","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/geodata.go#L19-L55","documentation":"Thrown by validateHTTPS in infra/conf/geodata.go when a URL parses successfully but its scheme is not exactly 'https' or its host is empty. This helper guards geodata asset download URLs (and is reached via error 283's wrapper). It enforces that all geodata downloads go over TLS to a named host.","triggerScenarios":"A geodata asset url like 'http://example.com/x.dat', 'ftp://example.com/x.dat', or 'https:///path-only' (https scheme but empty host). Also triggered indirectly by any other config field that routes through validateHTTPS.","commonSituations":"Using an http mirror because the https mirror is blocked or slow; URL strings that parse but lack a host component; config generators emitting scheme-less or http URLs.","solutions":["Change the URL scheme to https and include a host name","If the source only offers http, mirror the file on an https endpoint (e.g. your own server or an https-capable CDN) before referencing it"],"exampleFix":"// before\n\"url\": \"http://example.com/geoip.dat\"\n// after\n\"url\": \"https://example.com/geoip.dat\"","handlingStrategy":"validation","validationCode":"u, err := url.Parse(rawURL)\nif err != nil || u.Scheme != \"https\" || u.Host == \"\" {\n\treturn errors.New(\"URL must use https with a host\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reject http:// URLs at config-authoring time with a schema rule","Maintain an allowlist of https geodata mirrors"],"tags":["xray","config","geodata","https","url-validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}