Theme / v13.24.1

Claude-Mem

Claude Code 持久化記憶系統

實戰範例

實戰範例 010:清理敏感記憶 — 用 forget 安全擦除意外寫入的金鑰觀察

新手嚮導:當 save_observation 意外把含金鑰的內容寫進長期記憶時,如何用 get_observations 定位、用 forget 徹底擦除,並以 <private> 標籤與 sensitive 分類預防再次發生。

實戰背景

Claude-Mem 把記憶落在本地 SQLite,比起雲端日誌更安全,但「本地」不等於「可以亂寫」。最常見的意外是:除錯過程中,AI 把一段包含範例金鑰或內部 URL 的程式碼當成「重要觀察」存了下來。一旦這台機器被其他人接手、或記憶檔被備份上傳,就會變成資安破口。

痛點與問題描述: 我們在排查 Stripe webhook 簽章驗證時,AI 為了方便日後回顧,把一段「測試用的範例簽章 + webhook secret」一起寫進了觀察。範例 secret 雖然不是正式金鑰,但格式真實,被當成真金鑰濫用的風險仍在。我們需要:

  1. get_observations 找出含敏感內容的觀察 ID。
  2. forget 從本地 SQLite 徹底刪除。
  3. <private> 標籤與 v13.13.0 起的 sensitive 分類,從源頭預防再次寫入。

本範例走完敏感記憶的「發現 → 擦除 → 預防」三步。


端到端 6 輪協作紀錄

── 第 1 輪:察覺異常 ──

  • You:

    我剛剛在 Web Viewer 串流頁看到一條觀察,內容好像有 webhook secret。
    幫我用 get_observations 查 stripe 或 webhook 相關的記憶。
  • AI:

    我來檢索可能含敏感內容的條目。

    CM 呼叫: get_observations(query: "stripe webhook secret sign") CM 回傳:

    [
      {
        "observationId": "obs_2078",
        "category": "debugging",
        "summary": "Stripe webhook 簽章驗證:使用 whsec_abc123EXAMPLEsecret 作為測試金鑰,於 webhookHandler.ts 第 28 行驗證 sig header。"
      }
    ]

    確認問題:obs_2078 含有 webhook secret 格式的字串 whsec_abc123EXAMPLEsecret。雖然標了 EXAMPLE,但格式是真實的 Stripe secret,不該留在記憶庫。

── 第 2 輪:擴大搜尋,確認沒有漏網之魚 ──

  • You:

    再用 key、token、password、secret 幾個關鍵字各查一次,別只看 obs_2078。
  • AI:

    合理,敏感字串可能散在多條觀察。我並行查四個關鍵字。

    CM 呼叫(四次):

    get_observations(query: "api key")
    get_observations(query: "bearer token")
    get_observations(query: "password")
    get_observations(query: "secret")

    CM 回傳彙整:

    [
      {"observationId": "obs_2078", "summary": "...whsec_abc123EXAMPLEsecret..."},
      {"observationId": "obs_2103", "summary": "資料庫連線字串使用 ${DB_PASSWORD} 環境變數,未硬編碼。"}
    ]

    結果:obs_2078 必須刪除;obs_2103 提到 DB_PASSWORD 但只是說明使用環境變數,沒有實際值,保留。

    這一步很重要:forget 不該無腦全刪,必須逐筆判讀,避免把「提到金鑰規範」的安全守則跟「真的含金鑰」的髒資料一起清掉。

── 第 3 輪:執行 forget 安全擦除 ──

  • You:

    好,刪掉 obs_2078。
  • AI:

    我來執行擦除。

    CM 呼叫: forget(observationId: "obs_2078") CM 回傳: {"status": "deleted", "observationId": "obs_2078"}

    obs_2078 已從本地 SQLite 徹底移除。再次查詢確認:

    CM 呼叫: get_observations(query: "whsec") CM 回傳: []

    空陣列,敏感記憶已清乾淨。

── 第 4 輪:用 <private> 標籤預防未來寫入 ──

  • You:

    下次除錯時要怎麼避免 AI 又把 secret 存進去?
  • AI:

    Claude-Mem 支援 <private> 標籤。在對話中,把不想被寫入記憶的內容用 <private>...</private> 包起來,自動壓縮與顯式 save_observation 都會跳過這段。

    實務做法是:貼上真實金鑰、JWT、連線字串時,用標籤包住:

    我們的 webhook 驗證邏輯如下,使用這個 secret:
    <private>whsec_realSecretValueHereDoNotLog</private>
    請幫我檢查簽章驗證流程。

    這段 <private> 內容會出現在當下對話讓我能讀取處理,但不會被壓縮進持久化記憶。get_observationstimeline 之後都查不到。

── 第 5 輪:套用 sensitive 分類(v13.13.0+) ──

  • You:

    那如果是「不是秘密、但不宜外流」的內容呢?例如內部 staging URL、未發布的營收數字。
  • AI:

    v13.13.0 起新增了第 9 類觀察分類 sensitive,專門處理這種「非隱私、但不宜外流」的內容:內部 URL、未發布計畫、商業指標。寫入時直接指定:

    CM 呼叫:

    save_observation(
      key: "staging_endpoint_internal",
      value: "內部 staging 環境位於 staging-internal.example.net,僅 VPN 可達,禁止寫入對外文件。",
      category: "sensitive"
    )

    CM 回傳: {"status": "saved", "observationId": "obs_2110"}

    重點:sensitive 類別在預設安裝下會自動觸發 Telegram 通知,提醒有人寫入了一條需要留意的內容。既有安裝會在升級到 v13.13.0 時,把舊的 security_alert 自動遷移成 security_alert,sensitive,自訂過的清單則保留不動。

    如果你不想接 Telegram 通知,可在設定檔調整會觸發通知的分類清單(theme.yaml 中提到的 security_alert,sensitive 即為此清單格式),但不建議sensitive 整個關掉,這條分類是資料外流的早期預警。

── 第 6 輪:建立寫入前自檢 SOP ──

  • You:

    幫我定義一個檢查規則,讓 AI 每次寫觀察前都先過一次。
  • AI:

    建議把這條 SOP 本身寫成一條 architecture 類別的觀察,這樣未來所有 Session 都會讀到:

    CM 呼叫:

    save_observation(
      key: "observation_write_precheck",
      value: "呼叫 save_observation 前必須自檢:(1) value 中不得含 whsec_/sk_/Bearer/密碼格式字串;(2) 真實金鑰須以 <private> 包住;(3) 內部 URL、未公開指標改用 sensitive 分類;(4) 不確定時先問使用者再寫入。",
      category: "architecture"
    )

    CM 回傳: {"status": "saved", "observationId": "obs_2111"}

    從此以後,我在每次呼叫 save_observation 之前都會先對照 obs_2111 的四點檢查表,把防線推到寫入之前,而不是等髒資料進庫再用 forget 收拾。


關鍵學習點

  • forget 之前先逐筆判讀:用多個關鍵字(key、token、password、secret)擴大搜尋,但要人工判斷哪些是「含真實金鑰」、哪些只是「提到金鑰規範」,後者必須保留,否則會連安全守則一起清掉。
  • <private> 標籤是源頭防線:在對話中貼真實金鑰、JWT、連線字串時用 <private>...</private> 包住,內容當下可讀但不會被壓縮進持久化記憶,比事後 forget 更省事。
  • sensitive 分類不等於機密:v13.13.0 起的 sensitive 類別處理的是「非隱私但不宜外流」的內容(內部 URL、未發布計畫、商業指標),預設觸發 Telegram 通知,是把外流風險提前預警的機制。
  • 把檢查規則本身寫進記憶:把「寫入前自檢 SOP」存成一條 architecture 觀察,防線就從事後擦除推進到事前攔截,這是 Claude-Mem 自我演進的典型用法。