New Ory Agent Security is now live! Claim your complimentary test drive. Get Started!

Skip to main content

Changelog for Ory Keto OEL

v26.4.3​

OEL images are no longer published to Cloudsmith​

Ory no longer publishes OEL images, their signatures, or their attestations to Cloudsmith (docker.cloudsmith.io/ory-corp/oel). New releases are available only from the Ory enterprise registries. Images already on Cloudsmith stay there, but receive no further versions.

Breaking changes​

Pull OEL images from the enterprise registry​

If you pull OEL images from docker.cloudsmith.io/ory-corp/oel, switch to the Ory enterprise registry to receive new releases. Contact Ory if you need access.


v26.4.2​

Finer latency histogram buckets​

The request latency histograms http_requests_duration_seconds and http_response_time_seconds (ory_oathkeeper_requests_duration_seconds and ory_oathkeeper_response_time_seconds in Ory Oathkeeper) now use boundaries chosen for request latency: 10 ms, 25 ms, 50 ms, 100 ms, then every 100 ms to 500 ms, 750 ms, 1 s, 1.5 s, 2 s, 3 s, 5 s, 10 s and 20 s.

Percentiles computed with histogram_quantile over a window that spans the upgrade mix both layouts and read wrong until the window has moved past it. Update dashboards and alerts that match on specific le values to the new boundaries.


v26.4.1​

Signatures and SBOM and CBOM attestations for OEL images​

Ory now signs every OEL image and publishes each signature next to its image, on the enterprise registries. All OEL images except the debug variants also carry two signed attestations: a Software Bill of Materials in SPDX format, and a CycloneDX document with the Software Bill of Materials and the Cryptography Bill of Materials.


v26.4.0​

Size limits for remote files and upstream responses​

Ory now rejects files loaded from a URL (http://, https://, file://, or base64://) and upstream responses that exceed a size limit, instead of reading them in full. If a fetch exceeds its limit, the operation fails. Ory Kratos also logs a warning that names the source and the limit.

SourceLimit
Ory Kratos: Jsonnet templates and claims mappers loaded from a URL (webhooks, courier, OpenID Connect, SCIM, session tokenizer)1 MiB
Ory Kratos: token and user info responses from social sign-in providers1 MiB
Ory Talos: JSON Web Key Sets loaded from a URL1 MiB
Any other file loaded from a URL, such as courier templates or Ory Permission Language files in Ory Keto5 MiB

If you expect to use a file larger than these limits, reduce its size before upgrading.


v26.3.19​

Validate Ory Permission Language files from the command line​

keto validate opl <file> checks an Ory Permission Language file for errors and exits non-zero if it finds any. Use --format json for machine-readable output.


26.3.18

This version contains only minor changes and improvements such as dependency updates.


26.3.17

This version contains only minor changes and improvements such as dependency updates.


26.3.16

This version contains only minor changes and improvements such as dependency updates.


v26.3.15​

Oathkeeper adopts shared HTTP metrics and adds per-rule access decisions​

Oathkeeper uses the shared Ory HTTP metric schema. It also exposes ory_oathkeeper_access_decisions_total, which reports allowed requests, authentication failures, authorization failures, and pipeline errors by rule ID. Access decisions are independent of login redirects and upstream response codes.

Breaking changes​

For Oathkeeper dashboards and alerts, replace service with app and status_code with code. The request label is replaced by endpoint, which contains API router patterns such as /rules/{param} and /decisions/ and is empty for proxy traffic. The app values remain oathkeeper-api and oathkeeper-proxy. HTTP metrics also include version, hash, and buildTime. Metric names retain the configured prefix. Health requests are now included.

serve.prometheus.hide_request_paths and serve.prometheus.collapse_request_paths are deprecated and have no effect. Update path filters to use router patterns or the new per-rule counter.

In Oathkeeper, Kratos, Hydra, and Keto, the requests_statuses_total metric's method labels now follow the same normalization as other shared HTTP metrics: recognized methods use lowercase values, and other methods use other. Oathkeeper applies this normalization to all HTTP metrics.

Unsupported methods use other instead of unknown across all shared HTTP metrics. Update queries that filter on the previous method label.

Keto can serve its APIs over HTTPS​

Every Keto endpoint - read, write, OPL syntax and metrics - can now terminate TLS itself. Point Keto at a certificate and key, either as file paths or as base64-encoded PEM:

serve:
read:
tls:
cert:
path: /etc/keto/tls/tls.crt
key:
path: /etc/keto/tls/tls.key

Configuring a certificate is what turns TLS on for an endpoint. If the TLS configuration is incomplete or incorrect, Keto fails to start instead of silently falling back to insecure HTTP.

When you configure the certificate through path, Keto reloads it automatically as it changes on disk, so certificate rotation needs no restart. gRPC and HTTP clients keep working over the TLS port.

TLS is off by default and the listen addresses are unchanged, so existing deployments continue to serve plain HTTP.

Listening on a unix socket​

Every endpoint can also listen on a unix socket instead of a TCP port. Set the host to a unix: path and control who may connect through the file permissions:

serve:
read:
host: unix:/var/run/keto/read.sock
socket:
owner: keto
group: keto
mode: 384 # 0600

Connecting to a unix socket requires write permission on the socket file, so mode is the access control for the endpoint. It defaults to 493 (0755), which lets only the owner connect. Keto removes the socket file when it shuts down.

A unix socket endpoint cannot terminate TLS, because the socket permissions are the access control and there is no host name for a client to verify. Configuring both is rejected at startup rather than silently serving one of them.

Configuration that is now rejected​

Two configurations that Keto used to accept and silently ignore are now rejected at startup: a write_listen_file without the file:// scheme, and a tls.cert or tls.key that sets both path and base64. Neither ever took effect, so correct the value and Keto starts as before.

TLS configuration and unix socket recovery in Hydra, Keto and Kratos​

A configured certificate is now the only switch for TLS in all three services. serve.<endpoint>.tls.enabled is deprecated but still accepted so that an existing configuration keeps loading, but it has no effect. Each service logs a warning at startup naming the key to remove. To serve plain HTTP behind a proxy that terminates TLS, remove the certificate rather than the flag.

Hydra and Kratos also pick up two fixes from the shared serve configuration:

  1. configuring only one half of a certificate pair is now a startup error instead of a listener that silently falls back to plain HTTP
  2. a unix socket left behind by an unclean shutdown is replaced instead of blocking the next start.

Because the three services now configure their endpoints identically, the documentation for it is one page: Serving the APIs. It replaces the separate Hydra and Kratos HTTPS pages, which now redirect to it.


26.3.14

This version contains only minor changes and improvements such as dependency updates.


v26.3.13​

Permission checks answer correctly when branches meet or loop​

A permission check could return the wrong answer — most often a denial or a max_depth_exceeded failure for a subject who should have been allowed, and on permissions that use !, a grant to a subject who should have been denied. Two cases caused it:

  • Branches that meet. When two paths through your data led to the same group or role, the first path to reach it claimed it for the whole check. If that path then ran out of depth, the second path was dropped even though it would have found the subject. Nested groups reachable more than one way are enough to hit this.
  • Loops in your data. A relationship that leads back to where it started — a folder chain that eventually points at an ancestor, or two groups that contain each other — was followed until the depth limit stopped it, instead of being recognized as adding nothing.

Both now resolve correctly. A loop in your data is answered decisively rather than reported as too deep, and one branch can no longer suppress another.

If you worked around this by raising limit.max_read_depth, you can lower it again. Checks over data whose branches converge are also considerably faster, because each group or role is now resolved once per check rather than once per path that reaches it.

Behavior changes​

Checks that previously answered "allowed": false — or 403 on the endpoints that signal a denial that way — or failed with 422 for the cases above now return the correct answer, which may be an allow. If you built on one of those denials, review it.

Checks also change the other way, which is the case to review first. A permission written as "allowed unless denied" — an allow list combined with ! over a deny list — could be granted to a subject the deny list covers, whenever another part of the same check had already walked the group that leads to that deny list. The deny branch was dropped as already seen, that reported "not denied", and ! turned it into a grant. Such a check now denies. Review any permission that negates a deny list reached through a group or a subject-set pointer: subjects who were allowed may no longer be, and some of them should never have been.

A permission defined as the negation of itself, directly or through other permissions — for example edit defined as "not view" while view is defined as "not edit" — has no answer, and never had one. Such a check now reports negation_cycle instead of failing after an internal step limit, and only that part of the check is affected: if the permission can also be granted another way, the check now answers from that instead of failing outright. This signals a definition to fix in your permission model.


26.3.12

This version contains only minor changes and improvements such as dependency updates.


26.3.11

This version contains only minor changes and improvements such as dependency updates.


26.3.10

This version contains only minor changes and improvements such as dependency updates.


26.3.9

This version contains only minor changes and improvements such as dependency updates.


26.3.8

This version contains only minor changes and improvements such as dependency updates.


v26.3.7​

Stricter validation for the Ory Permission Language​

Ory Keto now rejects OPL mistakes it previously accepted silently, most importantly a name declared as both a relation and a permit in one namespace. In that case, the relation shadows the permit, so the permit is never evaluated and checks can return wrong results. Other more obvious mistakes include duplicate namespace or relation declarations, or references that mix up relations and permits.

For backward compatibility, Ory Keto continues to load and run existing configurations with the relation/permit collision, but a future release will reject them. Configurations with the other mistakes, such as duplicate declarations, fail to load after upgrading.

Before upgrading a self-hosted deployment, validate your configuration with /opl/syntax/check on the new version, or start the new version against your configuration in a test environment, and fix reported errors — for example by renaming a permit that clashes with a relation, or removing duplicate relations from the OPL, and updating the application code accordingly.


26.3.6

This version contains only minor changes and improvements such as dependency updates.


v26.3.5​

Strict mode requires subject sets​

If you run Ory Keto with feature_flags.strict_mode (or the deprecated namespaces.experimental_strict_mode) enabled, creating relationships or checking permissions with a plain subject_id now fails with 400 Bad Request (InvalidArgument over gRPC). Reading and deleting existing subject_id relationships keeps working.

Before upgrading, rewrite subject_id relationships as subject sets or disable strict mode. See the migration guide.


v26.3.4​

Metrics endpoints now support OpenMetrics and trace exemplars​

The Prometheus metrics endpoints of Kratos, Keto, Hydra, Oathkeeper, and Talos now additionally serve the OpenMetrics exposition format. The format is selected automatically through standard HTTP content negotiation: scrapers that ask for OpenMetrics receive it, and all other scrapers keep receiving the classic text format. No configuration or scraper change is necessary.

OpenMetrics enables exemplars, which attach a trace reference to a metric sample. Two sets of metrics use this:

  • The HTTP request duration histograms and request counters attach an exemplar when a request runs under a sampled trace, so latency dashboards can link slow-request outliers and error spikes to the traces that caused them.
  • The ory_x_popx_cockroach_transaction_retries_total counter attaches an exemplar whose value is the transaction's retry count when a transaction is retried during a traced request, and the trace records a db.transaction.retry span event. Dashboards can link retry spikes directly to the traces that caused them.

That counter's caller label now also more reliably attributes automatic CockroachDB transaction retries to the business operation that opened the transaction, for example the OAuth2 refresh token flow, instead of a generic persistence Transaction wrapper method. This makes it possible to see which operation is causing database contention. Dashboards or alerts that match specific caller label values may need updating, because existing label values change with this release.

YugabyteDB support for Kratos, Hydra, and Keto (OEL)​

Ory Enterprise License deployments can now run Ory Kratos, Ory Hydra, and Ory Keto against YugabyteDB.

Enabling YugabyteDB​

Point the dsn at your YugabyteDB cluster using the yugabyte:// scheme (the synonym yugabytedb:// also works):

yugabyte://user@host:5433/database?sslmode=disable

Recovering an interrupted migration​

YugabyteDB applies DDL with autocommit. Old PostgreSQL migrations inherited by YugabyteDB can contain multiple statements, so an interruption may leave the first statements applied without a row in schema_migration. Current versions of Ory no longer use multi-statement migrations and are safe.


26.3.3

This version contains only minor changes and improvements such as dependency updates.


v26.3.2​

Enforce a DNS-label boundary on wildcard return URLs and CORS origins​

A wildcard in a return URL or CORS origin is now honored only when the * is confined to a subdomain label and the host part after it is a registrable domain (an eTLD+1, such as https://*.example.com or https://*.example.co.uk). The wildcard then matches only hosts under that one customer-owned domain.

These forms are no longer honored, because each can match an attacker-registrable host:

  • dot-less, e.g. https://*foo.com (matches https://evilfoo.com);
  • public-suffix base, e.g. https://*.com, https://*.co.uk, https://*.vercel.app;
  • trailing or bare, e.g. https://www.example.*, https://*.

Only the host is checked: wildcards in the URL path are unaffected. Exact origins, the catch-all *, and Hydra's https://* ("all hosts for a scheme") are unchanged.

What enforces it​

  • Return URLs: Kratos drops unsafe wildcard allowed_return_urls entries when it loads its config, and they never match.
  • CORS origins: matching across Kratos, Hydra, Keto, Oathkeeper, and Talos enforces the same boundary at request time.

Breaking changes​

Replace any unsafe wildcard with the labelled https://*.example.com form, or list exact origins. Update serve.*.cors.allowed_origins and Kratos allowed_return_urls before upgrading; otherwise cross-origin requests and post-flow redirects from those hosts will be blocked.


26.3.1

This version contains only minor changes and improvements such as dependency updates.


26.3.0

This version contains only minor changes and improvements such as dependency updates.


26.2.22

This version contains only minor changes and improvements such as dependency updates.


26.2.21

This version contains only minor changes and improvements such as dependency updates.


26.2.20

This version contains only minor changes and improvements such as dependency updates.


26.2.19

This version contains only minor changes and improvements such as dependency updates.


26.2.18

This version contains only minor changes and improvements such as dependency updates.


26.2.17

This version contains only minor changes and improvements such as dependency updates.


26.2.16

This version contains only minor changes and improvements such as dependency updates.


26.2.15

This version contains only minor changes and improvements such as dependency updates.


26.2.14

This version contains only minor changes and improvements such as dependency updates.


v26.2.13​

Detect mismatched database dialect at startup​

Kratos, Hydra, Keto, and backoffice now verify at startup that the configured database dialect matches the actual database server. The migrate sql and serve commands run a single SELECT version() query and refuse to start if the DSN scheme does not match the server.

Previously, pointing a service at a CockroachDB cluster with a postgres:// DSN (or the reverse) silently applied the wrong migrations and produced broken schemas. This is easy to do because CockroachDB speaks the PostgreSQL wire protocol and advertises a postgres:// DSN itself.

If your DSN scheme is wrong, you will now see a clear error such as:

DSN scheme postgres:// declares a PostgreSQL database but the server is
CockroachDB. Replace the scheme with cockroach:// so that the service
picks the correct migrations and SQL dialect.

To fix it, change the DSN scheme from postgres:// to cockroach:// (or the reverse) and restart. MySQL and SQLite are unaffected.


26.2.12

This version contains only minor changes and improvements such as dependency updates.


26.2.11

This version contains only minor changes and improvements such as dependency updates.


26.2.10

This version contains only minor changes and improvements such as dependency updates.


v26.2.9​

Patch security vulnerabilities in dependencies​

Bump several dependencies to patched versions to address security advisories reported by Dependabot.

Notable updates:

  • github.com/jackc/pgx/v5 to v5.9.2 across all Go modules (SQL injection via placeholder confusion in dollar-quoted string literals).
  • github.com/moby/spdystream to v0.5.1 (denial of service on container runtime interface).
  • go.opentelemetry.io/otel to v1.41.0 (remote DoS amplification via multi-value baggage header).
  • postcss to >=8.5.10 (XSS via unescaped </style> in CSS stringify output).
  • uuid to >=14.0.0 (missing buffer bounds check in v3/v5/v6 generators).
  • @xmldom/xmldom to >=0.8.13 (XML node injection and uncontrolled recursion).
  • axios, follow-redirects, lodash, picomatch, brace-expansion, serialize-javascript, yaml, file-type, i18next-fs-backend, @nestjs/core to their respective patched versions.

v26.2.8​

SSRF protection improvements​

Error messages originating from the SSRF protection mechanism no longer leak IP addresses if the hostname resolves to an internal IP address. This prevents SSRF recon through user-supplied URLs and hostnames.


26.2.7

This version contains only minor changes and improvements such as dependency updates.


26.2.6

This version contains only minor changes and improvements such as dependency updates.


v26.2.5​

Limit tree size in expand endpoint (default 4k nodes)​

The expand endpoint now returns a maximum of 4,000 nodes by default to reduce backend resource usage. For OSS and OEL deployments, this limit can be configured via limit.max_expand_size config.

Fix shared mutable state in error handling​

Error globals such as herodot.ErrNotFound were package-level variables shared across all requests. Calling methods like WithReason or WithDetail mutated these variables in place and returned the same pointer, so any request that added context to an error — reason text, details, etc, modified the global. The next request to reach an error path using the same error inherited those stale details.

As a consequence, observability (logs, traces) for requests resulting in an error suffered from the same issue: some errors were reported with details belonging to an unrelated request, or with fields missing that should have been present.

The new API creates a fresh error instance on each call, so each request gets its own copy.

The following values were at risk of leaking into unrelated error responses:

  • HTTP cookie names (Kratos CSRF flow)
  • Entity UUIDs (identity, organization, etc)
  • OAuth2 error hints (Hydra and Kratos Hydra bridge)
  • OIDC provider URLs and raw upstream error responses (Kratos OIDC strategy)
  • External schema fetch URLs and HTTP status codes (Kratos schema handler)
  • JWT claims and issuers (Oathkeeper JWT authenticator)

No data was written to persistent storage or transmitted outside the error response. Any two requests hitting the same error path on the same node — even back-to-back with no concurrency — could exchange error details.

Under concurrent load, the shared writes also constitute a true data race, which can additionally produce errors in an inconsistent or partially written state.

This change has no externally observable effect other than fixing the information leak in error paths.


v26.2.4​

Migrate Helm chart repository URL from k8s.ory.sh to k8s.ory.com​

The Helm chart repository URL has been updated from k8s.ory.sh to k8s.ory.com. The old URL will continue to work with redirects for a limited time. Update your Helm repository configuration to use the new URL.


v26.2.3​

Remove CGO requirement from Ory by switching to modernc.org/sqlite​

Migrates SQLite support from mattn/go-sqlite3 (CGO) to modernc.org/sqlite (pure Go) and fixes several timestamp comparison bugs that caused incorrect pagination results. This migration is fully backwards compatible. Going forward, the -tags sqlite tag is no longer required to compile Ory.


26.2.2

This version contains only minor changes and improvements such as dependency updates.


26.2.1

This version contains only minor changes and improvements such as dependency updates.


26.2.0

This version contains only minor changes and improvements such as dependency updates.


26.1.18

This version contains only minor changes and improvements such as dependency updates.


26.1.17

This version contains only minor changes and improvements such as dependency updates.


26.1.16

This version contains only minor changes and improvements such as dependency updates.


26.1.15

This version contains only minor changes and improvements such as dependency updates.


26.1.14

This version contains only minor changes and improvements such as dependency updates.


26.1.13

This version contains only minor changes and improvements such as dependency updates.


26.1.12

This version contains only minor changes and improvements such as dependency updates.


v26.1.11​

Breaking changes​

Upgrading from <26.1.7 will break pagination tokens. To ensure smooth upgrade, you must upgrade to 26.1.7 first.

Optimizes List Tuples query performance​

Optimizes pagination performance for certain list relation-tuple queries. This also changes the order of results while ensuring stable pagination.


26.1.10

This version contains only minor changes and improvements such as dependency updates.


26.1.9

This version contains only minor changes and improvements such as dependency updates.


26.1.8

This version contains only minor changes and improvements such as dependency updates.


26.1.7

This version contains only minor changes and improvements such as dependency updates.


26.1.6

This version contains only minor changes and improvements such as dependency updates.


26.1.5

This version contains only minor changes and improvements such as dependency updates.


26.1.4

This version contains only minor changes and improvements such as dependency updates.


26.1.3

This version contains only minor changes and improvements such as dependency updates.


26.1.2

This version contains only minor changes and improvements such as dependency updates.


26.1.1

This version contains only minor changes and improvements such as dependency updates.


26.1.0

This version contains only minor changes and improvements such as dependency updates.


25.4.12

This version contains only minor changes and improvements such as dependency updates.


25.4.11

This version contains only minor changes and improvements such as dependency updates.


25.4.10

This version contains only minor changes and improvements such as dependency updates.


25.4.9

This version contains only minor changes and improvements such as dependency updates.


25.4.8

This version contains only minor changes and improvements such as dependency updates.


25.4.7

This version contains only minor changes and improvements such as dependency updates.


25.4.6

This version contains only minor changes and improvements such as dependency updates.


25.4.5

This version contains only minor changes and improvements such as dependency updates.


25.4.4

This version contains only minor changes and improvements such as dependency updates.


v25.4.3​

Breaking changes​

Remove the ability for Keto to watch a WebSocket URL (starting with ws://) for legacy namespaces.

This affects the configuration field namespaces, but only when using the legacy namespaces which are deprecated. Use the new Ory Permission Language instead.

To check if you are affected, run the command: keto namespace validate-legacy -c /path/to/keto.yml.


25.4.2

This version contains only minor changes and improvements such as dependency updates.


25.4.1

This version contains only minor changes and improvements such as dependency updates.


25.4.0

This version contains only minor changes and improvements such as dependency updates.


25.3.9

This version contains only minor changes and improvements such as dependency updates.


25.3.8

This version contains only minor changes and improvements such as dependency updates.


25.3.7

This version contains only minor changes and improvements such as dependency updates.


25.3.6

This version contains only minor changes and improvements such as dependency updates.


v25.3.5​

Change of base image​

The base image for OEL images is now set to "gcr.io/distroless/static-debian12:nonroot". Previously, it was "gcr.io/distroless/static-debian12:debug-nonroot", which included BusyBox (a minimal shell and basic debugging utilities). Debug images are still available using the "-debug" tag suffix.


25.3.4

This version contains only minor changes and improvements such as dependency updates.


v25.3.3​

Improved tracing and metrics for the high-performance SQL connection pool​

This change adds distributed tracing and advanced metrics for the high-performance SQL connection pool in all Ory OEL products.