{"record":{"id":"90c77dd8fd6cdf3d","repo":"ory/kratos","slug":"invalid-ref-url-q-w","errorCode":null,"errorMessage":"invalid $ref URL %q: %w","messagePattern":"invalid \\$ref URL %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"schema/loader.go","lineNumber":32,"sourceCode":"\t_ \"github.com/ory/jsonschema/v3/base64loader\"\n\t_ \"github.com/ory/jsonschema/v3/fileloader\"\n\t\"github.com/ory/jsonschema/v3/httploader\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/ory/jsonschema/v3\"\n\t\"github.com/ory/x/httpx\"\n)\n\n// loadRefURL resolves the URL of a `$ref` inside a schema. It enforces the\n// scheme allowlist and then delegates to the jsonschema package's global\n// loader table. The global `file` loader remains registered so that\n// operator-configured top-level schema URLs (resolved outside the compiler)\n// keep working.\nfunc loadRefURL(ctx context.Context, raw string) (io.ReadCloser, error) {\n\tu, err := url.Parse(raw)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid $ref URL %q: %w\", raw, err)\n\t}\n\tif u.Scheme != \"base64\" {\n\t\treturn nil, fmt.Errorf(\"$ref scheme %q is not permitted in identity schemas\", u.Scheme)\n\t}\n\treturn jsonschema.LoadURL(ctx, raw)\n}\n\n// NewCompiler returns a jsonschema.Compiler. When disallowRefs is true, the\n// compiler rejects `file://` URLs (and any other non-allowlisted scheme) in\n// `$ref` values, preventing an attacker-supplied schema from reading local\n// files on the Kratos host. When disallowRefs is false, the compiler uses\n// the jsonschema library's default loader table, which preserves legacy\n// behavior for operators who intentionally reference local files.\n//\n// The flag is controlled by `security.disallow_ref_in_identity_schemas`.\n// Ory Network forces it on.\nfunc NewCompiler(disallowRefs bool) *jsonschema.Compiler {\n\tc := jsonschema.NewCompiler()","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/schema/loader.go#L14-L50","documentation":"loadRefURL validates each $ref URL in an identity schema before fetching it. If the raw URL cannot be parsed by net/url.Parse, the error is wrapped as \"invalid $ref URL %q: %w\". This guard exists so malformed references fail fast at the schema-loader level instead of failing deep inside jsonschema.LoadURL.","triggerScenarios":"An identity schema JSON contains a $ref whose value is not a parseable URL — e.g. a missing scheme like \"$ref\": \"some/relative/path\" is actually parseable, but broken percent-escapes (\"%zz\"), control characters, or a malformed IPv6 host in a URL will make url.Parse fail. Triggered whenever the schema compiler resolves refs via loadRefURL (identity schema compilation with $ref loader registered).","commonSituations":"Hand-edited identity schemas where a $ref was written as an invalid URL string (unescaped characters, stray spaces are tolerated by url.Parse but % sequences are not); templating tools that interpolated values into $ref leaving stray characters; copying refs between systems where quotes got mangled.","solutions":["Inspect the exact %q value in the error message and fix the $ref string in the identity schema so it is a valid, parseable URL.","Percent-encode any literal '%' characters and remove control characters/whitespace from the $ref value.","Verify the ref uses the expected form: a valid URL with the allowed 'base64' scheme for identity schemas (e.g. base64://<encoded schema>).","Validate the schema JSON offline (url.Parse the refs yourself) before submitting it to the schema compiler."],"exampleFix":"// before\n\"$ref\": \"base64://ewogIC8vIGJyb2tlbg%zz\"\n// after\n\"$ref\": \"base64://ewogIC8vIHNjaGVtYQ%3D%3D\" (properly percent-encoded) or an otherwise valid URL","handlingStrategy":"validation","validationCode":"for _, ref := range collectRefs(schema) {\n    if _, err := url.Parse(ref); err != nil {\n        return fmt.Errorf(\"schema contains invalid $ref %q: %w\", ref, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"var urlErr *url.Error\nif errors.As(err, &urlErr) {\n    // handle malformed $ref URL\n}","preventionTips":["Validate schema $refs with url.Parse in CI before deployment","Never build $ref strings by raw string interpolation; use url building helpers","Keep $ref values as simple, well-formed URLs"],"tags":["jsonschema","url","ref-resolution","identity-schema"],"backgroundTag":"invalid-url-format","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}