ShadowRoot: innerHTML 屬性
警告:此屬性將輸入解析為 HTML,並將結果寫入 DOM。像這樣的 API 被稱為注入槽,如果輸入最初來自攻擊者,它們可能是跨站指令碼(XSS)攻擊的潛在途徑。
您可以透過始終分配 TrustedHTML 物件而不是字串並強制執行可信型別來減輕這種風險。有關更多資訊,請參閱安全注意事項。
ShadowRoot 介面的 innerHTML 屬性用於獲取或設定 ShadowRoot 內部 DOM 樹的 HTML 標記。
值
獲取該屬性會返回一個字串,其中包含陰影根(shadow root)的後代節點的 HTML 序列化表示。
設定該屬性接受一個 TrustedHTML 物件或一個字串。它會將此值解析為 HTML,並用解析結果替換元素的所有後代節點。當設定為 null 值時,該 null 值會被轉換為空字串(""),因此 shadowRoot.innerHTML = null 等同於 shadowRoot.innerHTML = ""。
異常
SyntaxErrorDOMException-
如果嘗試使用格式不正確的 HTML 字串來設定
innerHTML的值,將丟擲此異常。 TypeError
描述
innerHTML 獲取陰影根內巢狀的子 DOM 元素的序列化表示,或者設定應該被解析以替換陰影根內 DOM 樹的 HTML 或 XML。
請注意,當 < 和 > 字元出現在屬性值中時,某些瀏覽器會將其序列化為 < 和 >(請參閱瀏覽器相容性)。這是為了防止潛在的安全漏洞(變異 XSS),其中攻擊者可以精心構造繞過淨化函式的輸入,從而實現跨站指令碼(XSS)攻擊。
安全注意事項
innerHTML 屬性是 跨站指令碼(XSS)攻擊的潛在攻擊向量,在這種攻擊中,使用者提供的潛在不安全字串會在未經驗證的情況下注入 DOM。雖然該屬性可以阻止注入的 <script> 元素執行,但它仍然容易受到攻擊者精心構造的、用於執行惡意 JavaScript 的其他 HTML 方法的攻擊。例如,下面的示例將在 error 事件處理程式中執行程式碼,因為 <img> 的 src 值不是有效的影像 URL。
const name = "<img src='x' onerror='alert(1)'>";
shadowRoot.innerHTML = name; // shows the alert
您可以透過始終分配 TrustedHTML 物件而不是字串來緩解這些問題,並透過使用 require-trusted-types-for CSP 指令 強制執行受信任型別。這確保輸入會透過一個轉換函式,該函式有機會在注入之前 清理輸入以移除潛在危險的標記。
示例
讀取元素的 HTML 內容
讀取 innerHTML 會導致使用者代理序列化陰影根的後代節點。
給定以下 HTML
<div class="host">
<template shadowrootmode="open">
<p>My name is Joe</p>
</template>
</div>
您可以按照如下所示獲取並記錄陰影根的標記。
const shadowHost = document.querySelector("#host");
const shadowRoot = shadowHost.shadowRoot;
const contents = shadowRoot.innerHTML;
console.log(contents); // "\n <p>My name is Joe</p>\n"
設定 ShadowRoot 的 innerHTML
在此示例中,我們將透過將 HTML 分配給元素的 innerHTML 屬性來替換元素的 DOM。為了降低 XSS 風險,我們將首先從包含 HTML 的字串建立 TrustedHTML 物件,然後將該物件分配給 innerHTML。
受信任的型別尚未在所有瀏覽器中得到支援,因此我們首先定義 受信任型別 tinyfill。它充當受信任型別 JavaScript API 的透明替代品。
if (typeof trustedTypes === "undefined")
trustedTypes = { createPolicy: (n, rules) => rules };
接下來,我們建立一個 TrustedTypePolicy,它定義一個 createHTML() 方法,用於將輸入字串轉換為 TrustedHTML 例項。通常,createHTML() 的實現會使用像 DOMPurify 這樣的庫來清理輸入,如下所示:
const policy = trustedTypes.createPolicy("my-policy", {
createHTML: (input) => DOMPurify.sanitize(input),
});
然後我們使用這個 policy 物件從潛在不安全的輸入字串建立 TrustedHTML 物件,並將結果分配給元素。
// The potentially malicious string
const untrustedString = "<p>I might be XSS</p><img src='x' onerror='alert(1)'>";
// Create a TrustedHTML instance using the policy
const trustedHTML = policy.createHTML(untrustedString);
// Get the shadow root
const shadowHost = document.querySelector("#host");
const shadowRoot = shadowHost.shadowRoot;
// Inject the TrustedHTML (which contains a trusted string)
shadowRoot.innerHTML = trustedHTML;
警告:雖然您可以直接將字串分配給 innerHTML,但這是一種 安全風險,如果待插入的字串可能包含潛在的惡意內容。
規範
| 規範 |
|---|
| HTML # dom-shadowroot-innerhtml |
瀏覽器相容性
載入中…