Skip to content

Commit b26cbb3

Browse files
committed
Update pagetual.user.js
1 parent 64a3ec2 commit b26cbb3

File tree

1 file changed

+83
-44
lines changed

1 file changed

+83
-44
lines changed

Pagetual/pagetual.user.js

Lines changed: 83 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4562,32 +4562,40 @@
45624562

45634563
function parseTrustedTypes(cspString) {
45644564
const policies = new Set();
4565+
let allowDuplicates = false;
4566+
let ttDirectiveFound = false;
45654567
const ttRegex = /trusted-types\s+([^;]+)/gi;
45664568
let match;
4569+
45674570
while ((match = ttRegex.exec(cspString)) !== null) {
4568-
match[1].trim().split(/\s+/)
4569-
.forEach(name => {
4570-
if (name !== "'allow-duplicates'" && name !== "'none'") {
4571-
policies.add(name.replace(/'/g, ''));
4572-
}
4573-
});
4574-
}
4575-
return Array.from(policies);
4576-
}
4571+
ttDirectiveFound = true;
45774572

4578-
async function getAvailablePolicyNamesOptimized() {
4579-
if (_unsafeWindow.trustedTypes && _unsafeWindow.trustedTypes.getPolicyNames) {
4580-
const existingNames = _unsafeWindow.trustedTypes.getPolicyNames();
4581-
if (existingNames.length > 0) {
4582-
return new Set(existingNames);
4573+
const policyNames = match[1].trim().split(/\s+/);
4574+
for (const name of policyNames) {
4575+
if (name === "'allow-duplicates'") {
4576+
allowDuplicates = true;
4577+
} else if (name !== "'none'") {
4578+
policies.add(name.replace(/'/g, ''));
4579+
}
45834580
}
45844581
}
4582+
return { names: policies, allowDuplicates: allowDuplicates, ttDirectiveFound: ttDirectiveFound };
4583+
}
4584+
4585+
async function getCspTrustedTypesInfo() {
4586+
const combinedPolicies = new Set();
4587+
let combinedAllowDuplicates = false;
4588+
let combinedTtDirectiveFound = false;
45854589

45864590
const meta = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
45874591
if (meta) {
4588-
const metaNames = parseTrustedTypes(meta.content);
4589-
if (metaNames.length > 0) {
4590-
return new Set(metaNames);
4592+
const metaResult = parseTrustedTypes(meta.content);
4593+
metaResult.names.forEach(name => combinedPolicies.add(name));
4594+
if (metaResult.allowDuplicates) {
4595+
combinedAllowDuplicates = true;
4596+
}
4597+
if (metaResult.ttDirectiveFound) {
4598+
combinedTtDirectiveFound = true;
45914599
}
45924600
}
45934601

@@ -4597,19 +4605,31 @@
45974605
url: window.location.href,
45984606
onload: function(response) {
45994607
const cspHeader = response.responseHeaders.split('\r\n')
4600-
.filter(h => h.toLowerCase().startsWith('content-security-policy:'))
4601-
.map(h => h.substring(26).trim())
4602-
.join('; ');
4608+
.filter(h => h.toLowerCase().startsWith('content-security-policy:'))
4609+
.map(h => h.substring(26).trim())
4610+
.join('; ');
46034611

4604-
const headerNames = parseTrustedTypes(cspHeader);
4605-
if (headerNames.length > 0) {
4606-
resolve(new Set(headerNames));
4607-
} else {
4608-
resolve(new Set());
4612+
const headerResult = parseTrustedTypes(cspHeader);
4613+
headerResult.names.forEach(name => combinedPolicies.add(name));
4614+
if (headerResult.allowDuplicates) {
4615+
combinedAllowDuplicates = true;
46094616
}
4617+
if (headerResult.ttDirectiveFound) {
4618+
combinedTtDirectiveFound = true;
4619+
}
4620+
4621+
resolve({
4622+
names: combinedPolicies,
4623+
allowDuplicates: combinedAllowDuplicates,
4624+
ttDirectiveFound: combinedTtDirectiveFound
4625+
});
46104626
},
46114627
onerror: function(error) {
4612-
resolve(new Set());
4628+
resolve({
4629+
names: combinedPolicies,
4630+
allowDuplicates: combinedAllowDuplicates,
4631+
ttDirectiveFound: combinedTtDirectiveFound
4632+
});
46134633
}
46144634
});
46154635
});
@@ -4625,29 +4645,48 @@
46254645
}
46264646

46274647
async function createPolicy() {
4628-
if (_unsafeWindow.trustedTypes && _unsafeWindow.trustedTypes.createPolicy && isTrustedTypesEnforced()) {
4629-
const allowedNames = await getAvailablePolicyNamesOptimized();
4648+
if (!(_unsafeWindow.trustedTypes && _unsafeWindow.trustedTypes.createPolicy && isTrustedTypesEnforced())) {
4649+
return;
4650+
}
46304651

4631-
if (allowedNames.size === 0) {
4632-
escapeHTMLPolicy = _unsafeWindow.trustedTypes.createPolicy('pagetual_default', {
4633-
createHTML: (string, sink) => string
4634-
});
4635-
return;
4652+
const { names: allowedNames, allowDuplicates, ttDirectiveFound } = await getCspTrustedTypesInfo();
4653+
4654+
if (ttDirectiveFound && !allowDuplicates) {
4655+
debug("CSP Trusted Types is enforced without 'allow-duplicates'. " +
4656+
"Skipping policy creation to avoid conflicts with the page.");
4657+
return;
4658+
}
4659+
4660+
const MY_POLICY_NAME = 'pvcep_default';
4661+
4662+
try {
4663+
escapeHTMLPolicy = _unsafeWindow.trustedTypes.createPolicy(MY_POLICY_NAME, {
4664+
createHTML: (string, sink) => string,
4665+
createScriptURL: string => string,
4666+
createScript: string => string
4667+
});
4668+
return;
4669+
} catch (e) {
4670+
}
4671+
4672+
const existingPolicies = new Set(_unsafeWindow.trustedTypes.getPolicyNames());
4673+
for (const name of allowedNames) {
4674+
if (name === '*' || existingPolicies.has(name)) {
4675+
continue;
46364676
}
46374677

4638-
for (const name of allowedNames) {
4639-
if (name === '*') continue;
4640-
try {
4641-
escapeHTMLPolicy = _unsafeWindow.trustedTypes.createPolicy(name, {
4642-
createHTML: (string, sink) => string
4643-
});
4644-
break;
4645-
} catch (e) {
4646-
console.warn(`create '${name}' failed`);
4647-
return;
4648-
}
4678+
try {
4679+
escapeHTMLPolicy = _unsafeWindow.trustedTypes.createPolicy(name, {
4680+
createHTML: (string, sink) => string,
4681+
createScriptURL: string => string,
4682+
createScript: string => string
4683+
});
4684+
return;
4685+
} catch (e) {
4686+
debug(`create '${name}' failed, trying next...`);
46494687
}
46504688
}
4689+
debug("Could not create any trusted types policy.");
46514690
}
46524691

46534692
let escapeHTMLPolicy = null;

0 commit comments

Comments
 (0)