@optilogic/core 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -2968,7 +2968,24 @@ declare namespace CsvRenderer {
2968
2968
  /**
2969
2969
  * HtmlRenderer
2970
2970
  *
2971
- * Renders HTML content in a fully sandboxed iframe.
2971
+ * Renders HTML content in a triple-locked iframe:
2972
+ *
2973
+ * Layer 1 — `sandbox="allow-scripts"` (no allow-same-origin):
2974
+ * Opaque origin. No access to parent DOM, cookies, localStorage,
2975
+ * sessionStorage, or IndexedDB. No form submission, popups,
2976
+ * top-navigation, or pointer-lock.
2977
+ *
2978
+ * Layer 2 — Content-Security-Policy (iframe `csp` attr + meta fallback):
2979
+ * Blocks ALL network requests (fetch, XHR, WebSocket, sendBeacon,
2980
+ * image pings, external scripts/styles/fonts). Only inline scripts,
2981
+ * inline styles, and data:/blob: images are allowed.
2982
+ *
2983
+ * Layer 3 — Permissions-Policy via `allow` attribute:
2984
+ * Explicitly denies every device/sensor API (camera, microphone,
2985
+ * geolocation, payment, USB, display-capture, etc.).
2986
+ *
2987
+ * Additional hardening:
2988
+ * - referrerpolicy="no-referrer" — no URL leakage to embedded content
2972
2989
  */
2973
2990
  declare function HtmlRenderer({ content, fileName, className, }: FileRendererProps): react_jsx_runtime.JSX.Element;
2974
2991
  declare namespace HtmlRenderer {
package/dist/index.d.ts CHANGED
@@ -2968,7 +2968,24 @@ declare namespace CsvRenderer {
2968
2968
  /**
2969
2969
  * HtmlRenderer
2970
2970
  *
2971
- * Renders HTML content in a fully sandboxed iframe.
2971
+ * Renders HTML content in a triple-locked iframe:
2972
+ *
2973
+ * Layer 1 — `sandbox="allow-scripts"` (no allow-same-origin):
2974
+ * Opaque origin. No access to parent DOM, cookies, localStorage,
2975
+ * sessionStorage, or IndexedDB. No form submission, popups,
2976
+ * top-navigation, or pointer-lock.
2977
+ *
2978
+ * Layer 2 — Content-Security-Policy (iframe `csp` attr + meta fallback):
2979
+ * Blocks ALL network requests (fetch, XHR, WebSocket, sendBeacon,
2980
+ * image pings, external scripts/styles/fonts). Only inline scripts,
2981
+ * inline styles, and data:/blob: images are allowed.
2982
+ *
2983
+ * Layer 3 — Permissions-Policy via `allow` attribute:
2984
+ * Explicitly denies every device/sensor API (camera, microphone,
2985
+ * geolocation, payment, USB, display-capture, etc.).
2986
+ *
2987
+ * Additional hardening:
2988
+ * - referrerpolicy="no-referrer" — no URL leakage to embedded content
2972
2989
  */
2973
2990
  declare function HtmlRenderer({ content, fileName, className, }: FileRendererProps): react_jsx_runtime.JSX.Element;
2974
2991
  declare namespace HtmlRenderer {
package/dist/index.js CHANGED
@@ -7450,18 +7450,80 @@ function CsvRenderer({ content, className }) {
7450
7450
  ) });
7451
7451
  }
7452
7452
  CsvRenderer.displayName = "CsvRenderer";
7453
+ var CSP_POLICY = [
7454
+ "default-src 'none'",
7455
+ "script-src 'unsafe-inline'",
7456
+ "style-src 'unsafe-inline'",
7457
+ "img-src data: blob:"
7458
+ ].join("; ");
7459
+ var PERMISSIONS_POLICY = [
7460
+ "camera=()",
7461
+ "microphone=()",
7462
+ "geolocation=()",
7463
+ "payment=()",
7464
+ "usb=()",
7465
+ "display-capture=()",
7466
+ "fullscreen=()",
7467
+ "autoplay=()",
7468
+ "web-share=()",
7469
+ "screen-wake-lock=()",
7470
+ "xr-spatial-tracking=()",
7471
+ "magnetometer=()",
7472
+ "gyroscope=()",
7473
+ "accelerometer=()"
7474
+ ].join(", ");
7475
+ function buildSandboxedHtml(content) {
7476
+ return `<!DOCTYPE html>
7477
+ <html>
7478
+ <head>
7479
+ <meta http-equiv="Content-Security-Policy" content="${CSP_POLICY}">
7480
+ <script>
7481
+ // Neutralise APIs that the sandbox + CSP can't fully block.
7482
+ // This runs in <head> before any user content in <body>.
7483
+ // Uses Object.defineProperty to make overrides non-configurable
7484
+ // so user scripts cannot restore the original via prototype tricks.
7485
+ (function(){
7486
+ // postMessage: iframe can message parent even without allow-same-origin.
7487
+ // Kill it so content can't probe or spam any future parent listeners.
7488
+ // Also kill parent/top refs as an extra layer.
7489
+ var noop = function(){};
7490
+ try { Object.defineProperty(window, 'postMessage', { value: noop, writable: false, configurable: false }); } catch(e) {}
7491
+ try { Object.defineProperty(window, 'parent', { value: window, writable: false, configurable: false }); } catch(e) {}
7492
+ try { Object.defineProperty(window, 'top', { value: window, writable: false, configurable: false }); } catch(e) {}
7493
+ try { Object.defineProperty(window, 'opener', { value: null, writable: false, configurable: false }); } catch(e) {}
7494
+
7495
+ // RTCPeerConnection: not governed by CSP; could contact a STUN server
7496
+ // over UDP to leak the user's IP. Kill all browser-prefixed variants.
7497
+ var rtcNames = ['RTCPeerConnection', 'webkitRTCPeerConnection', 'mozRTCPeerConnection'];
7498
+ for (var i = 0; i < rtcNames.length; i++) {
7499
+ try { Object.defineProperty(window, rtcNames[i], { value: undefined, writable: false, configurable: false }); } catch(e) {}
7500
+ }
7501
+ })();
7502
+ </script>
7503
+ </head>
7504
+ <body>${content}</body>
7505
+ </html>`;
7506
+ }
7453
7507
  function HtmlRenderer({
7454
7508
  content,
7455
7509
  fileName,
7456
7510
  className
7457
7511
  }) {
7512
+ const srcDoc = React20.useMemo(
7513
+ () => buildSandboxedHtml(content ?? ""),
7514
+ [content]
7515
+ );
7516
+ const iframeProps = { csp: CSP_POLICY };
7458
7517
  return /* @__PURE__ */ jsx(
7459
7518
  "iframe",
7460
7519
  {
7461
- srcDoc: content ?? "",
7520
+ srcDoc,
7462
7521
  sandbox: "allow-scripts",
7463
7522
  title: fileName,
7464
- className: cn("h-full w-full border-0", className)
7523
+ referrerPolicy: "no-referrer",
7524
+ allow: PERMISSIONS_POLICY,
7525
+ className: cn("h-full w-full border-0", className),
7526
+ ...iframeProps
7465
7527
  }
7466
7528
  );
7467
7529
  }