URIError: URI malformed - decodeURI in the clerk-js handshake aborts initialization on a malformed URL fragment
维护者通常 1 天内回复
评估
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 新手友好度
- 68/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- javascript, typescript
调研方向
从 clerk-js 的浏览器初始化和客户端握手路径开始,然后使用报告中的格式错误 URL 片段重现该问题。验证无法解码的片段不再中止初始化,同时有效片段仍能使握手和后续客户端请求完成。
由索引模型根据 Issue 内容生成。
描述
Preliminary Checks
- I have reviewed the documentation: https://clerk.com/docs
- I have searched for existing issues: https://github.com/clerk/javascript/issues
- I have not already reached out to Clerk support via email or Discord
- This issue is not a question, general help request, or anything other than a bug report directly related to Clerk
Reproduction
https://gist.github.com/RagDam/4a3098709c53c799c8351da0f586e0fe
Publishable key
Not included on purpose: the application is a private family tool. The bug reproduces with
any development instance - the failing call happens in the browser bundle, on a value read
from the current URL, before the instance matters. Happy to provide ours privately if it
helps.
Description
When the current URL carries a fragment that is not a valid percent-encoded sequence, for
example https://<app>/some-page#%E0%A4%A, clerk-js throws while initializing:
URIError: URI malformed
at decodeURI (<anonymous>)
at si (https://<instance>.clerk.accounts.dev/npm/@clerk/clerk-js@6/dist/clerk.browser.js:18:1587)
The call is decodeURI, on a value taken from the current URL, outside any try/catch.
Measured difference. Same page, same signed-in session, only the fragment differs:
| Fragment | Frontend API requests | window.Clerk.session |
window.Clerk.user |
|---|---|---|---|
#anything-valid |
GET /v1/client/handshake (307) x3, POST /v1/environment (200), GET /v1/client (200) |
active | present |
#%E0%A4%A |
GET /v1/client/handshake (307) x3, then nothing |
null | null |
Initialization stops at the handshake: /v1/environment and /v1/client are never
requested, so the client never gets a session.
Why this matters for end users. The session is never refreshed. The short-lived session
token expires (60 s in our development instance, exp - iat), and from then on every route
of the application shows the sign-in screen instead of the requested page. Signing in again
changes nothing, because the same fragment is still in the address bar. The user is locked
out with no way to relate this to the URL.
The input is not exotic: a truncated percent sequence is what a clipped copy-paste produces,
and what some mail clients do when they wrap a long link. Our application links to
/registre#<uuid> from e-mails and from an assistant answer, which is how we ran into it.
Expected. An unreadable fragment is not addressed to Clerk. Reading location.hash never
requires decoding, and decoding a value that comes from the URL should fail softly:
initialization should carry on and treat an undecodable fragment as an absent one.
This is the same class of bug as #9333 (ClerkRequest.parseCookies, malformed percent-escape
in the Cookie header), which was fixed in @clerk/backend. This one is the browser-side
counterpart, on the URL rather than on cookies, and is still present in clerk-js 6 as
loaded by @clerk/nextjs 7.9.1.
Workaround we shipped, an inline script in <head>, before the Clerk bundle runs:
!function () {
function n() {
try { decodeURIComponent(location.hash.slice(1)); }
catch (e) { history.replaceState(null, "", location.pathname + location.search); }
}
n();
addEventListener("hashchange", n);
}();
It removes the unreadable fragment before anything reads it, but every application would have
to know about this.
Environment
@clerk/nextjs: 7.9.1
@clerk/localizations: 4.16.0
clerk-js: 6 (loaded from the CDN as clerk.browser.js)
next: 16.3.4 (App Router, Turbopack)
node: 24.16.0
browser: Chromium 151.0.7922.34 (Playwright)
instance: development
- 主要语言
- TypeScript
- 星标
- 1.8k
- 派生
- 477
- 平均合并
- 2 天 25 分钟
- 30 天内合并 PR
- 267
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
clerk/javascript 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 78/100
clerk/javascript#10026 · 1 条评论 ·
维护者通常 1 天内回复
-
@clerk/nextjs: onBeforeSetActive never settles when invalidateCacheAction rejects (e.g. after a redeploy), so setActive and signOut hang forever可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
clerk/javascript#9987 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 3/5 1-2 天 新手友好度 65/100
clerk/javascript#10011 ·
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 50/100
clerk/javascript#9984 ·
维护者通常 1 天内回复
-
M2M Token only authentication in Clerk Middleware可能已有人在做 @wobsoriano 于 7 天前认领。 未关闭needs-triage
clerk/javascript#9981 · 已指派 1 人 ·
维护者通常 1 天内回复
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 85/100
wardian-app/Wardian#1603 ·
维护者通常 1 天内回复
-
Sign the pledge未关闭
难度 1/5 1 小时以内 新手友好度 85/100
input-output-hk/devx-updates#168 ·
维护者通常 1 天内回复
-
triage
难度 2/5 1-3 小时 新手友好度 75/100
维护者通常 1 天内回复
-
agent-ready area: config area: skills type: chore upstream: brain-kit
难度 1/5 1 小时以内 新手友好度 95/100
-
dev experience frontend good first issue
难度 2/5 1-3 小时 新手友好度 78/100
cuttle-cards/cuttle#1403 ·
维护者通常 1 天内回复