Source: full HTML (SPA shell)
Labels: #security #privacy #perf #seo #a11y
Verdict: Medium (mostly solid, a few easy wins)
It’s a modern module-bundled SPA with nonced inline scripts (good CSP hygiene) and a lean shell, but there are a handful of privacy, referrer/OG, and perf tune-ups you can apply without changing app logic.
Findings & fixes
High
- Consent gating for telemetry & 3P beacons
Several inline frameworks log to Bing endpoints and error/CLS pipelines (/fd/ls/lsp.aspx,directLog,navigator.sendBeacon). Make sure they respect user choice (region, consent).
Fix: initialize logging only after consent and set a global flag to no-op before consent:// before any instrumentation is defined: window.__allowTelemetry__ = false; // wrap directLog / sendBeacon uses: function safeBeacon(url, body){ if (!window.__allowTelemetry__) return false; try { return navigator.sendBeacon?.(url, body) || false; } catch { return false; } } - Referrer Policy (privacy)
You setorigin-when-cross-origin. Preferstrict-origin-when-cross-originto avoid sending path/query to same-scheme cross-origin.<meta name="referrer" content="strict-origin-when-cross-origin">
Medium
- Open Graph image size
og:image:width=600/height=315is small for high-DPI shares.
Fix: serve a 1200×630 (or larger) asset and declare dimensions:<meta property="og:image" content="https://…/copilot-1200x630.jpg"> <meta property="og:image:width" content="1200"> <meta property="og:image:height" content="630"> - Preconnect your static CDN
Static bundles/fonts are onstudiostaticassetsprod.azureedge.net. Add preconnect to reduce TLS/handshake latency:<link rel="preconnect" href="https://studiostaticassetsprod.azureedge.net" crossorigin> <link rel="dns-prefetch" href="//studiostaticassetsprod.azureedge.net"> - Subresource Integrity (SRI)
External scripts/styles load withcrossoriginbut no SRI. If bundle URLs are content-hashed and stable, addintegrity:<link rel="stylesheet" href="…/index-abc123.css" integrity="sha384-…" crossorigin="anonymous"> <script type="module" src="…/vendor-abc123.js" integrity="sha384-…" crossorigin="anonymous"></script> - Noscript accessibility hint
The shell is just<div id="app"></div>. Provide a minimal noscript message for assistive tech and non-JS environments:<noscript><p>Copilot requires JavaScript to run. Please enable JavaScript, or use the Copilot mobile app.</p></noscript> - Permissions/Feature Policy
You likely don’t need broad device APIs on the landing shell. Set a conservative policy at the document level (headers ideally, meta fallback in dev):<!-- Prefer server header: Permissions-Policy --> <meta http-equiv="Permissions-Policy" content="geolocation=(), microphone=(), camera=(), usb=(), payment=()">
Low
- Icons & favicons
You declare both.icoand.svgfavicons. That’s fine; ensure the.svgincludes a fallback color for dark mode. Considermask-iconfor Safari pinned tabs. - Font loading
You preload the variable font—good. Ensurefont-display: swap|optionalis set in the CSS to mitigate FOIT (not visible from the HTML). - SEO / SPA routing
Since this is an SPA, confirm your client router updates<title>/og:*/canonicalon route changes (or serve pre-rendered HTML per route). The shell meta is good for the root. - CSP & security headers(server)
You use nonces on inline scripts—great signal that CSP is enforced. Also ensure headers for:Content-Security-Policywithscript-src 'self' 'nonce-…' https://studiostaticassetsprod.azureedge.net …Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadX-Content-Type-Options: nosniffCross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp(if you ever do streaming/wasm and can isolate)
Quick wins
- Switch referrer policy → strict-origin-when-cross-origin.
- Add preconnect to
azureedge.net. - Upgrade OG image to 1200×630.
- Gate telemetry/logging behind consent flag.
- Provide noscript message.
- Add SRI to static bundles (if feasible).
- Confirm CSP + security headers on the edge.
Drop the next URL when you’re ready—I’ll keep stamping these with concise diffs and priority.