Sep 18, 2026·8 min read·15 visits
Obot's fallback authorization logic incorrectly treats `/v0.1` API routes as public UI assets, allowing unauthenticated remote access to registered Model Context Protocol (MCP) server metadata.
An authentication bypass vulnerability in Obot versions <= v0.22.1 allows unauthenticated remote attackers to access Model Context Protocol (MCP) registry metadata and retrieve server lists when OBOT_SERVER_ENABLE_REGISTRY_AUTH is configured. This is due to a routing logic flaw where `/v0.1` paths are incorrectly categorized as public frontend user interface assets.
Obot is an enterprise-grade AI Governance and Model Context Protocol (MCP) management platform. It manages integrations between large language models and external computational contexts. The platform includes a management server, frontend user interface, and an API designed to register and orchestrate MCP servers. To manage access control in multi-tenant or protected environments, Obot allows administrators to set the configuration parameter OBOT_SERVER_ENABLE_REGISTRY_AUTH=true. This enforces authentication requirements across all critical registry management APIs.
The vulnerability GHSA-pr6h-vr44-xq8j describes an incorrect authorization flaw (CWE-863) within the application's global access control layer. When registry authentication is enabled, the API endpoints responsible for exposing Model Context Protocol server registries are left accessible to unauthenticated callers. These endpoints are hosted under the /v0.1 and /v0.1/* request paths. Because of a missing exclusion rule in the central routing engine, the system fails to apply authentication checks to these paths, routing them as public assets.
The attack surface is exposed directly on the public-facing HTTP interface of any Obot server deployment. Exploitation does not require prior authentication or session establishment. By querying the /v0.1/servers endpoint, an external network-positioned attacker can bypass the configuration restrictions of OBOT_SERVER_ENABLE_REGISTRY_AUTH=true. This bypass discloses the entire active metadata catalog of internal MCP integrations, compromising architectural boundaries.
The core flaw is located within the custom routing authorizer component inside pkg/api/authz/ui.go. Obot implements a multi-tiered authorization model to differentiate between frontend assets (which must remain accessible to anonymous browsers) and protected backend APIs (which require valid user identities). The system utilizes a 'default-allow' fallback algorithm for route parsing. This algorithm assumes any incoming request that does not explicitly match a restricted backend API pattern is an innocuous user interface resource, such as static HTML, JavaScript, CSS, or images.
The classification is performed by the checkUI helper function. The function inspects the path of the incoming http.Request and compares it against specific prefix lists. Before version v0.23.0, the comparison array and exclusion logic only checked for paths matching /api, /mcp-connect/, /oauth/, and /debug/. Because the Model Context Protocol registry endpoints are routed under the /v0.1 base prefix, requests directed to paths such as /v0.1/servers failed all exclusion checks in checkUI.
As a result, checkUI mistakenly returned true, declaring the backend API path to be a harmless UI resource. This bypassed the global authentication filters entirely, skipping WWW-Authenticate header validation and avoiding session token verification. The application router forwarded the unauthenticated request directly to the backend registry handler.
Once the request bypassed the API authentication layer and reached the backend registry handler, the handler evaluated the user identity. Because the user had no session, they were mapped to the UnauthenticatedGroup (anonymous identity). The registry handler enforces its own per-user Access Control Rules (ACRs). For an anonymous caller, it filters out all credential-carrying variables (such as secret environment parameters, API tokens, and authorization headers). However, the handler is still allowed to return wildcard and default-catalog entries to the user. Consequently, the response returned to the unauthenticated caller contains the inventory of the registry server.
To understand the flaw, we must analyze the vulnerable code path in pkg/api/authz/ui.go prior to the patch. The checkUI function was structured to allow anonymous requests to bypass the main security filters based on a logical OR evaluation.
// Vulnerable Implementation in pkg/api/authz/ui.go
func (a *Authorizer) checkUI(req *http.Request, user user.Info) bool {
// Reject direct access to /debug/, /api or /api paths for UI except for /api/image/{id}
if req.URL.Path == "/api" || hasAnyPrefix(req.URL.Path, "/mcp-connect/", "/oauth/", "/debug/") || (strings.HasPrefix(req.URL.Path, "/api/") && !strings.HasPrefix(req.URL.Path, "/api/image/")) {
return false
}
// Under default-allow logic, if the request does not trigger the 'return false' check,
// the authorizer assumes the request is a static asset and returns true (authorized).
return true
}Because the prefix list "/mcp-connect/", "/oauth/", "/debug/" did not contain the /v0.1/ path, any client seeking resources at /v0.1/servers avoided the false evaluation condition, proceeding to be handled as an authorized UI route.
The official patch introduced in commit 7da59f71ca9a168af7cf53016a75bde90c6a57a3 corrects this logic by explicitly registering the /v0.1 and /v0.1/ prefixes as non-UI routes. This ensures that any incoming connection directed to these API endpoints is rejected by the fallback UI logic, requiring normal user authentication.
// Patched Implementation in pkg/api/authz/ui.go
func (a *Authorizer) checkUI(req *http.Request, user user.Info) bool {
// Reject direct access to non-UI routes except for /api/image/{id}.
if req.URL.Path == "/api" || req.URL.Path == "/v0.1" || hasAnyPrefix(req.URL.Path, "/mcp-connect/", "/oauth/", "/debug/", "/v0.1/") || (strings.HasPrefix(req.URL.Path, "/api/") && !strings.HasPrefix(req.URL.Path, "/api/image/")) {
return false
}
return true
}The patch is logically straightforward and covers the exact API root exposed by the Model Context Protocol service layer. However, the use of 'default-allow' fallback logic inside checkUI remains an architectural concern. If developers introduce new API routes on different path bases in future releases without modifying the exclusion list, similar authorization bypass variants may occur.
Exploiting this vulnerability does not require sophisticated custom tooling, specialized network positions, or complex prerequisites. An attacker only needs basic TCP/IP access to the target port where the Obot management platform is hosted. The bypass is triggered by issuing an unauthenticated HTTP GET request targeting the API registry path /v0.1/servers.
The attack cycle consists of three phases. First, the attacker maps the target Obot service by making a standard probe request. Second, the attacker sends a GET request to /v0.1/servers. If the system is running a vulnerable version and has registry authentication configured, the server bypasses security filtering and returns an HTTP status of 200 OK rather than the expected 401 Unauthorized or 403 Forbidden response.
The following request trace demonstrates a successful exploit query against a vulnerable target:
GET /v0.1/servers HTTP/1.1
Host: vulnerable-obot-instance.local
User-Agent: Security-Audit-Scanner
Accept: application/json
Connection: closeThe response packet returns the application payload disclosing registered MCP services:
[
{
"id": "jira-mcp-endpoint",
"name": "Corporate Jira Bridge",
"description": "Enterprise tool to access ticket states and internal infrastructure planning.",
"repositoryUrl": "https://git.internal-corp.net/sec-ops/mcp-jira-bridge.git",
"connectUrl": "https://mcp-gateway.internal-corp.net/jira/v1"
}
]As demonstrated, no API keys, OAuth session tokens, or username/password combinations are present in the request headers, yet the server fully discloses the internal MCP integration structure.
The security impact of GHSA-pr6h-vr44-xq8j is classified as confidentiality exposure with medium severity. Although the unauthenticated endpoint does not allow attackers to modify, delete, or add registry configuration settings (since WRITE-access requests utilize separate API handlers that enforce strict token validation), the leaked metadata reveals highly sensitive architectural insights. The inventory provides an internal roadmap of the target environment's internal components, connected tools, and external services.
The disclosure of repository URLs, backend service routes, and descriptions gives attackers direct access to names and paths of proprietary systems. For instance, finding a connection endpoint pointing to an internal Git repository (https://git.internal-corp.net/...) or an internal API gateway (https://mcp-gateway.internal-corp.net/...) points to secondary targets. Attackers can leverage this intelligence to design highly targeted attacks, seeking out other internal vulnerabilities based on the specific server descriptions and tools exposed in the JSON response.
The CVSS score of 5.3 reflects the lack of integrity and availability impact, but underscores the low-complexity network-accessible nature of the confidentiality disclosure. Because there is no user interaction required, this vulnerability can be automated by scanning engines on the public internet, exposing systems that run vulnerable configurations of Obot.
The primary remediation path is upgrading the Obot installation to version v0.23.0 or higher. The upgrade completely changes the route handling characteristics of the checkUI block, forcing all requests matching /v0.1 and /v0.1/* to undergo mandatory session-validation and token-checking procedures. This prevents anonymous queries from reaching the backend registry handlers.
If an immediate software upgrade is not possible due to development constraints or change control freezes, administrators should implement a temporary mitigation using a Web Application Firewall (WAF) or reverse proxy. The proxy must inspect the request URI. If the requested path starts with /v0.1, the proxy should verify the existence of authorization parameters. If no authorization is present, the proxy should terminate the request immediately, returning an HTTP 401 Unauthorized status to the client.
For proactive network-level detection, security engineers can deploy signature-based intrusion detection rules. The following Snort signature detects attempt patterns to exploit the registry access bypass over unencrypted network streams:
alert tcp $EXTERNAL_NET any -> $HOME_NET 8080 (msg:"EXPLOIT-ACTIVE Obot MCP Registry Authorization Bypass Attempt (GHSA-pr6h-vr44-xq8j)"; flow:to_server,established; content:"GET"; http_method; content:"/v0.1/servers"; http_uri; fast_pattern; metadata:service http; reference:url,github.com/obot-platform/obot/security/advisories/GHSA-pr6h-vr44-xq8j; classtype:attempted-recon; sid:1000001; rev:1;)Using this rule helps network administrators locate and isolate vulnerable instances of Obot that are active on internal or external networks.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Obot Obot AI | <= v0.22.1 | v0.23.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862, CWE-863 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 5.3 (Medium) |
| Exploit Status | PoC / Active Reconnaissance |
| Impact Type | Unauthenticated Metadata Disclosure |
| Remediation | Upgrade to v0.23.0 or restrict /v0.1/ via WAF |
| CISA KEV Status | Not Listed |
The software does not perform an authorization check when an actor attempts to access a resource or perform an action.
CVE-2026-62374 (GHSA-f9j6-8p6x-r9j6) is a verification bypass vulnerability in the OpenWallet Foundation SD JWT JS library (@sd-jwt/core and @sd-jwt/decode versions 0.19.0 and earlier). Due to permissive UTF-8 decoding and the omission of mandatory reference checks during presentation verification, tampered or unreferenced disclosures are silently dropped rather than rejected. This deviates from RFC 9901 §7.1 requirements and allows attackers to execute silent claim-set reduction attacks against relying parties.
An interpretation conflict in Bytebase DBHub (< 0.22.6) allows attackers to bypass read-only SQL query restrictions when connected to MySQL or MariaDB instances. Because DBHub's custom SQL tokenizer treats any '--' sequence as a comment, whereas MySQL and MariaDB require trailing whitespace or a control character, crafted queries containing '--' immediately followed by non-whitespace characters allow stacked destructive SQL statements to execute on connections configured as read-only.
CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.
CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.
CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).
CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.