@@ -12458,32 +12458,39 @@ ImgOps | https://imgops.com/#b#`;
1245812458
1245912459 function parseTrustedTypes(cspString) {
1246012460 const policies = new Set();
12461+ let allowDuplicates = false;
12462+ let ttDirectiveFound = false;
1246112463 const ttRegex = /trusted-types\s+([^;]+)/gi;
1246212464 let match;
12465+
1246312466 while ((match = ttRegex.exec(cspString)) !== null) {
12467+ ttDirectiveFound = true;
1246412468 match[1].trim().split(/\s+/)
1246512469 .forEach(name => {
12466- if (name !== "'allow-duplicates'" && name !== "'none'") {
12467- policies.add(name.replace(/'/g, ''));
12468- }
12469- });
12470+ if (name === "'allow-duplicates'") {
12471+ allowDuplicates = true;
12472+ } else if (name !== "'none'") {
12473+ policies.add(name.replace(/'/g, ''));
12474+ }
12475+ });
1247012476 }
12471- return Array.from( policies) ;
12477+ return { names: policies, allowDuplicates: allowDuplicates, ttDirectiveFound: ttDirectiveFound } ;
1247212478 }
1247312479
12474- async function getAvailablePolicyNamesOptimized() {
12475- if (unsafeWindow.trustedTypes && unsafeWindow.trustedTypes.getPolicyNames) {
12476- const existingNames = unsafeWindow.trustedTypes.getPolicyNames();
12477- if (existingNames.length > 0) {
12478- return new Set(existingNames);
12479- }
12480- }
12480+ async function getCspTrustedTypesInfo() {
12481+ const combinedPolicies = new Set();
12482+ let combinedAllowDuplicates = false;
12483+ let combinedTtDirectiveFound = false;
1248112484
1248212485 const meta = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
1248312486 if (meta) {
12484- const metaNames = parseTrustedTypes(meta.content);
12485- if (metaNames.length > 0) {
12486- return new Set(metaNames);
12487+ const metaResult = parseTrustedTypes(meta.content);
12488+ metaResult.names.forEach(name => combinedPolicies.add(name));
12489+ if (metaResult.allowDuplicates) {
12490+ combinedAllowDuplicates = true;
12491+ }
12492+ if (metaResult.ttDirectiveFound) {
12493+ combinedTtDirectiveFound = true;
1248712494 }
1248812495 }
1248912496
@@ -12493,19 +12500,31 @@ ImgOps | https://imgops.com/#b#`;
1249312500 url: window.location.href,
1249412501 onload: function(response) {
1249512502 const cspHeader = response.responseHeaders.split('\r\n')
12496- .filter(h => h.toLowerCase().startsWith('content-security-policy:'))
12497- .map(h => h.substring(26).trim())
12498- .join('; ');
12499-
12500- const headerNames = parseTrustedTypes(cspHeader);
12501- if (headerNames.length > 0) {
12502- resolve(new Set(headerNames));
12503- } else {
12504- resolve(new Set());
12503+ .filter(h => h.toLowerCase().startsWith('content-security-policy:'))
12504+ .map(h => h.substring(26).trim())
12505+ .join('; ');
12506+
12507+ const headerResult = parseTrustedTypes(cspHeader);
12508+ headerResult.names.forEach(name => combinedPolicies.add(name));
12509+ if (headerResult.allowDuplicates) {
12510+ combinedAllowDuplicates = true;
1250512511 }
12512+ if (headerResult.ttDirectiveFound) {
12513+ combinedTtDirectiveFound = true;
12514+ }
12515+
12516+ resolve({
12517+ names: combinedPolicies,
12518+ allowDuplicates: combinedAllowDuplicates,
12519+ ttDirectiveFound: combinedTtDirectiveFound
12520+ });
1250612521 },
1250712522 onerror: function(error) {
12508- resolve(new Set());
12523+ resolve({
12524+ names: combinedPolicies,
12525+ allowDuplicates: combinedAllowDuplicates,
12526+ ttDirectiveFound: combinedTtDirectiveFound
12527+ });
1250912528 }
1251012529 });
1251112530 });
@@ -12521,33 +12540,48 @@ ImgOps | https://imgops.com/#b#`;
1252112540 }
1252212541
1252312542 async function createPolicy() {
12524- if (unsafeWindow.trustedTypes && unsafeWindow.trustedTypes.createPolicy && isTrustedTypesEnforced()) {
12525- const allowedNames = await getAvailablePolicyNamesOptimized();
12543+ if (!(unsafeWindow.trustedTypes && unsafeWindow.trustedTypes.createPolicy && isTrustedTypesEnforced())) {
12544+ return;
12545+ }
12546+
12547+ const { names: allowedNames, allowDuplicates, ttDirectiveFound } = await getCspTrustedTypesInfo();
12548+
12549+ if (ttDirectiveFound && !allowDuplicates) {
12550+ debug("CSP Trusted Types is enforced without 'allow-duplicates'. " +
12551+ "Skipping policy creation to avoid conflicts with the page.");
12552+ return;
12553+ }
1252612554
12527- if (allowedNames.size === 0) {
12528- escapeHTMLPolicy = unsafeWindow.trustedTypes.createPolicy('pvcep_default', {
12555+ const MY_POLICY_NAME = 'pvcep_default';
12556+
12557+ try {
12558+ escapeHTMLPolicy = unsafeWindow.trustedTypes.createPolicy(MY_POLICY_NAME, {
12559+ createHTML: (string, sink) => string,
12560+ createScriptURL: string => string,
12561+ createScript: string => string
12562+ });
12563+ return;
12564+ } catch (e) {
12565+ }
12566+
12567+ const existingPolicies = new Set(unsafeWindow.trustedTypes.getPolicyNames());
12568+ for (const name of allowedNames) {
12569+ if (name === '*' || existingPolicies.has(name)) {
12570+ continue;
12571+ }
12572+
12573+ try {
12574+ escapeHTMLPolicy = unsafeWindow.trustedTypes.createPolicy(name, {
1252912575 createHTML: (string, sink) => string,
1253012576 createScriptURL: string => string,
1253112577 createScript: string => string
1253212578 });
1253312579 return;
12534- }
12535-
12536- for (const name of allowedNames) {
12537- if (name === '*') continue;
12538- try {
12539- escapeHTMLPolicy = unsafeWindow.trustedTypes.createPolicy(name, {
12540- createHTML: (string, sink) => string,
12541- createScriptURL: string => string,
12542- createScript: string => string
12543- });
12544- break;
12545- } catch (e) {
12546- console.warn(`create '${name}' failed`);
12547- return;
12548- }
12580+ } catch (e) {
12581+ debug(`create '${name}' failed, trying next...`);
1254912582 }
1255012583 }
12584+ debug("Could not create any trusted types policy.");
1255112585 }
1255212586
1255312587 let escapeHTMLPolicy = null;
0 commit comments