Tutorial iframe host allowlist
Tutorial markdown can embed <iframe> elements from a small set of SAP-blessed video hosts. The allowlist is enforced at three layers, each providing defense-in-depth against the other two.
Enforcement layers
- Sanitizer (scripts/parsers/sanitize-html.ts) strips iframes whose src hostname is not on the list at build time.
- CSP (approuter/xs-app.json) makes the browser refuse to render iframes whose src host is not in
frame-srcat runtime. - Lint (scripts/lint-rules/iframe-non-allowlisted-host.ts) warns tutorial authors at PR time before the sanitizer silently strips their content.
Current allowlist
| Host | Rationale |
|---|---|
www.youtube.com | YouTube embed - the most common video host in the catalog (~129 occurrences). |
youtube.com | YouTube bare-domain form - occasional author variant. |
youtu.be | YouTube short-link form. Browsers evaluate CSP against the original src URL before any redirect, so this needs its own entry. |
microlearning.opensap.com | SAP openSAP microlearning embed (~7 occurrences). |
sapvideo.cfapps.eu10-004.hana.ondemand.com | SAP internal video service. |
player.vimeo.com | Vimeo player embed (standard <iframe> form). |
vimeo.com | Vimeo bare-domain form — some author embed codes use this origin directly. |
<video> element support
Native <video src> elements are supported in tutorial markdown. Because default-src 'self' would otherwise block external media sources, the CSP also carries a media-src directive:
media-src 'self' https://raw.githubusercontent.comThis allows <video> files served from GitHub raw content (https://raw.githubusercontent.com). If a new raw-media host is needed, add it to media-src in approuter/xs-app.json and document it here.
Extending the allowlist
Three files must be updated together:
- Sanitizer constant - scripts/parsers/sanitize-html.ts, the
ALLOWED_IFRAME_HOSTNAMESarray. - CSP
frame-src- approuter/xs-app.json, line 6 (the singleContent-Security-Policyvalue,frame-srcdirective). - This doc page - the table above.
The lint rule auto-updates because it imports ALLOWED_IFRAME_HOSTNAMES.
After the three-file change, the next MTA redeploy activates the new allowlist on DEV/QA/PROD.
Attribute allowlist
Allowed iframe attributes (defense-in-depth - narrower than HTML5 defaults):
src- host-checked byallowedIframeHostnames, scheme-checked byallowedSchemeswidth,height- author-controlled sizingframeborder- legacy attribute, harmlessallow- feature-policy delegationallowfullscreen- fullscreen permission flagtitle- a11y labelloading- performance hint (lazy)referrerpolicy- privacy attribute
Deliberately excluded: srcdoc (would allow inline HTML bypassing the host allowlist), name (deprecated), sandbox (authors should not relax our defaults), on* event handlers (always stripped by sanitize-html).
History
- PR #141 (issue #136, 2025-05-31) - migrated from a regex sanitizer to the
sanitize-htmlnpm package. Iframes were deliberately stripped because the regex sanitizer couldn't enforce a hostname allowlist. YouTube embeds in ~65 catalog tutorials silently disappeared. - PR #560 (2026-06-22) - re-introduced a narrow iframe allowlist using
sanitize-html'sallowedIframeHostnamesoption + the matching CSPframe-srcdirective + a lint rule that warns authors at PR time. Surfaced when Tom noticed the missing "Video Version" embed on/tutorials/hana-cloud-cap-create-project.