HTMLIFrameElement: srcdoc 屬性

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2020 年 1 月⁩ 起,所有主流瀏覽器均已支援。

警告:此屬性會將其輸入解析為 HTML,並將結果寫入 iframe 的 DOM。像這樣的 API 被稱為注入點,並且可能是跨站指令碼 (XSS) 攻擊的載體,如果輸入最初來自攻擊者。

您可以透過始終分配 TrustedHTML 物件而不是字串並強制執行可信型別來減輕這種風險。有關更多資訊,請參閱安全注意事項

HTMLIFrameElement 介面的 srcdoc 屬性用於獲取或設定 iframe 文件的內聯 HTML 標記。

這反映了 <iframe> 元素的 srcdoc 屬性。

獲取此屬性會返回一個包含 iframe 文件 HTML 序列化的字串。如果未設定該值,則返回 undefined

設定此屬性可以接受 TrustedHTML 物件或字串。它會將此輸入解析為 HTML 文件,並用結果替換 iframe 的內容。

異常

TypeError

如果在可信型別CSP 強制執行且未定義預設策略時將屬性設定為字串,則丟擲此錯誤。

描述

srcdoc 屬性反映了 <iframe> 元素 srcdoc 屬性的內容,並且可以用於設定或獲取屬於 <iframe> 的 HTML 文件。

設定此屬性時,輸入應定義一個有效的 HTML 文件,包括 文件型別宣告<html><body> 以及其他標籤。但請注意,瀏覽器通常能容忍無效的標記,並且大多數瀏覽器應該會嘗試渲染僅包含 body 內容的輸入。

瀏覽器支援的任何標記都將被解析/序列化,包括Shadow 根

請注意,如果設定了此屬性,它將覆蓋在 src 屬性中設定的任何值。

安全注意事項

srcdoc 屬性預設允許任何 HTML 標記在 iframe 中執行。如果 iframe 未使用內容安全策略 (CSP) 的 sandbox 指令進行沙箱化(或已沙箱化但包含 allow-same-origin 值),則它將與父級同源。這意味著 iframe 將完全訪問父級 DOM 和資源,反之亦然。

如果使用者提供的潛在不安全字串未經驗證就注入到 iframe 中,這將是跨站指令碼 (XSS) 攻擊的重要載體。考慮以下程式碼,其中來自使用者的 HTML 字串可能被傳遞到一個 iframe 中,然後該 iframe 被新增到文件中。

js
const untrustedStringFromUser = `<!doctype html><script src="http://evil.com/naughty.js"></script>`;
const iframe = document.createElement("iframe");
iframe.srcdoc = untrustedStringFromUser;
document.body.appendChild(iframe);

如果 iframe 不需要訪問您的父文件,您可以透過使用不包含 allow-same-origin 值的 CSP 沙箱來降低風險。然後,iframe 將被視為跨域資源,攻擊將受到顯著限制。您也可以使用更通用的 CSP 來限制允許從何處獲取指令碼和其他資源。

您可以始終將 TrustedHTML 物件而不是字串賦給 srcdoc,並使用 require-trusted-types-for CSP 指令強制執行可信型別,以進一步降低風險。這可確保輸入透過轉換函式,該函式有機會清理輸入,在注入之前刪除潛在的危險標記。

示例

從 iframe 讀取 HTML

讀取 srcdoc 會導致使用者代理序列化 iframe 的文件。

給定以下 HTML

html
<frame
  id="example"
  srcdoc="<!doctype html><body><p>Hello World!</p></body>"></frame>

您可以按如下所示獲取並記錄標記

js
const frame = document.querySelector("#frame");
const frameDoc = frame.srcdoc;
console.log(frameDoc); // "<!doctype html><body><p>Hello World!</p></body>"

替換 iframe 的內聯源

在此示例中,我們將透過將 HTML 分配給 iframe 的 srcdoc 屬性來替換其文件。為降低 XSS 風險,我們將首先從包含 HTML 的字串建立 TrustedHTML 物件,然後將該物件分配給 srcdoc

Trusted Types 尚未在所有瀏覽器中得到支援,因此我們首先定義可信型別 tinyfill。它充當可信型別 JavaScript API 的透明替代品。

js
if (typeof trustedTypes === "undefined")
  trustedTypes = { createPolicy: (n, rules) => rules };

接下來,我們建立一個 TrustedTypePolicy,它定義了一個 createHTML() 方法,用於將輸入字串轉換為 TrustedHTML 例項。通常,createHTML() 的實現會使用像 DOMPurify 這樣的庫來清理輸入,如下所示。

js
const policy = trustedTypes.createPolicy("my-policy", {
  createHTML: (input) => DOMPurify.sanitize(input),
});

然後我們使用這個 policy 物件從潛在不安全的輸入字串建立 TrustedHTML 物件,並將結果分配給元素。

js
// The potentially malicious string
const untrustedString =
  "<!doctype html><body><p>I might be XSS</p><img src='x' onerror='alert(1)'></body>";

// Create a TrustedHTML instance using the policy
const trustedHTML = policy.createHTML(untrustedString);

// Inject the TrustedHTML (which contains a trusted string)
const frame = document.querySelector("#frame");
const frameDoc = frame.srcdoc;

警告:雖然您可以直接將字串賦給 srcdoc,但如果待插入的字串可能包含潛在的惡意內容,這是一種安全風險。您應該使用 TrustedHTML 來確保在插入內容之前對其進行清理,並且應該設定 CSP 標頭來強制執行可信型別

規範

規範
HTML
# dom-iframe-srcdoc

瀏覽器相容性