{"record":{"id":"0cfcce3388a4e70c","repo":"ory/kratos","slug":"ref-scheme-q-is-not-permitted-in-identity-schema","errorCode":null,"errorMessage":"$ref scheme %q is not permitted in identity schemas","messagePattern":"\\$ref scheme %q is not permitted in identity schemas","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"schema/loader.go","lineNumber":35,"sourceCode":"\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()\n\tif disallowRefs {\n\t\tc.LoadURL = loadRefURL\n\t}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/schema/loader.go#L17-L53","documentation":"After parsing a $ref URL, loadRefURL enforces that only the \"base64\" scheme is allowed for identity schemas; any other scheme (file://, http://, https://, etc.) is rejected with this error. This prevents identity schemas from pulling in arbitrary local or remote resources, closing a data-exfiltration/SSRF vector.","triggerScenarios":"An identity schema contains a $ref with a non-base64 scheme, e.g. \"file:///etc/passwd\" or \"https://example.com/schema.json\". Raised during identity schema compilation whenever the registered loadRefURL loader resolves a ref whose u.Scheme != \"base64\".","commonSituations":"Operators reusing schemas written for generic JSON Schema tooling where file:// or https:// refs are normal; schemas migrated from environments without scheme restrictions; attempts to reference local helper schemas during development.","solutions":["Inline the referenced schema directly into the identity schema instead of using a $ref to an external URL.","Convert the referenced schema content to a base64 data reference using the permitted scheme: base64://<url-safe base64 of the schema JSON>.","Remove file:// and http(s):// $refs entirely — they are deliberately blocked; only the base64 scheme is allowlisted.","If tooling generates schemas with external refs, change the generator to emit base64:// refs or embed subschemas via definitions/$defs."],"exampleFix":"// before\n\"$ref\": \"file:///schemas/address.json\"\n// after\n\"$ref\": \"base64://eyJ0eXBlIjoib2JqZWN0In0=\"  (or inline the schema under $defs and use \"#/definitions/address\")","handlingStrategy":"validation","validationCode":"u, _ := url.Parse(ref)\nif u != nil && u.Scheme != \"base64\" {\n    return fmt.Errorf(\"$ref %q must use base64:// scheme\", ref)\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"is not permitted in identity schemas\") {\n    // inline the schema or convert to base64:// ref\n}","preventionTips":["Always inline subschemas via $defs instead of external file:// or https:// refs","Use a schema lint rule that rejects non-base64 schemes in identity schemas","Document the base64://-only policy to schema authors"],"tags":["jsonschema","ref-resolution","scheme-allowlist","security"],"backgroundTag":"unsupported-operation","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"}