@optilogic/core 1.2.0 → 1.2.2

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,82 @@ 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
+ "clipboard-read=()",
7466
+ "clipboard-write=()",
7467
+ "display-capture=()",
7468
+ "fullscreen=()",
7469
+ "autoplay=()",
7470
+ "web-share=()",
7471
+ "screen-wake-lock=()",
7472
+ "xr-spatial-tracking=()",
7473
+ "magnetometer=()",
7474
+ "gyroscope=()",
7475
+ "accelerometer=()"
7476
+ ].join(", ");
7477
+ function buildSandboxedHtml(content) {
7478
+ return `<!DOCTYPE html>
7479
+ <html>
7480
+ <head>
7481
+ <meta http-equiv="Content-Security-Policy" content="${CSP_POLICY}">
7482
+ <script>
7483
+ // Neutralise APIs that the sandbox + CSP can't fully block.
7484
+ // This runs in <head> before any user content in <body>.
7485
+ // Uses Object.defineProperty to make overrides non-configurable
7486
+ // so user scripts cannot restore the original via prototype tricks.
7487
+ (function(){
7488
+ // postMessage: iframe can message parent even without allow-same-origin.
7489
+ // Kill it so content can't probe or spam any future parent listeners.
7490
+ // Also kill parent/top refs as an extra layer.
7491
+ var noop = function(){};
7492
+ try { Object.defineProperty(window, 'postMessage', { value: noop, writable: false, configurable: false }); } catch(e) {}
7493
+ try { Object.defineProperty(window, 'parent', { value: window, writable: false, configurable: false }); } catch(e) {}
7494
+ try { Object.defineProperty(window, 'top', { value: window, writable: false, configurable: false }); } catch(e) {}
7495
+ try { Object.defineProperty(window, 'opener', { value: null, writable: false, configurable: false }); } catch(e) {}
7496
+
7497
+ // RTCPeerConnection: not governed by CSP; could contact a STUN server
7498
+ // over UDP to leak the user's IP. Kill all browser-prefixed variants.
7499
+ var rtcNames = ['RTCPeerConnection', 'webkitRTCPeerConnection', 'mozRTCPeerConnection'];
7500
+ for (var i = 0; i < rtcNames.length; i++) {
7501
+ try { Object.defineProperty(window, rtcNames[i], { value: undefined, writable: false, configurable: false }); } catch(e) {}
7502
+ }
7503
+ })();
7504
+ </script>
7505
+ </head>
7506
+ <body>${content}</body>
7507
+ </html>`;
7508
+ }
7453
7509
  function HtmlRenderer({
7454
7510
  content,
7455
7511
  fileName,
7456
7512
  className
7457
7513
  }) {
7514
+ const srcDoc = React20.useMemo(
7515
+ () => buildSandboxedHtml(content ?? ""),
7516
+ [content]
7517
+ );
7518
+ const iframeProps = { csp: CSP_POLICY };
7458
7519
  return /* @__PURE__ */ jsx(
7459
7520
  "iframe",
7460
7521
  {
7461
- srcDoc: content ?? "",
7522
+ srcDoc,
7462
7523
  sandbox: "allow-scripts",
7463
7524
  title: fileName,
7464
- className: cn("h-full w-full border-0", className)
7525
+ referrerPolicy: "no-referrer",
7526
+ allow: PERMISSIONS_POLICY,
7527
+ className: cn("h-full w-full border-0", className),
7528
+ ...iframeProps
7465
7529
  }
7466
7530
  );
7467
7531
  }