Your HTML renders inside <iframe sandbox="allow-scripts"> under a strict
Content-Security-Policy that fails silently — non-compliant HTML renders blank or
partially broken with no error surfaced. Follow this contract and the page just works.
This is a snapshot for offline use. The authoritative, always-current version is generated from the live viewer source and served at
https://<your-sharepoint-host>/_html/llms.txt. When they disagree, trust/_html/llms.txt.
default-src 'none';
script-src 'unsafe-inline' 'unsafe-eval';
style-src 'unsafe-inline';
img-src data: blob:;
font-src data: blob:;
connect-src 'none';
worker-src 'none';
object-src 'none';
base-uri 'none';
form-action 'none';
The wrapper iframe additionally applies frame-src 'none'.
- No external resources — no
<script src>,<link href>,<img src=https://…>,@import,url(https://…), remote fonts, or CDNs. Inline everything or usedata:/blob:URIs. - All script inline —
<script>blocks only. No module imports, noimport(), no<script src>. - All styling inline —
<style>orstyle="…". No<link rel="stylesheet">. - No runtime network —
fetch,XMLHttpRequest,WebSocket,sendBeacon,EventSourceare blocked (connect-src 'none'). Use the LiveData manifest for SharePoint data. - No storage primitives —
localStorage,sessionStorage,indexedDB,document.cookie(opaque-origin sandbox). Setlocation.hashdirectly for cross-reload state — do not usehistory.pushState/replaceState, which always throwsSecurityErrorhere (the sandboxed document's base URL is inherited from the wrapper'sblob:origin, so anyurlargument resolves to a mismatched origin). - No top-level navigation, popups, form submission, workers, or plugins.
alert/confirm/promptare no-ops. - Inline
on*=handlers work (rewritten to nonced scripts) but are an XSS sink if they template untrusted data — preferaddEventListenerfor computed/user/fetched data. - Save as UTF-8 (add a BOM when authoring by hand if non-ASCII renders wrong).
<a href> opens only for same-tenant SharePoint hosts or the external allowlist.
javascript: / vbscript: / data: hrefs are rejected.
Embed a manifest; the host prefetches each item server-side with the viewer's credentials
and injects window.__LD_RESULTS__ (keyed by spItemUrl) before your script runs:
<script type="application/json" class="ka-livedata-manifest">
[{"spItemUrl":"https://contoso.sharepoint.com/…/_api/v2.0/drives/{driveId}/items/{itemId}"}]
</script>- Item cap: 32 per page.
- Per-item size cap: 50 MB.
- Supported formats: text, csv, xlsx-sheets.
- Refresh:
postMessage({type:'ka-html-viewer-refresh'}, '*')to the parent (debounced to 5s).
See ../assets/templates/livedata-dashboard.html
for a working example.