From b0c454ef7528b49cd2a28a15a022b7dfdfb60649 Mon Sep 17 00:00:00 2001 From: Mario Heiderich Date: Mon, 22 Jun 2026 11:04:57 +0200 Subject: [PATCH] release: 0.3.0 --- dist/fortify.cjs.js | 4 ++-- dist/fortify.es.mjs | 4 ++-- dist/fortify.js | 4 ++-- dist/fortify.min.js | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/dist/fortify.cjs.js b/dist/fortify.cjs.js index 2b75bdc..1566be7 100644 --- a/dist/fortify.cjs.js +++ b/dist/fortify.cjs.js @@ -1,4 +1,4 @@ -/*! DOMFortify 0.2.0 | (c) Cure53 and contributors | (MPL-2.0 OR Apache-2.0) */ +/*! DOMFortify 0.3.0 | (c) Cure53 and contributors | (MPL-2.0 OR Apache-2.0) */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); @@ -82,7 +82,7 @@ function urlMatches(pattern, url) { * - Fails closed: no sanitizer means sinks throw, never leak. * - Only covers Trusted Types sinks; inline handlers / style / URL props stay open. */ -const VERSION = '0.2.0'; +const VERSION = '0.3.0'; // Natives captured up front, so later prototype pollution or clobbering can't swap them out. const root = typeof globalThis !== 'undefined' ? globalThis : window; const doc = typeof document !== 'undefined' ? document : undefined; diff --git a/dist/fortify.es.mjs b/dist/fortify.es.mjs index 2b58836..60b7b8f 100644 --- a/dist/fortify.es.mjs +++ b/dist/fortify.es.mjs @@ -1,4 +1,4 @@ -/*! DOMFortify 0.2.0 | (c) Cure53 and contributors | (MPL-2.0 OR Apache-2.0) */ +/*! DOMFortify 0.3.0 | (c) Cure53 and contributors | (MPL-2.0 OR Apache-2.0) */ // Cached up front so later prototype pollution or clobbering can't swap hasOwnProperty out. const hasOwn = Object.prototype.hasOwnProperty; /** True only for an own (non-inherited) property, so a polluted prototype is never consulted. */ @@ -78,7 +78,7 @@ function urlMatches(pattern, url) { * - Fails closed: no sanitizer means sinks throw, never leak. * - Only covers Trusted Types sinks; inline handlers / style / URL props stay open. */ -const VERSION = '0.2.0'; +const VERSION = '0.3.0'; // Natives captured up front, so later prototype pollution or clobbering can't swap them out. const root = typeof globalThis !== 'undefined' ? globalThis : window; const doc = typeof document !== 'undefined' ? document : undefined; diff --git a/dist/fortify.js b/dist/fortify.js index fa1cf6d..88d6adb 100644 --- a/dist/fortify.js +++ b/dist/fortify.js @@ -1,4 +1,4 @@ -/*! DOMFortify 0.2.0 | (c) Cure53 and contributors | (MPL-2.0 OR Apache-2.0) */ +/*! DOMFortify 0.3.0 | (c) Cure53 and contributors | (MPL-2.0 OR Apache-2.0) */ (function () { 'use strict'; @@ -81,7 +81,7 @@ * - Fails closed: no sanitizer means sinks throw, never leak. * - Only covers Trusted Types sinks; inline handlers / style / URL props stay open. */ - const VERSION = '0.2.0'; + const VERSION = '0.3.0'; // Natives captured up front, so later prototype pollution or clobbering can't swap them out. const root = typeof globalThis !== 'undefined' ? globalThis : window; const doc = typeof document !== 'undefined' ? document : undefined; diff --git a/dist/fortify.min.js b/dist/fortify.min.js index 918a571..d0f8ead 100644 --- a/dist/fortify.min.js +++ b/dist/fortify.min.js @@ -1,3 +1,3 @@ -/*! DOMFortify 0.2.0 | (c) Cure53 and contributors | (MPL-2.0 OR Apache-2.0) */ -!function(){"use strict";const t=Object.prototype.hasOwnProperty;function e(e,r){return null!=e&&t.call(e,r)}function r(t,r){return e(t,r)?t[r]:void 0}function n(t){return String(t).slice(0,80)}function i(t){try{return String(t?.message)}catch{return"unknown error"}}function o(t,e){if(null==t)return!1;const r=Array.isArray(t)?t:[t];for(let t=0;t{if(!r)return n("sanitizer-unavailable",{sink:"createHTML"}),null;if(o)return c;try{return o=!0,t.sanitize(c,e)}catch(t){return n("sanitize-threw",{error:i(t)}),null}finally{o=!1}}}function p(t,e,r){return o=>{if(e){let n;try{n=e(o)}catch(e){return r("script-hook-threw",{sink:t,error:i(e)}),null}if("string"==typeof n)return r("script-sink-allowed",{sink:t}),n}return r("script-sink-refused",{sink:t,sample:n(o)}),null}}const h=Object.freeze({init:function(n={}){if(f)return s;f=!0;const h=r(n,"ON_VIOLATION"),O="function"==typeof h?(t,e)=>{try{h(t,e)}catch{}}:()=>{},m={version:"0.2.0",ttSupported:!!l,enforcementActive:!1,defaultPolicyOwned:!1,sanitizerReady:!1,excluded:!1,metaInjected:!1,protected:!1,reason:""},v=(t,e)=>(m.protected=m.defaultPolicyOwned&&m.enforcementActive&&m.sanitizerReady,m.reason=t,s=Object.freeze({...m}),e&&O(e,s),s);try{const f=a&&void 0!==a.href?String(a.href):"";if(o(r(n,"EXCLUDE"),f))return m.excluded=!0,v("URL matched EXCLUDE; DOMFortify is intentionally inactive on this page.","excluded-by-url");if(!l||"function"!=typeof l.createPolicy)return v("Trusted Types not supported; library is inert. Sinks are NOT routed.","tt-unsupported");const s=function(t,e){const n=r(t,"URL_CONFIG");if(!Array.isArray(n))return null;for(let t=0;ts&&e(s,t)?s[t]:r(n,t);if(!0===r(n,"INJECT_META")){const t=(T=r(n,"META_DIRECTIVE"),w="function"==typeof h("SANITIZER"),"string"==typeof T&&T?T:`require-trusted-types-for 'script'; trusted-types ${w?"default":"default dompurify"};`);m.metaInjected=function(t){if(!u)return!1;const e=u,r='\r\n]/g,"")+'">';if("loading"===e.readyState&&"function"==typeof e.write)try{return e.write(r),!0}catch{}try{const r=e.createElement("meta");r.setAttribute("http-equiv","Content-Security-Policy"),r.setAttribute("content",t),(e.head||e.documentElement).appendChild(r)}catch{}return!1}(t),O("meta-injection-attempted",{directive:t,written:m.metaInjected})}m.enforcementActive=function(){try{return u.createElement("div").innerHTML="x",!1}catch{return!0}}();let g=h("SANITIZER");void 0===g&&(g=c.DOMPurify);const b=d(g),A=h("SANITIZER_CONFIG"),I=A&&"object"==typeof A?function(e){const r={};for(const n in e)t.call(e,n)&&"__proto__"!==n&&"constructor"!==n&&"prototype"!==n&&(r[n]=e[n]);return r}(A):void 0,L=h("ALLOW_SCRIPT"),k=h("ALLOW_SCRIPT_URL"),E="function"==typeof L?L:null,P="function"==typeof k?k:null;let R=!1;if(b){const t=function(t,e){try{return"string"==typeof t.sanitize("x",e)?{ready:!0,error:null}:{ready:!1,error:"sanitize() did not return a string"}}catch(t){return{ready:!1,error:i(t)}}}(b,I);R=t.ready,t.ready||O("sanitizer-smoketest-failed",{error:t.error})}m.sanitizerReady=R;const S={createHTML:y(b,I,R,O),createScript:p("createScript",E,O),createScriptURL:p("createScriptURL",P,O)};if(l.defaultPolicy)return v("A default Trusted Types policy already exists; DOMFortify did NOT install and cannot vouch for it. Load DOMFortify first, inline in .","preexisting-default-policy");let z;try{z=l.createPolicy("default",S)}catch(t){return v(`createPolicy("default") threw (${i(t)}); another default policy won the race.`,"default-policy-lost")}return l.defaultPolicy&&l.defaultPolicy!==z?v('Our policy was created but is not the active default (allow-duplicates race lost). Remove "allow-duplicates" from the trusted-types directive.',"default-policy-not-active"):(m.defaultPolicyOwned=!0,m.enforcementActive?R?v(`Active: HTML sinks sanitized, script sinks ${E||P?"partly allowed by hooks":"refused"}.`):v("Enforcement active and slot locked, but the sanitizer is unavailable - HTML sinks will THROW (failing closed). Bundle DOMPurify and load it before DOMFortify.","failing-closed"):v("Default policy installed and slot locked, but TT enforcement is NOT active - sinks are not routed. Deliver require-trusted-types-for (header preferred).","enforcement-inactive"))}catch(t){return v(`init() hit an unexpected error (${i(t)}); failing closed.`,"failing-closed")}var T,w},status:function(){return s}});"undefined"!=typeof window&&(window.DOMFortify=h,h.init(window.DOMFortifyConfig||{}))}(); +/*! DOMFortify 0.3.0 | (c) Cure53 and contributors | (MPL-2.0 OR Apache-2.0) */ +!function(){"use strict";const t=Object.prototype.hasOwnProperty;function e(e,r){return null!=e&&t.call(e,r)}function r(t,r){return e(t,r)?t[r]:void 0}function n(t){return String(t).slice(0,80)}function i(t){try{return String(t?.message)}catch{return"unknown error"}}function o(t,e){if(null==t)return!1;const r=Array.isArray(t)?t:[t];for(let t=0;t{if(!r)return n("sanitizer-unavailable",{sink:"createHTML"}),null;if(o)return c;try{return o=!0,t.sanitize(c,e)}catch(t){return n("sanitize-threw",{error:i(t)}),null}finally{o=!1}}}function p(t,e,r){return o=>{if(e){let n;try{n=e(o)}catch(e){return r("script-hook-threw",{sink:t,error:i(e)}),null}if("string"==typeof n)return r("script-sink-allowed",{sink:t}),n}return r("script-sink-refused",{sink:t,sample:n(o)}),null}}const h=Object.freeze({init:function(n={}){if(f)return s;f=!0;const h=r(n,"ON_VIOLATION"),O="function"==typeof h?(t,e)=>{try{h(t,e)}catch{}}:()=>{},m={version:"0.3.0",ttSupported:!!l,enforcementActive:!1,defaultPolicyOwned:!1,sanitizerReady:!1,excluded:!1,metaInjected:!1,protected:!1,reason:""},v=(t,e)=>(m.protected=m.defaultPolicyOwned&&m.enforcementActive&&m.sanitizerReady,m.reason=t,s=Object.freeze({...m}),e&&O(e,s),s);try{const f=a&&void 0!==a.href?String(a.href):"";if(o(r(n,"EXCLUDE"),f))return m.excluded=!0,v("URL matched EXCLUDE; DOMFortify is intentionally inactive on this page.","excluded-by-url");if(!l||"function"!=typeof l.createPolicy)return v("Trusted Types not supported; library is inert. Sinks are NOT routed.","tt-unsupported");const s=function(t,e){const n=r(t,"URL_CONFIG");if(!Array.isArray(n))return null;for(let t=0;ts&&e(s,t)?s[t]:r(n,t);if(!0===r(n,"INJECT_META")){const t=(T=r(n,"META_DIRECTIVE"),w="function"==typeof h("SANITIZER"),"string"==typeof T&&T?T:`require-trusted-types-for 'script'; trusted-types ${w?"default":"default dompurify"};`);m.metaInjected=function(t){if(!u)return!1;const e=u,r='\r\n]/g,"")+'">';if("loading"===e.readyState&&"function"==typeof e.write)try{return e.write(r),!0}catch{}try{const r=e.createElement("meta");r.setAttribute("http-equiv","Content-Security-Policy"),r.setAttribute("content",t),(e.head||e.documentElement).appendChild(r)}catch{}return!1}(t),O("meta-injection-attempted",{directive:t,written:m.metaInjected})}m.enforcementActive=function(){try{return u.createElement("div").innerHTML="x",!1}catch{return!0}}();let g=h("SANITIZER");void 0===g&&(g=c.DOMPurify);const b=d(g),A=h("SANITIZER_CONFIG"),I=A&&"object"==typeof A?function(e){const r={};for(const n in e)t.call(e,n)&&"__proto__"!==n&&"constructor"!==n&&"prototype"!==n&&(r[n]=e[n]);return r}(A):void 0,L=h("ALLOW_SCRIPT"),k=h("ALLOW_SCRIPT_URL"),E="function"==typeof L?L:null,P="function"==typeof k?k:null;let R=!1;if(b){const t=function(t,e){try{return"string"==typeof t.sanitize("x",e)?{ready:!0,error:null}:{ready:!1,error:"sanitize() did not return a string"}}catch(t){return{ready:!1,error:i(t)}}}(b,I);R=t.ready,t.ready||O("sanitizer-smoketest-failed",{error:t.error})}m.sanitizerReady=R;const S={createHTML:y(b,I,R,O),createScript:p("createScript",E,O),createScriptURL:p("createScriptURL",P,O)};if(l.defaultPolicy)return v("A default Trusted Types policy already exists; DOMFortify did NOT install and cannot vouch for it. Load DOMFortify first, inline in .","preexisting-default-policy");let z;try{z=l.createPolicy("default",S)}catch(t){return v(`createPolicy("default") threw (${i(t)}); another default policy won the race.`,"default-policy-lost")}return l.defaultPolicy&&l.defaultPolicy!==z?v('Our policy was created but is not the active default (allow-duplicates race lost). Remove "allow-duplicates" from the trusted-types directive.',"default-policy-not-active"):(m.defaultPolicyOwned=!0,m.enforcementActive?R?v(`Active: HTML sinks sanitized, script sinks ${E||P?"partly allowed by hooks":"refused"}.`):v("Enforcement active and slot locked, but the sanitizer is unavailable - HTML sinks will THROW (failing closed). Bundle DOMPurify and load it before DOMFortify.","failing-closed"):v("Default policy installed and slot locked, but TT enforcement is NOT active - sinks are not routed. Deliver require-trusted-types-for (header preferred).","enforcement-inactive"))}catch(t){return v(`init() hit an unexpected error (${i(t)}); failing closed.`,"failing-closed")}var T,w},status:function(){return s}});"undefined"!=typeof window&&(window.DOMFortify=h,h.init(window.DOMFortifyConfig||{}))}(); //# sourceMappingURL=fortify.min.js.map diff --git a/package-lock.json b/package-lock.json index 33c3203..3cacbb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "domfortify", - "version": "0.2.0", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "domfortify", - "version": "0.2.0", + "version": "0.3.0", "license": "(MPL-2.0 OR Apache-2.0)", "devDependencies": { "@playwright/test": "^1.49.0", diff --git a/package.json b/package.json index 2128d38..b5d1408 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "domfortify", - "version": "0.2.0", + "version": "0.3.0", "description": "Retrofit Trusted Types onto a legacy page: claim the realm's default policy so old DOM-XSS sinks get sanitized without touching the code.", "license": "(MPL-2.0 OR Apache-2.0)", "homepage": "https://github.com/cure53/DOMFortify",