惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
罗磊的独立博客
F
Fortinet All Blogs
人人都是产品经理
人人都是产品经理
量子位
V
Visual Studio Blog
Blog — PlanetScale
Blog — PlanetScale
M
MIT News - Artificial intelligence
B
Blog RSS Feed
腾讯CDC
博客园_首页
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
博客园 - Franky
S
SegmentFault 最新的问题
N
Netflix TechBlog - Medium
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
D
Docker
P
Privacy & Cybersecurity Law Blog
S
Securelist
V
V2EX
Jina AI
Jina AI
阮一峰的网络日志
阮一峰的网络日志
T
Tor Project blog
The Hacker News
The Hacker News
Microsoft Azure Blog
Microsoft Azure Blog
AWS News Blog
AWS News Blog
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
T
The Exploit Database - CXSecurity.com
Help Net Security
Help Net Security
酷 壳 – CoolShell
酷 壳 – CoolShell
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 叶小钗
Recent Announcements
Recent Announcements
Cloudbric
Cloudbric
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Latest news
Latest news
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Recorded Future
Recorded Future
V2EX - 技术
V2EX - 技术

Clerk Blog

Going to production with Clerk Deploy Clerk Init: The fastest way to start a new project Introducing Clerk CLI Middleware-based route protection bypass Postmortem: Clerk System Outage (March 10, 2026) Clerk for the AI era Add API Key support to your SaaS in minutes Postmortem: Clerk System Outage (February 19, 2026) Using Clerk in a React Native app Postmortem: DNS Provider Outage (February 10, 2026) How do I implement passkeys in Next.js? Clerk ranked #4 fastest-growing software vendor on Ramp’s December 2025 list How do I handle JWT verification in Next.js? Committing to Agent Identity: Clerk raises $50m Series C from Menlo and Anthropic’s Anthology Fund What is the best way to handle authentication in Next.js App Router? Postmortem: Database Incident (September 14–18, 2025) How do I add authentication to a Next.js app? Introducing Free Trials in Clerk Billing Postmortem: August 28, 2025 - elevated API latency and errors Introducing Mosaic: Bring Your Brand to Every Authentication Flow Multi-tenant authentication: What you need to know (and how Clerk helps) What are the risks and challenges of multi-tenancy? Resilience in Practice: Regional Failover at Clerk Build a Cross-Platform B2B App with Clerk, Expo, and Supabase Highlights from the MiduDev/Clerk Hackathon Add multi-tenancy to an app built with Clerk, Lovable, and Supabase How to build an AI coding rules app with Clerk, Lovable, and Supabase How to Build Multi-Tenant Authentication with Clerk Choosing the right SaaS architecture: Multi-Tenant vs. Single-Tenant Postmortem: June 26, 2025 service outage How to Design a Multi-Tenant SaaS Architecture What is multi-tenancy and why it matters for B2B SaaS How OAuth Works Synchronize user data from Clerk to Supabase Add subscriptions to your SaaS with Clerk Billing Getting started with Clerk Billing Multi-tenant analytics with Tinybird and Clerk How Huntr Migrated 250K Users to Clerk: A Scalable Auth Solution for Startups How to take Clerk to Production How to take your Clerk application to production A practical guide to testing Clerk Next.js applications Implementing multi-tenancy into a Supabase app with Clerk How Clerk integrates with a Next.js application using Supabase How Clerk integrates with Supabase Build a blog with tRPC, Prisma, Next.js and Clerk How to enrich PostHog events with Clerk user data How to build a secure project management platform with Next.js, Clerk, and Neon Validate your SaaS idea while building an audience Postmortem: February 6, 2025 service outage Implement Role-Based Access Control in Next.js 15 Build a Next.js sign-up form with React Hook Form Build a Next.js login page template How to implement Google authentication in Next.js 15 What is middleware in Next.js? How to customize Next.js metadata How to set environment variables in Node.js Building a React Login Page Template How to implement per-user OAuth scopes with Clerk Using Clerk SSO to access Google Calendar and other service data Streamline enterprise customer onboarding with SAML and Clerk Clerk launches EASIE SSO and eliminates SSO fees How to secure Liveblocks Rooms with Clerk in Next.js Securing Node.js Express APIs with Clerk and React Combining the benefits of session tokens and JWTs Build a task manager with Next.js, Supabase, and Clerk Comparing Clerk Webhooks vs Backend API Automate Neon schema changes with Drizzle and GitHub Actions A guide to reading authenticated user data from Clerk Role based access control with Clerk Organizations Per-user B2B monetization with Stripe and Clerk Organizations Build a team-based task manager with Next.js, Neon, and Clerk Building a Hybrid Sign-Up/Subscribe Form with Stripe Elements Welcoming Colin from Zod as our inaugural Open Source Fellow Build a modern authenticated chat application with Next.js, Ably, and Clerk Build a waitlist with Clerk user metadata How to use Clerk with PostHog Identify in Next.js How to secure API Gateway using JWT and Lambda Authorizers with Clerk What are passkeys and how do they work? Comparing Authentication in React.js vs. Next.js How to Add an Onboarding Flow for your Application with Clerk Create Your Own Custom User Menu with Radix - Part 2 Introducing Webhook Workflows with Inngest & Svix Clerk raises $30M Series B from CRV and Stripe Clerk in 2023: A Year in Review Build a Movie Emoji Quiz App with Remix, Fauna, and Clerk Ultimate Guide to Magic Link Authentication Create Your Own Custom User Menu with Radix Introducing has(), protect(), and <Protect> Updated Pricing: 10,000 MAUs Free, and a new “Pro Plan” Next.js Authentication with Clerk: Streamlined SSR Handling Clerk Webhooks: Data Sync with Convex Exploring Clerk Metadata with Stripe Webhooks The Ultimate Guide to Next.js Authentication Empower Your Support Team With User Impersonation Clerk Webhooks: Getting Started A Complete Guide to Session Management in Next.js The Advanced Guide to Passwordless Authentication in Next.js How We Roll – Chapter 10: Roundup How We Roll – Chapter 9: Infrastructure Password-Based Authentication in Next.js
Mitigating OAuth’s recently discovered Open Response Type vulnerability
Colin Sidoti · 2024-08-07 · via Clerk Blog

On July 29, security researchers at Salt released details of an OAuth vulnerability that can reliably be chained with any XSS vulnerability to establish a long-lived account takeover. This is a general OAuth vulnerability, not particular to Clerk’s implementation.

At Clerk, we believe it’s our responsibility to protect our customers from vulnerabilities like this, so we worked quickly to understand the attack and devise a mitigation. Fortunately, we discovered that Clerk’s default configuration is not susceptible to this chaining, and over 99.7% of our customers were already protected. For the last 0.3%, we released an update today that mitigates the attack.

In this post, we dive into the technical details of the vulnerability, why most customers were protected by default, and how we mitigated the attack for the last few.

Understanding the Open Response Type vulnerability: a clever variation of the Open Redirect

The OAuth happy path

The OAuth flow starts by redirecting a user to the “authorization URL” of an identity provider, with redirect_uri and response_type in the query param, as well as an application identifier and the scope of authorization requested. Here’s a sample for Google:

On Google’s website, the user is asked to authorize the requested scope, which normally only includes profile information so the user can be signedin.

After authorization, the user is redirected back to the redirect_uri using the given response_type. In this case, the response type is code, which means a single-use secret code is appended to the redirect_uri as a query param:

The Open Redirect vulnerability

An “Open Redirect” is when an attacker tricks a user into visiting an authorization URL with a nefarious value passed to redirect_uri. For example, instead of passing https://myapp.com/oauth_callback, they can pass https://attackapp.com/oauth_callback. This accomplishes two things:

  1. https://myapp.com/oauth_callback doesn’t receive the secret code, so its single-use nature does not provide any protection.
  2. The attacker gets access to a secret code. With it, they can open a new browser on their own machine, and navigate to the valid redirect_uri with the code appended. This tricks the application into granting a session for the victim to the attacker.

Thankfully, the OAuth specification guides implmentors on how to prevent Open Redirects, and Google and other identity providers maintain a strict allowlist of acceptable redirect_uris. The allowlist ensures that the user, and the secret code, will not be sent to a URL the attacker controls.

The Open Response Type vulnerability

In OAuth, the response type dictates the format and mechanism for how the identity provider passes sensitive information back to the application. With code, a single-use token is passed by query param. With token, an access token is passed by the URL’s hash fragment.

Unlike redirect_uris, the response_type parameter is not strictly bound to a per-application allowlist. This lack of enforcement is pivotal to the attack, which is why we’re calling it the “Open Response Type” vulnerability. Here is Salt’s explanation of how the parameter was leveraged:

Note that we changed the original OAuth link to Google - we used the response type “code,token” instead of only “code”, which makes Google send the code in the hash fragment (#code=...). This enables us to read the code from the URL and ensure Hotjar doesn’t consume the code, which can be consumed only once.

After changing the response type to code,token, the secret code is returned in the fragment instead of the query param. In all likelihood, the application implementing OAuth has not prepared for a secret code to be in the fragment, so it doesn’t consume it, and it remains in the URL instead.

Put another way: the open nature of response_type means an attacker has a reliable way to get a valid, unused secret code in the URL bar.

Thankfully, getting the code in the URL bar alone is not sufficient, since the attacker also must be able to read its value. This is not normally possible, but it is when an XSS vulnerability is present. Depending on the page the XSS is present on, it may be as easy as reading window.location.href. In Salt’s case, they opened a new tab to the Authorization URL via window.open, then polled the tab’s location until the OAuth flow completed.

The impact

You might be wondering: Do we really need to worry about Open Response Type if it needs to be chained with an XSS attack?

The answer is absolutely yes. When managing user sessions on the web, it’s critical to mitigate the effects of XSS as much as possible. After an XSS is patched, it should be impossible for the attacker to continue acting on behalf of any users.

This is why developers use the HttpOnly directive when managing session cookies: it ensures that session tokens cannot be extracted for the attacker to continue using after the XSS is patched. Without this feature, developers would need to revoke sessions after an XSS attack and force users to sign in again.

The challenge with the Open Response Type vulnerability is that it completely bypasses the protections afforded by HttpOnly. The attacker is able to generate new sessions, and those sessions will continue to be valid after the XSS is patched.

Mitigating the Open Response Type vulnerability

The Open Response Type vulnerability relies on two behaviors:

  1. The user must land on a page with an unused code in the URL bar.
  2. The application must have an open XSS vulnerability that allows them to programmatically read the URL bar.

Below, we list two techniques that can be used to suppress these behaviors.

Mitigation 1: Process the OAuth code on a separate origin

At the top of this post, we mentioned that over 99.7% of Clerk customers were protected by default. That is because Clerk forces developers to set the OAuth redirect_uri to be an endpoint on our API, which is normally hosted on a subdomain like https://clerk.yourdomain.com. When the Open Response Type attack is attempted against a Clerk customer, the user would land on URL on this subdomain, like:

Fortunately, this subdomain does not serve HTML, so it’s exceedingly unlikely to be the source of an XSS. An XSS on any other subdomain cannot read the URL of a tab on the Clerk subdomain, since it breaks the web’s cross-origin rules.

If your application also leverages a separate origin for processing the OAuth code (e.g. identity.yourdomain.com or auth.yourdomain.com), it will also be protected as long as that origin never introduces an XSS.

While this technique helps, it’s hard to guarantee that you will never introduce an XSS on the origin processing the OAuth code. For that reason, we recommend using Mitigation 2 instead.

Mitigation 2: Eliminate unexpected fragments

Some Clerk customers use a reverse proxy to host our API directly on their primary domain, so OAuth codes are not processed on a separate origin. For these users, and for a more robust solution overall, we needed to find an additional mitigation.

Our solution is to eliminate unexpected fragments from the URL bar before an XSS vulnerability has the chance to read them. To do this, we’ve added an extra redirect to any OAuth failure that eliminates the fragment.

Again, let’s consider a user that lands on this URL as a result of an Open Response Type attack:

Fragments aren’t sent to the server, so our server cannot tell that code is even present. But, this URL is expecting code in the query param, and since it’s missing, Clerk is going to return an error.

Instead of simply returning the error, we are now issuing a redirect first. We issue the redirect with status=301 and a Location header that has a trailing #, which clears any fragment that might exist:

Since we use Clerk at Clerk, you can confirm the behavior by visiting the URL on our domain with a fake code – the code will be stripped away. (You’ll notice we add an extra query param to prevent an infinite redirect.)

This behavior is easy to implement in your own OAuth handler and will effectively protect you against Open Response Type attacks.