搜尋

首頁  >  問答  >  主體

無需 JavaScript 即可安全地將不受信任的輸入指派給 CSS 自訂屬性:指南

假設我有一個字串鍵和字串值的對象,我想將它們作為 CSS 自訂屬性寫入伺服器產生的一些 HTML 中。我怎樣才能安全地做到這一點?

我所說的安全是指

為了簡單起見,我將限制鍵只允許 [a-zA-Z0-9_-] 類別中的字元。

透過閱讀 CSS 規範和一些個人測試,我認為透過以下步驟來取得值可以取得很大的進展:

我根據這個 CSS 語法規格想出了上述步驟

對於上下文,這些屬性可以由我們在其他地方插入的用戶自訂樣式使用,但同一物件也用作模板中的模板數據,因此它可能包含旨在作為內容的字串和預期的字串的混合作為CSS 變數。我覺得上面的演算法取得了很好的平衡,既非常簡單,又不會冒丟棄太多可能在CSS 中有用的鍵值對的風險(即使考慮到未來對CSS 的添加,但我想確保我沒有遺漏什麼。


這裡有一些 JS 程式碼,展示了我想要實現的目標。 obj 是有問題的對象,而 preprocessPairs 是一個函數,它接受該對象並對其進行預處理,刪除/重新格式化值,如上述步驟所述。

function generateThemePropertiesTag(obj) {
  obj = preprocessPairs(obj);
  return `<style>
:root {
${Object.entries(obj).map(([key, value]) => {
  return `--theme-${key}: ${value};`
}).join("\n")}
}
</style>`
}

所以當給定一個這樣的物件時

{
  "color": "#D3A",
  "title": "The quick brown fox"
}

我希望 CSS 看起來像這樣:

:root {
--theme-color: #D3A;
--theme-title: The quick brown fox;
}

雖然 --theme-title 在 CSS 中使用時是一個非常無用的自訂變量,但它實際上並沒有破壞樣式表,因為 CSS 會忽略它不理解的屬性。

P粉356361722P粉356361722535 天前782

全部回覆(1)我來回復

  • P粉898107874

    P粉8981078742023-09-07 21:34:20

    我們實際上可能只使用正規表示式和一些其他演算法,而不必依賴特定的語言,希望這是您所需要的。

    透過宣告物件鍵位於 [a-zA-Z0-9_-] 內,我們需要以某種方式解析值。

    價值模式

    因此,我們可以將其分為幾類,然後看看我們會遇到什麼(為了清楚起見,它們可能會稍微簡化):

    1. '.*'(用撇號包圍的字串;貪婪)
    2. ".*"(用雙引號括起來的字串;貪婪)
    3. [ -]?\d (\.\d )?(%|[A-z] )?(整數和小數,可選百分比或帶單位)
    4. #[0-9A-f]{3,6}(顏色)
    5. [A-z0-9_-] (關鍵字、命名顏色、「緩入」等內容)
    6. ([\w-] )\([^)] \) (類似url()calc() 的函數> 等等)

    第一次過濾

    我可以想像在嘗試識別這些模式之前您可以進行一些過濾。也許我們首先修剪值字串。正如您所提到的, <<> 可以在preprocessPairs() 函數的開頭進行轉義,因為它不會出現為我們上面有的任何模式。如果您不希望在任何地方出現未轉義的分號,您也可以轉義它們。

    識別模式

    然後我們可以嘗試識別中的這些模式,對於每個模式,我們可能需要再次執行過濾。我們期望這些模式將由一些(或兩個)空白字元分隔。

    包括對多行字串的支援應該沒問題,這是一個轉義的換行符。

    語言環境

    我們需要認識到我們至少要過濾兩個上下文 - HTML 和 CSS。當我們在