ory/kratos · error
$ref scheme is not permitted in identity schemas
Error message
$ref scheme %q is not permitted in identity schemas
What it means
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.
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.
Example fix
// before "$ref": "file:///schemas/address.json" // after "$ref": "base64://eyJ0eXBlIjoib2JqZWN0In0=" (or inline the schema under $defs and use "#/definitions/address")
Defensive patterns
Strategy: validation
Validate before calling
u, _ := url.Parse(ref)
if u != nil && u.Scheme != "base64" {
return fmt.Errorf("$ref %q must use base64:// scheme", ref)
} Try / catch
if strings.Contains(err.Error(), "is not permitted in identity schemas") {
// inline the schema or convert to base64:// ref
} Prevention
- 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
When it happens
Trigger: 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".
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- invalid $ref URL
- identity schema rejected: self-referential $ref cycle
- you must provide `secrets.pagination` for FIPS compliance
- you must provide `secrets.cipher` for FIPS compliance
- you must provide `secrets.cookie` for FIPS compliance
AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07).
Data as JSON: /api/errors/0cfcce3388a4e70c.
Report an issue: GitHub.
Appendix: source
Thrown at schema/loader.go:35
"github.com/pkg/errors"
"github.com/ory/jsonschema/v3"
"github.com/ory/x/httpx"
)
// loadRefURL resolves the URL of a `$ref` inside a schema. It enforces the
// scheme allowlist and then delegates to the jsonschema package's global
// loader table. The global `file` loader remains registered so that
// operator-configured top-level schema URLs (resolved outside the compiler)
// keep working.
func loadRefURL(ctx context.Context, raw string) (io.ReadCloser, error) {
u, err := url.Parse(raw)
if err != nil {
return nil, fmt.Errorf("invalid $ref URL %q: %w", raw, err)
}
if u.Scheme != "base64" {
return nil, fmt.Errorf("$ref scheme %q is not permitted in identity schemas", u.Scheme)
}
return jsonschema.LoadURL(ctx, raw)
}
// NewCompiler returns a jsonschema.Compiler. When disallowRefs is true, the
// compiler rejects `file://` URLs (and any other non-allowlisted scheme) in
// `$ref` values, preventing an attacker-supplied schema from reading local
// files on the Kratos host. When disallowRefs is false, the compiler uses
// the jsonschema library's default loader table, which preserves legacy
// behavior for operators who intentionally reference local files.
//
// The flag is controlled by `security.disallow_ref_in_identity_schemas`.
// Ory Network forces it on.
func NewCompiler(disallowRefs bool) *jsonschema.Compiler {
c := jsonschema.NewCompiler()
if disallowRefs {
c.LoadURL = loadRefURL
}View on GitHub (pinned to b86338da04)