The Unsolicited Report
A security researcher recently reported a vulnerability in a QR code service. The core of the finding was that the service's POST /api/oauth/register endpoint accepted registrations from any source, with any HTTPS redirect URI, without requiring credentials, review, or an allowlist. The researcher recommended closing this endpoint.
The service's operator, however, pushed back. The endpoint, far from being a bug, was functioning precisely as designed. It implements Open Dynamic Client Registration, a feature defined in RFC 7591, which is essential for the service's operation. This protocol allows clients to dynamically register as OAuth clients with a server they have never encountered before, a crucial step when users, for instance, paste a remote Model Context Protocol (MCP) server URL into applications like Claude or ChatGPT. The client must establish itself as an OAuth client of this unfamiliar server, a process facilitated by dynamic registration.
This situation highlights a common tension in software development: the gap between a security researcher's immediate assessment of risk and the product's intended functionality. While the researcher correctly identified an open registration mechanism, their proposed solution—closing the endpoint—would have rendered the product inoperable for its intended use case.

Understanding OAuth Dynamic Client Registration
RFC 7591, "OAuth 2.0 Dynamic Client Registration Protocol," defines a mechanism for clients to register themselves with an authorization server. This is particularly useful in scenarios where client applications are not pre-configured or need to be provisioned dynamically. The protocol defines a set of metadata that a client must provide, such as its redirect URIs, software versions, and contact information. The authorization server can then issue client credentials (client ID and client secret) to the newly registered client.
The key here is the "dynamic" aspect. Unlike static registration, where an administrator manually configures client applications, dynamic registration allows for automated provisioning. This is invaluable for platforms that integrate with a wide array of third-party services or for user-driven onboarding processes where users might connect services that need to act as OAuth clients on their behalf.
In the context of the QR code service, the dynamic registration endpoint allows users to connect their own OAuth-enabled services (like a custom identity provider or a specialized MCP server) without the service operator needing to manually pre-configure each one. This dramatically scales the service's interoperability. The researcher's recommendation to close this endpoint would, therefore, eliminate this core capability, forcing users to rely solely on pre-approved, statically registered clients, or to use manual, cumbersome OAuth configuration methods.
The Unforeseen Exposure
While the initial report focused on the open registration endpoint, the actual security exposure turned out to be elsewhere. This is a critical point: even if a recommendation addresses a perceived vulnerability, it might not address the true risk. The service operator discovered that the real issue lay not in the registration endpoint itself, but in how the service handled the redirect URIs once registered. Specifically, the system failed to adequately validate the provided redirect URIs against a curated list of trusted domains. This oversight meant that a malicious actor could potentially register a client with a seemingly legitimate redirect URI that, in reality, pointed to an attacker-controlled server.
The implication is that while the registration endpoint was indeed open, its immediate danger was mitigated by the fact that the service controlled the redirect process. The vulnerability was more subtle: the service's trust in the registered redirect URI was misplaced. An attacker could have registered their malicious client, and then, during the OAuth flow, been redirected to their own phishing page or a site that could intercept sensitive information. This is a classic example of a system being vulnerable not because a specific component is fundamentally insecure, but because the interaction between components, or the trust placed in data passed between them, is flawed.
The surprising detail here is not the researcher's accurate identification of an open endpoint, but that the *actual* attack vector was overlooked. It underscores the complexity of security assessments; a single finding, even if technically correct, might not encompass the full attack surface or the most critical risk.
Balancing Security and Functionality
The operator's refusal to close the OAuth registration endpoint was not an act of defiance against security, but a defense of product functionality. The challenge for developers and security professionals is finding the right balance. Simply closing off all open endpoints, while seemingly secure, often cripples a product's usability and innovation potential.
Instead of disabling dynamic client registration, the service operator could implement more robust security measures around it. This might include:
- IP Address Whitelisting/Rate Limiting: Restricting registration attempts to known IP ranges or implementing rate limits to prevent brute-force attacks.
- Human Review Workflow: For certain types of registrations or sensitive domains, implementing a manual review process.
- Enhanced Redirect URI Validation: Stricter validation of redirect URIs, ensuring they belong to a pre-approved set of domains or adhere to specific patterns. This is where the actual vulnerability lay, and strengthening this validation is paramount.
- Client Secret Rotation: Implementing policies for rotating client secrets to limit the impact of a compromised secret.
- Domain Verification: Requiring domain verification for custom redirect URIs, similar to how social media platforms verify website ownership.
These measures allow the dynamic registration endpoint to remain functional, preserving the product's interoperability, while significantly reducing the attack surface. The goal is not to eliminate all potential risks, which is often impossible without sacrificing utility, but to manage and mitigate them to an acceptable level.
This case serves as a valuable lesson: security reports should be treated as starting points for investigation, not as definitive dictates. The most effective approach often involves a deep understanding of the product's architecture and intended use, combined with targeted, functional security enhancements rather than blunt-force closures.
What nobody has addressed yet is how to standardize best practices for dynamic client registration, ensuring that vendors and security researchers alike can agree on what constitutes a reasonable risk profile for these powerful, flexible features.
