iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0
Modern Web

AI 驅動的 Web 資安新時代系列 第 7

Day7 - CSP 策略最佳化:由 Agent 自動生成與測試

  • 分享至 

  • xImage
  •  

為什麼需要 CSP 最佳化?

  • CSP(Content-Security-Policy)是防止 XSS 與惡意資源的重要防線
  • 但實際撰寫很困難:
    • 太嚴 → 前端功能壞掉
    • 太鬆 → 等於沒保護
  • 多數團隊最後只能「抄範例」或「放很寬鬆」,導致安全性不足

傳統做法的限制

  • 開發者需要 人工測試:重整 → 看 console 錯誤 → 改 CSP → 再測
  • 大型系統維護成本高,常常有遺漏
  • 常見安全掃描警告:unsafe-inlineunsafe-eval
  • 最後 CSP 不是太鬆,就是過於複雜難以維護

CSP Agent 的自動化流程

為了最佳化 CSP,我們設計一個 CSP Agent,自動完成以下工作:

  1. 收集錯誤 → 爬瀏覽器 console log、掃描 CSP 問題
  2. 分析結果 → 判斷哪些 script 被阻擋
  3. 修正策略 → 自動生成新 CSP(加上 nonce/hash)
  4. 驗證測試 → 套用新策略並重新檢查網站是否正常運作

server – Express 伺服器

1、初始化伺服器 & 預設 CSP

先建立一個 Express 伺服器,並設定一個最簡單的 CSP:只允許本站資源。

import express from "express";

const app = express();
app.use(express.json());

let currentCSP = "default-src 'self';"; // 初始策略

2、中介層:每次回應都加 CSP

middleware 會在每次回應時,自動加上最新的 CSP header

app.use((req, res, next) => {
  res.setHeader("Content-Security-Policy", currentCSP);
  next();
});

3、測試頁面:包含一個 inline script

頁面裡故意放了一個 inline script,用來測試 CSP 是否會阻擋它

app.get("/", (req, res) => {
  res.send(`
    <html>
      <head><title>CSP Test</title></head>
      <body>
        <h1>Hello CSP</h1>
        <script>
          console.log("Inline script executed");
        </script>
      </body>
    </html>
  `);
});

4、API:更新 CSP

提供一個 API,讓我們的 Agent 可以動態更新 CSP

app.post("/set-csp", (req, res) => {
  currentCSP = req.body.csp || currentCSP;
  res.json({ message: "CSP updated", csp: currentCSP });
});

5、啟動伺服器

app.listen(3000, () => {
  console.log("Server running on http://localhost:3000");
});

CSP Agent 模擬程式

1、初始策略

先設定一個 非常嚴格的 CSP

  • 所有資源只能從本站載入(default-src 'self'
  • Script 也只能來自本站(script-src 'self'
  • 這會導致 inline script 被完全阻擋,用來測試 Agent 的修正能力
import puppeteer from "puppeteer";
import fetch from "node-fetch";
import { GoogleGenerativeAI } from "@google/generative-ai";
import 'dotenv/config';

let cspPolicy = "default-src 'self'; script-src 'self';";

2、更新 CSP API

透過 fetch 呼叫伺服器提供的 /set-csp API,把新的 CSP 策略傳送過去,讓 Express 伺服器即時套用。

async function applyCSP(csp) {
  await fetch("http://localhost:3000/set-csp", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ csp }),
  });
}

3、 測試 CSP 是否造成錯誤

利用 Puppeteer 模擬瀏覽器行為,開啟測試頁面並收集 console log。透過檢查 log 訊息,我們可以判斷 CSP 是否阻擋了 inline script 的執行。

async function testCSP() {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();
  const logs = [];
  page.on("console", (msg) => logs.push(msg.text()));
  await page.goto("http://localhost:3000");
  await browser.close();
  return logs;
}

4、用 Gemini 官方 SDK 分析錯誤訊息並建議 CSP

將瀏覽器回傳的錯誤訊息丟給 Gemini 模型,請 AI 判斷問題並生成新的 CSP 策略。

程式會自動清理回傳內容,只保留實際可套用的策略字串(例如 script-src 'self' 'nonce-xxxxxx';)。


async function analyzeErrorWithAI(logs) {
  const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
  const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });

  const prompt = `
  以下是瀏覽器的 CSP 錯誤訊息:
  ${logs.join("\n")}
  請判斷要怎麼修正策略,並輸出一份新的 Content-Security-Policy。
  請只輸出一行 CSP,格式例如:
  script-src 'self' 'nonce-xxxxxx';
  `;

  const result = await model.generateContent(prompt);
  let policy = result.response.text().trim();

  //  移除多餘的前綴
  policy = policy.replace(/^Content-Security-Policy:\s*/i, "");

  return policy;
}

5、主程式流程

(async () => {
  console.log("[Agent] 套用初始 CSP:", cspPolicy);
  await applyCSP(cspPolicy);

  let logs = await testCSP();
  console.log("[Browser Logs]", logs);

  if (logs.some(log => log.includes("Refused to execute inline script"))) {
    console.log("[Agent] 偵測到 CSP 問題,呼叫 Gemini AI 分析中...");
    const newCsp = await analyzeErrorWithAI(logs);
    console.log("[AI 建議的 CSP]:", newCsp);

    await applyCSP(newCsp);

    logs = await testCSP();
    console.log("[Browser Logs after fix]", logs);
  }
})();

測試結果(Console Logs 對照)

  • 初始策略(過嚴格)
[Agent] 套用初始 CSP: default-src 'self'; script-src 'self';
[Browser Logs] [
  Refused to execute inline script because it violates the following Content Security Policy directive...
]

inline script 被阻擋,功能壞掉

  • AI 修正後(Gemini 建議策略)
[Agent] 偵測到 CSP 問題,呼叫 Gemini AI 分析中...
[AI 建議的 CSP]: script-src 'self' 'unsafe-inline';
[Browser Logs after fix] [ 'Inline script executed' ]

Gemini 生成的新策略允許了 unsafe-inline,因此 inline script 成功執行。

不過要注意:unsafe-inline 雖然解決了錯誤,但安全性相對較低,實務上建議改用

noncehash 方式來允許特定 script。


上一篇
DAY6 - HTTPS 與憑證安全:AI Agent 自動檢查弱點
下一篇
Day8 - Cookie / Session 安全:Agent 審查 Secure、HttpOnly、SameSite
系列文
AI 驅動的 Web 資安新時代8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言