從 OpenClaw 談起:AI 工具的 OAuth 風險,不該只藏在免責聲明裡

內容目錄

當一般使用者被教會「把登入後的 redirect URL 貼回工具」是正常操作時,問題已經不只是單一漏洞,而是整個產品敘事對安全邊界的淡化。

OpenClaw 暴露的不只是漏洞,而是錯誤的授權心智模型

這不是抽象的安全疑慮,而是已經發生過的問題

OpenClaw 之所以值得拿來當文章開頭,不是因為它的登入流程「看起來怪怪的」,而是這種做法已經被證明會打開真實的攻擊面。GitHub 公開安全公告指出,OpenClaw 的 manual Chutes OAuth login flow 在受影響版本中,可能接受攻擊者控制的 callback 輸入,導致 OAuth 的 state 驗證被繞過,進而造成 credential substitution。更直接地說,如果攻擊者能誘導使用者在手動登入提示中貼上惡意 callback 資料,OpenClaw 可能會去交換錯誤帳號的 authorization code,並把不屬於使用者預期的 token 持久化到本機。這個問題影響 <= 2026.2.13,並在 2026.2.14之後修補。 

也因為這個案例是公開、可驗證、而且有明確修補版本的事件,它讓整個問題從「我覺得這樣不太安全」變成「這種流程真的曾經讓安全邊界失守」。對讀者來說,這一點很重要。因為很多人對 OAuth 流程的判斷,常常停在「反正能登入成功就好」,但 OpenClaw 的例子剛好說明:當一個產品把 callback 交給使用者手動搬運時,風險不是想像出來的,而是足以被正式列成安全公告的。 

問題不只在少驗了一個 state,而是 callback 被外包給使用者

如果只把這件事理解成「開發者少驗了一個 state」,其實會低估它真正暴露的設計問題。因為這個漏洞背後更值得警惕的,不只是某個參數驗證不完整,而是整個流程本身已經把原本應該由應用程式自己處理的 callback 環節,外包給使用者手動完成。

正常的 OAuth 心智模型應該是這樣:使用者在瀏覽器授權,然後應用程式透過註冊好的 redirect URI、localhost callback,或其他標準機制,自動接住回傳結果並完成後續驗證。使用者理解的是「我在授權一個 app」,而不是「我在幫 app 搬運一段帶有敏感參數的網址」。但在 OpenClaw 這類手動流程裡,使用者被要求自己處理最後那段重新導向結果,這代表本來應該由系統穩定處理的安全邊界,被轉化成需要人肉判斷與複製貼上的操作。

這裡最值得寫進文章的地方是:一旦 callback 不再由程式完整接住,而是依賴使用者手動轉交,安全問題就不再只是技術細節,而是設計責任的位移。 工具把自己的授權收尾工作,變成使用者的操作負擔;而一旦使用者貼錯、被騙、或根本不理解自己貼了什麼,後果仍然由使用者承擔。

真正危險的,是它在教一般人錯誤的授權習慣

這也是我認為 OpenClaw 最值得被拿來討論的地方。它暴露的不只是漏洞,而是錯誤的授權心智模型

對工程師來說,看到 redirect URL 可能知道裡面有 code、state、query parameter,也大概知道那不是普通網址;但對一般使用者來說,那通常只是一段登入完成後跳出來的網址。他們不會知道裡面哪些欄位有安全意義,也不會知道為什麼這種資訊不該被隨意轉交。當產品把這種操作包裝成正常登入流程時,它其實是在訓練使用者形成一個很危險的直覺:登入後跳轉出來的網址,可以複製、貼上、轉交給其他工具。

這種習慣之所以危險,不只是因為它容易出錯,而是因為它和釣魚、callback 置換、授權碼攔截這類社工情境太接近。使用者一旦被教會「這樣做是正常的」,下一次遇到相似情境時,防備心就會明顯下降。也就是說,這個問題的層級其實比單一漏洞更大:它會把本來應該被保護起來的授權邊界,重新定義成「只要能登入成功,貼一段網址回去也是合理操作」。

所以 OpenClaw 的警訊,不只是修掉漏洞就結束了

GitHub 公告顯示,OpenClaw 後來已修補這個問題,將 manual flow 改為要求完整 redirect URL,並驗證返回的 state,而且公告也特別說明,自動 local callback flow 不受影響,因為它會在本地 HTTP callback handler 中正確驗證 state。這代表技術上當然可以把問題補起來。 

但這篇文章真正要指出的是:就算某個漏洞被修掉,這類流程本身仍然可能在產品層面留下錯誤訊號。 它讓使用者以為 OAuth 可以被理解成一種「登入後再把網址貼回工具」的模式,甚至誤以為這是 AI 工具很正常的授權方式。這才是 OpenClaw 作為案例最值得被寫下來的原因。它提醒我們,授權流程不能只看能不能用、能不能修、能不能補,而必須看它到底在教使用者什麼。

這種手動 OAuth 流程,為什麼不適合一般使用者

它也許適合受限環境,但不適合被包裝成通用登入方式

先講公平一點,這種手動 OAuth 流程不是完全沒有存在理由。在 CLI、SSH、遠端伺服器或沒有可用瀏覽器的環境裡,工具先產生登入網址,讓使用者在另一個瀏覽器完成授權,再把結果帶回原本的客戶端,確實有它的歷史背景。OAuth 對 native app 的最佳實務本來就鼓勵使用外部瀏覽器完成授權,而不是把帳密直接輸入到工具本身;RFC 8252 明確指出,native app 的 authorization request 應透過 external user-agent,也就是通常由使用者自己的瀏覽器來完成。 

但這裡有個很重要的界線:外部瀏覽器授權是標準做法,不等於要求使用者手動搬運 redirect URL 也是標準做法。 真正理想的流程,應該是應用程式自己透過註冊好的 callback URI、loopback interface 或其他受控機制把授權結果接回來,而不是讓使用者在最後一哩扮演 callback handler。RFC 8252 之所以被視為 best current practice,講的是「用瀏覽器授權」這件事;它不是在鼓勵產品把最後的安全收尾工作交給終端使用者。 

所以問題不在於這類流程能不能在特殊環境下成立,而在於它一旦被包裝成面向大眾的通用登入方式,就會把受限環境下的工程折衷,誤導成一般使用者也應該照做的正常操作。

一般使用者無法判斷自己到底貼了什麼

對工程師來說,看到 redirect URL,可能會知道裡面帶有 code、state 或其他 query parameter,也知道這不是普通的結果頁網址;但對非技術背景的人來說,那通常只是一串登入後跳轉出來的網址。他們大多不會知道哪些參數與授權碼有關,也不會知道哪些欄位是用來防止 CSRF、避免 callback 被置換,或區分這次登入是不是原本那個 session 發起的。

也正因為如此,要求一般使用者去複製、貼上、轉交這段網址,本質上就是把一個他們無法理解的敏感環節,包裝成看似簡單的使用步驟。這不是「多按一步」而已,而是要求使用者在毫無能力驗證內容的前提下,替系統搬運帶有授權語意的資料。OpenClaw 的公開安全公告正好證明,這個環節一旦處理不好,攻擊者就可能利用使用者貼入 attacker-controlled callback input,造成 state 驗證被繞過與 credential substitution。 

這也是為什麼這種流程對一般使用者特別不合適。因為它不是單純的 UX 繞路,而是把本來應該由系統自動、嚴格、可驗證地處理的內容,轉成需要使用者憑直覺完成的操作。 一旦產品這樣設計,使用者就會被迫在不知道自己授了什麼、交出了什麼、風險在哪裡的情況下完成授權。

它會訓練出危險的安全直覺

比起單一次操作失誤,更值得警惕的是這種流程長期會養成什麼習慣。當一個產品讓使用者習慣於「登入完成後,把最後那段網址貼回工具」,它其實是在默默建立一個錯誤的授權心智模型:登入後跳轉出來的資訊,是可以被複製、轉交、甚至提供給第三方工具的。

這種心智模型很危險,因為它和釣魚、callback 置換、授權碼攔截這類社工情境太接近。使用者一旦被教育成「這就是 AI 工具常見的登入方式」,下一次看到類似畫面時,警戒心就會下降。也就是說,這類流程的問題不只是某次登入會不會出錯,而是它會不會把原本應該高度受控的授權邊界,重新定義成一種可由人肉搬運、靠使用者自行判斷的流程。

對內部工程工具來說,這種風險有時會被接受,因為使用者本來就知道自己在做什麼,也知道這是一種 fallback。但對一般使用者產品來說,這就不再只是工程折衷,而是一種錯誤的安全教育。產品不是在幫使用者理解授權,而是在訓練他們忽略授權流程中的敏感訊號。

真正更好的替代方案其實早就存在

如果一個工具真的運行在沒有瀏覽器、沒有方便 callback 的環境裡,也不代表只能依賴這種手動貼網址的方式。OAuth 其實早就有更適合受限裝置與輸入受限場景的標準流程。RFC 8628 定義的 Device Authorization Grant,就是為了讓那些缺乏瀏覽器、或不適合在本機輸入大量認證資訊的裝置完成授權;它的設計重點,就是讓使用者改在另一個較完整的裝置上操作,而不是把整段 redirect URL 手動搬回原客戶端。 

這一點很關鍵,因為它代表市場上不是沒有替代方案,而是很多產品選擇了比較省事、比較快能做出來的方式。從工程角度看,manual pasteback 可能是短期內最容易完成的流程;但從產品與安全角度看,它不應該是給一般使用者的預設選項。當更合適的標準流程已經存在時,仍然要求一般使用者靠複製貼上 callback 來完成授權,本質上就不是在「解決環境限制」,而是在把設計成本與安全成本一起轉嫁給使用者。

所以不適合一般使用者的,不只是流程本身,而是它背後的責任分配

總結來說,這種手動 OAuth 流程不適合一般使用者,並不是因為它永遠不能用,而是因為它把責任分配做錯了。工具本來應該自己處理 callback、自己驗證回傳狀態、自己把授權邊界藏在系統內部;但在這種流程裡,最後卻變成使用者要自己搬運敏感資訊、自己承擔誤貼風險、自己面對不理解參數內容的後果。

這也是為什麼我會把它看成一個產品分級問題,而不只是實作問題。對內部工程情境,它可以是備援;對一般使用者產品,它不該是預設。 一旦這個界線被拿掉,產品實際上就是在告訴使用者:授權流程裡那些你看不懂的東西,照著貼就好。這不只是脆弱的 UX,更是脆弱的安全觀。

以 LobeHub/LobeChat 為對照:安全資訊是否只留在文件與免責聲明

技術文件裡知道正規做法,這點其實沒有太大懸念

如果把 OpenClaw 當成一個把問題直接暴露出來的案例,那麼 LobeHub/LobeChat 更像是另一種值得觀察的對照組。至少從官方文件來看,LobeHub 並不是不知道標準 OAuth/OIDC 該怎麼做。它的 self-hosting 文件清楚列出 Generic OIDC 與其他 provider 的 callback URL 格式,包含本機開發與正式環境的設定方式;開發文件也明確說明新增 authentication provider 時應使用的 callback 路徑格式。換句話說,在技術文件層面,它對「正常的 app 應如何接住授權回傳」這件事是有明確概念的。 

這點還不只停在基礎文件。LobeHub 在 2025 年 4 月的 RFC #7377 裡,明確提議在 LobeChat Web 服務端引入基於 oidc-provider 的 OAuth 2.0 / OIDC 授權伺服器,並且直接寫出要遵循最佳實務、強制 PKCE、支援 Refresh Token,以及用 scopes 做更細緻的最小權限控制。這表示至少在架構設計層面,它不是把 OAuth 當成一個隨便接上去的登入按鈕,而是理解它應該是產品級授權基礎設施的一部分。 

但真正影響一般使用者的,往往不是 RFC,而是推廣頁與生態內容

問題也正出在這裡。對多數一般使用者來說,他們不會先讀 RFC,也不太會先看 self-hosting 的 auth 文件;真正塑造他們認知的,通常是首頁、Discover 頁、marketplace 清單、社群分享與各種「可以快速接起來」的內容。而在這些公開可見的頁面裡,更常出現的是功能、能力、擴充性、部署便利性與整合體驗,而不是一開始就把授權風險與安全邊界放在最前面。從我查到的 LobeChat Discover 頁面來看,的確可以找到安全或風險相關提醒,但它們多半是附屬訊息,而不是產品敘事的主軸。 

這就是我想拿它來對照 OpenClaw 的原因。OpenClaw 把問題暴露得很直接:使用者真的被要求去搬運 callback URL,最後還發生了 state 驗證問題。LobeHub/LobeChat 則比較像是另一條路線:技術上知道正規做法,生態上也不是完全沒有安全提醒,但面向一般使用者的訊號未必足夠強,未必足以讓非技術背景的人在「快速接入」與「安全理解」之間,真的把後者放在前面。 

免責聲明確實存在,但它更像附註,不像主流程設計

這裡最值得寫清楚的是:我不是要說 LobeHub/LobeChat 完全不談安全,而是它公開可見的很多安全提示,形式上更接近 warning、backup warning 或 disclaimer。像 Discover 上就能找到明確寫著「Disclaimer & Backup Warning」的頁面,提醒某些 MCP Server 有寫入、修改使用者資料的權限,使用前應先備份;也能找到直接標示「故意包含安全漏洞」「不要部署到生產環境」「不要用真實敏感資料」的專案頁。這些提示當然有價值,至少它沒有假裝風險不存在。 

但問題在於,這些提示的存在,不等於安全已經被做成產品主流程的一部分。 如果安全資訊主要以 warning、disclaimer、backup notice 的形式出現,它更像是在提醒「這裡有風險,請自行注意」,而不是在設計上主動限制風險、降低誤用機率、或幫一般使用者建立正確的授權心智模型。換句話說,這種做法比較像責任告知,不完全等於安全設計。尤其當使用者最先接觸到的仍然是功能與能力,而不是權限邊界與風險說明時,安全就很容易退到附註的位置。 

這也是為什麼「文件知道安全」和「產品真的把安全講清楚」是兩件事

很多技術產品都會出現這種落差:工程文件、架構提案、RFC 裡把最佳實務寫得很完整,但到了真正對外擴散的內容,最醒目的訊號卻是「功能很多」「接入很快」「生態很活躍」。LobeHub/LobeChat 目前給人的感覺就有一部分是這樣:從文件與 RFC 看,它顯然知道 OAuth/OIDC 的標準路線,也知道 PKCE、Refresh Token、Scopes 這些安全元素的重要性;但從公開可見的生態內容來看,安全提醒常常仍是附帶文字,而不是使用者最先被教會的事情。 

也因此,把 LobeHub/LobeChat 放在這篇文章裡,最準確的寫法不是說它「不安全」,而是說它提供了一個很典型的對照:技術文件裡懂安全,不代表推廣敘事裡也真的把安全放在前面;而當安全主要留在文件角落、warning 區塊或 disclaimer 中時,一般使用者很可能仍然接收不到足夠清楚的風險訊號。 這正是 OpenClaw 事件之後更值得被拿出來討論的地方。 

AI 工具授權真正該問的是:該用 API,還是使用者 OAuth?

先把問題問對:你要的是「能力接入」,還是「代表使用者行動」

很多 AI 工具一談到授權,就直接往 OAuth 走,彷彿只要和外部服務整合,答案就一定是「請使用者登入並授權」。但這其實常常是把問題問錯了。OAuth 2.0 的核心用途,是讓第三方應用程式取得對某個 HTTP 服務的有限存取權,這個權限可能是代表資源擁有者,也就是代表使用者去存取其資源;也可能是代表應用程式自己,也就是在沒有使用者介入的情況下,以客戶端自身身分取得權限。RFC 6749 從一開始就把這兩種情境分開定義了。 

所以,AI 工具在設計授權時,第一個問題不該是「怎麼把使用者登入接進來」,而應該是:這個工具到底是在替產品本身取得某種能力,還是真的需要代表某個使用者去操作那個人的私人資源? 這兩件事長得很像,但責任邊界完全不同。前者更接近系統對系統的能力接入,後者才是典型的使用者授權問題。

如果產品只是要能力,優先考慮的通常應該是 API

假設你的 AI 工具只是要調用模型、呼叫某個固定後端服務、執行伺服器端工作流、讀寫屬於產品自己的資料,或整合一個本來就提供 machine-to-machine 存取的服務,那麼比較合理的起點通常不是使用者 OAuth,而是正式 API、client credentials、service account,或其他 server-to-server 的授權方式。OAuth 2.0 本身就把 Client Credentials Grant 定義為一種讓 client 代表自己而非代表使用者取得權限的方式,適用於 client 存取自己控制下的受保護資源,或與授權伺服器事先安排好的資源。 

這個差別很重要,因為一旦你本質上是在解決「產品能力」問題,卻硬要包裝成「使用者登入授權」,結果通常就是責任邊界混亂。工具明明只是要一個穩定、可控、可審計的能力入口,最後卻變成拿終端使用者的個人登入態、個人 token、個人 scopes 來撐整個整合。這不只讓最小權限難做,也會讓撤銷、輪替、審計與故障排查變得麻煩。更糟的是,使用者會誤以為自己只是「登入一下」,其實授出去的是持續性的第三方存取權。

真的需要代表使用者時,才是 OAuth 的主場

當然,不是所有整合都能用 API 取代。如果一個 AI 工具真的需要代表使用者讀取或修改該使用者在第三方服務裡的私人資源,例如讀 Gmail、寫 Google Calendar、操作 Notion 私人頁面、讀 Slack 私訊,這時候使用者 OAuth 就是合理而且必要的設計方向。因為這類情境的核心不是「產品本身要一個能力」,而是「使用者要授權這個工具代替自己做某些事」。RFC 6749 對 OAuth 的核心描述正是第三方應用程式取得對 HTTP 服務的有限存取權,且這個權限可以是透過資源擁有者與服務之間的批准互動來取得。 

但即使在這種情境下,正確問題仍然不是「怎麼最快把 token 弄到手」,而是「怎麼讓這個代表使用者的授權過程可理解、可控、可撤銷,並且盡可能採最小權限」。也就是說,需要 OAuth,不等於可以把任何拿 token 的手段都合理化。 如果某個產品其實是在處理使用者資源,卻仍然依賴手動貼 redirect URL、模糊不清的 scopes、過度寬鬆的持久化權限,那問題依然存在,只是披上了「這本來就是 OAuth 場景」的外衣。

受限裝置有標準做法,不代表可以把人肉搬運當成常態

有些產品會用一個很常見的理由來替手動流程辯護:它運行在 CLI、遠端主機或其他沒有瀏覽器的環境,所以只能讓使用者在別處登入,再把結果帶回來。這個理由有一部分成立,但它不能自動推出「所以讓使用者貼 redirect URL 是合理預設」。因為 OAuth 其實早就為這類受限場景準備了專門的 Device Authorization Grant。RFC 8628 明確說明,這個流程是為那些缺乏瀏覽器、或輸入能力受限到不適合在本機完成認證的裝置而設計的;它的目標就是讓使用者改在另一個較完整的裝置上完成授權,而不是把 callback 結果手動搬回原客戶端。 

同樣地,對 native app 而言,最佳實務是透過外部瀏覽器完成授權,再由 app 透過受控的 redirect URI 或 loopback interface 接回結果。RFC 8252 強調的是 external user-agent 與受控 callback 的結合,而不是把 callback handler 交給使用者扮演。 

所以,當一個產品面對受限環境時,真正該做的是:先判斷自己是不是應該用 Device Flow,或能否用標準 browser callback;而不是直接把「複製貼上最後那段網址」視為理所當然的登入方式。

真正成熟的授權設計,先分清楚主體,再選流程

把這一切收斂成一句話就是:先分清楚誰是授權主體,再決定用哪種機制。 如果主體是產品本身,優先想 API、service account、client credentials 或其他 machine-to-machine 方案。若主體是使用者本人,而且工具要代表他去碰他的私人資源,才進入使用者 OAuth 的範疇。至於在使用者 OAuth 的範疇裡,再進一步依場景選擇標準 browser callback、Authorization Code + PKCE,或在裝置受限時採用 Device Authorization Grant。RFC 6749 定義了代表使用者與代表 client 自己兩種不同的基本模式;RFC 8628 則補上了受限裝置的標準授權路徑。 

也因為如此,很多 AI 工具今天真正的問題,不是「它有沒有用 OAuth」,而是它拿錯了工具,或者更早一步,它連問題都問錯了。 明明只是要能力接入,卻用使用者 OAuth;明明是受限裝置場景,卻不用 Device Flow;明明是代表使用者的高敏感授權,卻又把最後一哩外包給人肉搬運。這些都不是單純的工程瑕疵,而是授權設計邏輯沒有釐清。

結論:安全不能只靠 warning、disclaimer 與使用者自行判斷

OpenClaw 給的警訊,不只是某個漏洞,而是一種產品級訊號

OpenClaw 這次最值得被記住的,不只是它曾在 manual OAuth flow 上出現 state 驗證繞過,而是它讓一個更大的問題浮上檯面:當產品把 callback 的最後一哩交給使用者手動搬運時,安全邊界就不再只存在於程式裡,而會被轉嫁到使用者的理解能力與判斷力上。 GitHub 的安全公告已經很清楚地說明,受影響版本的手動流程可能接受 attacker-controlled callback input,導致 credential substitution;修補後才要求貼完整 redirect URL,並驗證 state。這表示風險不是抽象討論,而是已經在真實產品中發生過。  

也因此,這篇文章真正想指出的,不是「某個專案做錯了某個細節」,而是只要產品開始讓一般使用者把授權流程裡的敏感資訊當成普通網址處理,整個安全模型就已經在鬆動。 漏洞可以修,參數可以補驗,但如果使用者被教會的是「登入後把網址貼回工具很正常」,那麼留下來的問題就不只是一次實作瑕疵,而是一種錯誤的授權心智模型。這也是為什麼 OpenClaw 這個案例,值得被當成對整個 AI 工具生態的警訊,而不只是單點事件。  

LobeHub/LobeChat 的對照提醒我們:知道安全,不等於把安全放進主流程

LobeHub/LobeChat 這邊提供的是另一種值得注意的訊號。從文件與 RFC 看,它們對 OAuth/OIDC 的標準路線並不陌生,甚至有意識地談到 callback、PKCE、refresh token 與更完整的授權基礎設施。這代表技術層面並不是不知道怎麼做。  

但真正值得警惕的是,對一般使用者來說,最先接觸到的通常不是 RFC,而是產品頁、教學文、Discover 頁、marketplace 與各種快速接入內容。 如果安全資訊主要停留在文件、warning、backup warning 或 disclaimer,而不是被做成主流程中的清楚說明、預設保護與風險引導,那它的效果往往更接近責任告知,而不是安全設計。也就是說,產品可能在工程文件裡懂安全,卻沒有在使用者體驗裡把安全講清楚。這正是它和 OpenClaw 形成對照的地方:一邊把風險暴露成實際事件,另一邊則提醒我們,安全也可能悄悄退到附註的位置。  

真正成熟的 AI 工具授權,應該把正確的事做成預設

所以最後的判準其實很簡單:安全不能只靠 warning、disclaimer,或期待使用者自己看懂那些本來就不該由他判斷的細節。 如果是產品本身要取得能力,應先考慮正式 API、service account、client credentials 這類 machine-to-machine 路線;如果真的是代表使用者去操作其私人資源,才進入使用者 OAuth 的場景,而在受限裝置或 CLI 條件下,也應優先考慮標準的 Device Authorization Grant 或受控 callback,而不是把「人肉搬運 redirect URL」常態化。OAuth 2.0 本來就區分代表使用者與代表 client 自己的兩種模式,而 RFC 8628 也已為受限裝置提供標準流程。  

換句話說,好的授權設計不是把風險寫在頁尾,而是把正確的流程做成預設,把錯誤的操作變得不容易發生。對內部工程工具,某些手動流程可以是備援;但對面向一般使用者的 AI 產品,不能把這種 fallback 包裝成正常操作,更不能把安全責任留給 warning、disclaimer,或一句「請自行注意」。如果一個產品真的重視安全,它應該讓使用者幾乎不需要理解 callback 細節,也能在合理保護下完成授權;而不是要求使用者在不理解的前提下,替系統完成最後一哩。