{"record":{"id":"81a803d8221e8c39","repo":"ory/hydra","slug":"w-in-source-q-allowed-schemes-s","errorCode":null,"errorMessage":"%w: in source %q: allowed schemes: %s","messagePattern":"%w: in source %q: allowed schemes: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/fetcher/fetcher.go","lineNumber":122,"sourceCode":"}\n\n// FetchContext fetches the file contents from the source and allows to pass a\n// context that is used for HTTP requests.\nfunc (f *Fetcher) FetchContext(ctx context.Context, source string) (*bytes.Buffer, error) {\n\tb, err := f.FetchBytes(ctx, source)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn bytes.NewBuffer(b), nil\n}\n\n// FetchBytes fetches the file contents from the source and allows to pass a\n// context that is used for HTTP requests.\nfunc (f *Fetcher) FetchBytes(ctx context.Context, source string) ([]byte, error) {\n\tif !slices.ContainsFunc(f.schemes, func(scheme string) bool {\n\t\treturn strings.HasPrefix(source, scheme+\"://\")\n\t}) {\n\t\treturn nil, errors.WithStack(fmt.Errorf(\"%w: in source %q: allowed schemes: %s\", ErrUnknownScheme, redactedSource(source), strings.Join(f.schemes, \", \")))\n\t}\n\tswitch {\n\tcase strings.HasPrefix(source, \"http://\"), strings.HasPrefix(source, \"https://\"):\n\t\treturn f.fetchRemote(ctx, source)\n\tcase strings.HasPrefix(source, \"file://\"):\n\t\tb, err := os.ReadFile(strings.TrimPrefix(source, \"file://\"))\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"read file: %s\", redactedSource(source))\n\t\t}\n\t\treturn b, nil\n\tcase strings.HasPrefix(source, \"base64://\"):\n\t\tsrc, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(source, \"base64://\"))\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"base64decode: %s\", redactedSource(source))\n\t\t}\n\t\treturn src, nil\n\tdefault:\n\t\treturn nil, errors.Wrap(ErrUnknownScheme, \"unknown scheme in source: \"+redactedSource(source))","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/fetcher/fetcher.go#L104-L140","documentation":"fetcher.FetchBytes validates the URL scheme against the fetcher's allowed scheme list (f.schemes) before fetching. If the source does not start with any allowed scheme (e.g. http://, https://, file://), it returns ErrUnknownScheme wrapped with the redacted source and the allowed schemes.","triggerScenarios":"Passing a source string to FetchBytes/FetchContext without a scheme prefix (e.g. \"keys.json\" or \"/path/file.json\" instead of \"file:///path/file.json\"), or a scheme disabled in the fetcher configuration (e.g. file:// when only http(s) is allowed).","commonSituations":"Config values like jwks URLs written without https://, users supplying bare file paths, environments where the fetcher was constructed with restricted allowed_schemes (common in Ory services for security), typos like htp://.","solutions":["Prefix the source with an allowed scheme: file:///abs/path.json or https://host/jwks.json","Update the fetcher/client config to allow the needed scheme (e.g. enable file:// scheme)","Fix typos in the scheme (htp:// -> https://)","Use an absolute path with file:// rather than a relative path"],"exampleFix":"// before\nf.FetchBytes(ctx, \"/etc/keys/jwks.json\")\n// after\nf.FetchBytes(ctx, \"file:///etc/keys/jwks.json\")","handlingStrategy":"validation","validationCode":"if !strings.Contains(source, \"://\") {\n    return fmt.Errorf(\"source %q missing scheme\", source)\n}","typeGuard":"// schemeSep = \"://\"\nfunc schemeAllowed(src string, schemes []string) bool {\n    return slices.ContainsFunc(schemes, func(s string) bool { return strings.HasPrefix(src, s+schemeSep) })\n}","tryCatchPattern":"if _, err := f.FetchBytes(ctx, src); err != nil {\n    if errors.Is(err, fetcher.ErrUnknownScheme) {\n        log.Fatalf(\"add scheme to %q or enable it in fetcher config\", src)\n    }\n}","preventionTips":["Always include scheme in configured URLs","Whitelist needed schemes explicitly in fetcher setup","Never rely on path-only sources"],"tags":["fetcher","url","scheme","configuration"],"backgroundTag":"unknown-url-scheme","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}