OSV 1.4.0 · github-reviewed · 修改于 2026-06-09 19:58
发布时间
2026-06-04 22:55
GitHub 审查时间
2026-06-04 22:55
NVD 发布时间
—
源文件
advisories/github-reviewed/2026/06/GHSA-cq3f-vc6p-68fh/GHSA-cq3f-vc6p-68fh.json
You are affected if all of the following are true:
better-auth at a version >= 1.6.0, < 1.6.11.deviceAuthorization plugin is enabled in your auth config (deviceAuthorization() in your plugins array).The standard device-flow UX displays user codes to humans, so realistic exposure includes shoulder-surfing, screen-share, voice or video calls, support-chat transcripts, referrer headers, and shared logs.
If your application does not enable the deviceAuthorization plugin, you are not affected.
Fix:
[email protected] or later.Better Auth's deviceAuthorization plugin treated any authenticated session as the owner of any pending device code. The ownership gate on POST /device/approve and POST /device/deny short-circuited whenever the row's userId was unset, and the GET /device verification handler did not claim the row. An authenticated attacker who learned a valid user_code before the legitimate user completed approval could bind the polling device to the attacker's account or deny the legitimate flow.
The device authorization flow binds the polling device to the user who entered the user code on the verification page. In affected versions, the plugin only created that binding at approve or deny time, with no claim at the verification step. The ownership check at approve and deny short-circuited when the owner was missing, accepting any authenticated caller instead of rejecting the request.
The fix changes GET /device to claim the pending row for the calling session. The approve and deny gates now require strict equality between the row's owner and the calling session. RFC 8628 §5.5 covers this risk class as Session Spying: a malicious party can hijack a session by completing authorization before the legitimate initiating user does.
Fixed in [email protected]. After the patch, GET /device claims the pending row for the calling session, and POST /device/approve and POST /device/deny reject calls whose session does not match the claimed owner. Custom verification pages must serve GET /device to an authenticated session for the flow to succeed.
If you cannot upgrade immediately:
deviceAuthorization() from your plugins array.before hook on POST /device/approve and POST /device/deny that tracks which session called GET /device for each user code, and rejects calls from a different session.expiresIn plugin option to reduce the exploitation window.Reported by Quikturn Security Team.