想法與洞見

探索 AI 優先開發、編碼護欄和可處置架構。

你的依賴能讀取環境變數。JavaScript允許它們這麼做

Ambient Authority意味著Node.js程序中的任何程式碼都能觸碰檔案系統、網路和執行環境。本文將講解如何透過lockdown、compartment和顯式capability傳遞來剝除它。

一個被攻破的傳遞依賴就能外洩你的 、寫入你的檔案系統、開啟出站連線。它不需要你的程式碼存在漏洞。它只需要存在於同一個程序裡。在JavaScript中,每個模組預設繼承執行時的全部權限。這就是Ambient Authority,而移除它是你能對Node.js應用程式做的最有效的安全性升級之一。 Ambient…

網路鄰近性不等於身份:服務如何在不依賴環境權威的情況下完成認證

大多數服務間信任來自網路位置,而非密碼學證明。本文介紹能力權杖、mTLS 和 SPIFFE 如何讓服務在不依賴環境權威的前提下完成認證,以及為何這做起來比想像中困難。

你的微服務共享同一個 VPC,因此彼此信任。這種信任就是環境權威:呼叫服務的權限不是由密碼學證明授予的,而是由網路拓撲決定的。一旦攻擊者突破邊界,就會繼承所有這些權限。 服務絕對可以在沒有環境權威的情況下完成認證。更難回答的問題是:為什麼你的平台讓你覺得這是在背叛既有架構。…

你的依賴項目可以讀取磁碟上的任何檔案。cap-std 讓它們必須先取得權限。

Rust 的標準函式庫將環境檔案系統權限授予每一個依賴項目。cap-std 以權能式 API 取而代之,強制程式碼在開啟路徑之前先證明自己擁有存取權。

依賴樹中的任何 crate 都可以開啟 、寫入你的 目錄,或是列舉專案中的每一個檔案。Rust 的標準函式庫不會要求任何權限。它預設任何有能力呼叫 的程式碼,都有權碰觸作業系統允許的任何路徑。 cap-std 改變了這個預設。它是 Rust I/O module…

你的服務是無心的共犯:Confused Deputy 攻擊的原理

Confused deputy 攻擊會誘騙具有高權限的服務,使其利用自身權限對自己造成傷害。以下是攻擊者如何利用隱性信任,以及為什麼 capability-based security 是解方。

你的服務持有雲端儲存空間的 API key。一名使用者發出請求,你的服務盡責地寫入一個檔案。結果檔案卻落在攻擊者的 bucket,而不是你的,現在他們擁有了你的資料。你剛剛成為了一名無心的共犯。 這就是 confused deputy 攻擊。攻擊者本身無法寫入目標…

你的權限檢查正在欺騙你

Capability-based security 用不可偽造的權限 token 取代散落各處的 role 檢查。以下是如何在 TypeScript 中實作它,同時不讓你的程式碼變得難以閱讀。

事後來看,每個權限漏洞都長得一模一樣。呼叫堆疊深處的某個函式假設呼叫者已經檢查過 。結果沒有。或者新增了一個角色,你在 47 個檔案裡用 grep 搜尋 ,祈禱自己沒有漏掉任何一處。 Capability-based security…

如果每個函式都必須被賦予權限,而不是預設擁有呢?

大多數程式碼在 ambient authority 下執行:每個函式都能碰觸一切。Capability-based security 顛覆了這個模式,強制函式必須接收明確且受範圍限制的權限。

你的 函式能夠存取資料庫、payment gateway與審計紀錄,只因為它恰好執行在同一個程序裡。如果攻擊者在某個 HTTP handler 中發現注入漏洞,他們就能繼承這一切權限。這個函式從未要求過這些能力,它僅僅因為被部署在這裡,就理所當然地預設擁有。 這就是 ambient…

讓 Type Checker 看得見的錯誤:停止拋出,開始回傳

拋出的例外會讓型別系統看不到失敗路徑。以下是為什麼明確回傳錯誤能讓你的程式碼更誠實,以及如何在不折磨自己的前提下採用這種做法。

你的函式簽名說它回傳 。其實不然。它回傳 ,不然就爆炸。型別系統根本不知道有第二條路。 這就是基於例外的錯誤處理最根本的不誠實。每一次 都是一條編譯器看不見、無法檢查、也無法強制的控制流路徑。你會得到型別檢查完美通過、卻還是在正式環境崩潰的程式碼,只因為有人在三層呼叫之外忘了寫 。…

Rust newtype 讓錯誤狀態在編譯期就無法被表示,而且完全免費

一個單欄位的 wrapper struct 就能在不增加任何位元組開銷的情況下,抓出單位混淆與型別錯用的 bug。

把 的使用者 ID 傳給一個預期接收訂單 ID 的函式,Rust 不會抱怨。兩者都是 。編譯器看到的是完全相同的型別,所以幫不上忙。你會在執行期才發現,通常是在正式環境,通常是在一次你以為安全的重構之後。 這正是 newtype 存在要消滅的 bug 類別。 newtype 是一個單欄位的 tuple…

Switch statements 在編譯時期就讓 bug 漏了進去

TypeScript 的 switch statements 會默默讓你忘記處理某些 case。以下說明如何將它們替換成經過 exhaustiveness-check 的 pattern,讓錯誤在 build 階段就失敗,而不是跑到 runtime 才出錯。

你重構了一個 shape type,加了一個新的 variant,TypeScript 依然顯示綠燈。CI 過了。Deploy 出去了。結果使用者踩到一個 runtime branch,回傳了 ,你的 app 就在 production 炸了。 罪魁禍首幾乎肯定是一個 switch…

編譯器應該抓住遺漏的狀態案例,而不是你的 QA 團隊

在state machine中新增狀態很簡單。記得更新每一個 switch 語句則不然。以下是讓 TypeScript 在你忘記處理某個案例時拒絕編譯的方法。

state machine一開始很乾淨。三個值,三個 switch 分支。然後重試邏輯加入了第四個狀態。部分失敗加入了第五個。你更新了 reducer,卻漏掉了狀態徽章元件、analytics mapper 和匯出格式化程式。 一切都能編譯通過。這個 bug…