Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Network-accessible, no-auth SSRF causes scope change to internal systems; C:L/I:L reflects internal service probing with no direct availability impact on Boruta itself.
Primary rating from Vendor (EEF).
CVSS VectorVendor: EEF
Lifecycle Timeline
2DescriptionCVE.org
Server-Side Request Forgery vulnerability in malach-it Boruta allows an unauthenticated remote attacker to cause the OAuth/OpenID authorization server to issue outbound HTTP requests to attacker-chosen URIs, including internal services and cloud metadata endpoints.
Three code paths fetch remote URIs supplied by the requester without sufficient validation of the target. Boruta.Oauth.Request.Base.fetch_unsigned_request/1 in lib/boruta/oauth/request/base.ex dereferences the OAuth request_uri parameter from the authorization request via Finch.build(:get, request_uri) |> Finch.request(OpenIDHttpClient). Boruta.Openid.parse_registration_params/2 in lib/boruta/openid.ex dereferences the jwks_uri supplied in an OpenID Connect dynamic client registration request. Boruta.Ecto.Clients.refresh_jwk_from_jwks_uri/1 in lib/boruta/adapters/ecto/clients.ex later refreshes the stored jwks_uri for an existing client. In all three paths the only validation is that the URI parses with a scheme (and one of the two request_uri clauses does not even restrict the scheme to http or https). The implementations do not require HTTPS, do not enforce a host or IP allowlist, do not reject loopback, private, link-local, or other non-public ranges after DNS resolution, do not cap response size, and do not constrain redirects. An attacker can therefore steer the server's HTTP client at arbitrary network targets reachable from the Boruta host.
This issue affects boruta: from 2.3.2 before 2.3.7.
AnalysisAI
Server-Side Request Forgery in Boruta (malach-it/boruta_auth versions 2.3.2 through 2.3.6) enables unauthenticated remote attackers to force the OAuth/OpenID authorization server to issue outbound HTTP requests to arbitrary attacker-controlled URIs, including cloud metadata endpoints (e.g., AWS IMDS at 169.254.169.254), internal APIs, and RFC 1918 network services. Three distinct code paths - OAuth request_uri handling, OpenID Connect dynamic client registration jwks_uri, and scheduled jwks_uri refresh - all invoke Elixir's Finch HTTP client against caller-supplied URIs with no host allowlist, no private IP rejection, no redirect constraint, and no response size cap. No public exploit has been identified at time of analysis; a vendor patch is available in version 2.3.7.
Technical ContextAI
Boruta is an Elixir library (hex package boruta_auth) implementing OAuth 2.0 and OpenID Connect for building authorization servers. The root cause is CWE-918 (Server-Side Request Forgery): three code paths in the library directly pass caller-supplied URI strings to Finch.build(:get, uri) |> Finch.request(OpenIDHttpClient) with validation limited to URI parseability. The three paths are: (1) Boruta.Oauth.Request.Base.fetch_unsigned_request/1 in lib/boruta/oauth/request/base.ex, which dereferences the OAuth 2.0 request_uri parameter - notably one clause does not restrict the URI scheme to http/https, permitting file:// or other schemes; (2) Boruta.Openid.parse_registration_params/2 in lib/boruta/openid.ex, which fetches the jwks_uri submitted during OpenID Connect dynamic client registration; and (3) Boruta.Ecto.Clients.refresh_jwk_from_jwks_uri/1 in lib/boruta/adapters/ecto/clients.ex, which re-fetches a stored jwks_uri for key refresh. CPE cpe:2.3:a:malach-it:boruta covers versions 2.3.2 through 2.3.6. The fix (commits 001e3dc and 95fb10b) introduces a new Boruta.HttpClient module that enforces per-client trusted_hosts and trusted_authorities allowlists and restricts schemes to http/https, replacing direct Finch calls in all three paths.
RemediationAI
Upgrade boruta_auth to version 2.3.7 or later, which introduces the Boruta.HttpClient module enforcing per-client outbound request allowlists via the new trusted_hosts (list of allowed hostnames) and trusted_authorities (trusted CA string) fields on the Client schema. After upgrading, operators must configure these fields on each client - the patched library rejects outbound requests from clients with neither field populated, returning an error rather than silently proceeding. Patch commits 001e3dc5c259e67c6f907e98867eda4141c96d0d and 95fb10b78129355e475681f324c9a01ef0af2be5 are available in the malach-it/boruta_auth repository. If immediate upgrade is not possible, disable OpenID Connect dynamic client registration to close the unauthenticated jwks_uri path (path 2), though this does not address the OAuth request_uri path (path 1) or the jwks_uri refresh path (path 3). As a compensating network control, apply egress filtering at the host, container, or cloud security group level to block outbound HTTP/HTTPS requests to RFC 1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), loopback (127.0.0.0/8), and link-local ranges (169.254.0.0/16, including AWS IMDS); note that this does not address SSRF against external attacker-controlled infrastructure. Advisory: https://github.com/malach-it/boruta_auth/security/advisories/GHSA-5q9h-vf5j-fr2g.
Authentication bypass via JWT assertion replay in malach-it Boruta (an Elixir OAuth 2.0/OpenID Connect provider) from 2.
Privilege escalation via dynamic client registration in malach-it's Boruta OAuth 2.0/OpenID Connect provider library (El
Same weakness CWE-918 – Server-Side Request Forgery (SSRF)
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-51143