diff --git a/platform/mv3/make-rulesets.js b/platform/mv3/make-rulesets.js index 7f603d9d8..611d80245 100644 --- a/platform/mv3/make-rulesets.js +++ b/platform/mv3/make-rulesets.js @@ -27,7 +27,7 @@ import fs from 'fs/promises'; import https from 'https'; import path from 'path'; import process from 'process'; -import { createHash } from 'crypto'; +import { createHash, randomBytes } from 'crypto'; import redirectResourcesMap from './js/redirect-resources.js'; import { dnrRulesetFromRawLists } from './js/static-dnr-filtering.js'; import * as sfp from './js/static-filtering-parser.js'; @@ -182,6 +182,9 @@ async function fetchAsset(assetDetails) { continue; } fetchedURLs.add(part.url); + if ( part.url.startsWith('https://ublockorigin.github.io/uAssets/filters/') ) { + newParts.push(`!#trusted on ${assetDetails.secret}`); + } newParts.push( fetchList(part.url, cacheDir).then(details => { const { url } = details; @@ -198,6 +201,7 @@ async function fetchAsset(assetDetails) { return { url, content: '' }; }) ); + newParts.push(`!#trusted off ${assetDetails.secret}`); } parts = await Promise.all(newParts); parts = sfp.utils.preparser.expandIncludes(parts, env); @@ -808,7 +812,7 @@ async function processScriptletFilters(assetDetails, mapin) { makeScriptlet.init(); for ( const details of mapin.values() ) { - makeScriptlet.compile(details, assetDetails.isTrusted); + makeScriptlet.compile(details); } const stats = await makeScriptlet.commit( assetDetails.id, @@ -851,7 +855,7 @@ async function rulesetFromURLs(assetDetails) { const results = await dnrRulesetFromRawLists( [ { name: assetDetails.id, text: assetDetails.text } ], - { env, extensionPaths } + { env, extensionPaths, secret: assetDetails.secret } ); const netStats = await processNetworkFilters( @@ -975,6 +979,10 @@ async function main() { JSON.parse(text) ); + // This will be used to sign our inserted `!#trusted on` directives + const secret = createHash('sha256').update(randomBytes(16)).digest('hex').slice(0,16); + log(`Secret: ${secret}`); + // Assemble all default lists as the default ruleset const contentURLs = [ 'https://ublockorigin.github.io/uAssets/filters/filters.min.txt', @@ -991,9 +999,9 @@ async function main() { id: 'default', name: 'Ads, trackers, miners, and more' , enabled: true, + secret, urls: contentURLs, homeURL: 'https://github.com/uBlockOrigin/uAssets', - isTrusted: true, }); // Regional rulesets @@ -1063,6 +1071,7 @@ async function main() { name: 'EasyList/uBO – Cookie Notices', group: 'annoyances', enabled: false, + secret, urls: [ 'https://ublockorigin.github.io/uAssets/thirdparties/easylist-cookies.txt', 'https://ublockorigin.github.io/uAssets/filters/annoyances-cookies.txt', @@ -1074,6 +1083,7 @@ async function main() { name: 'AdGuard/uBO – Overlays', group: 'annoyances', enabled: false, + secret, urls: [ 'https://filters.adtidy.org/extension/ublock/filters/19.txt', 'https://ublockorigin.github.io/uAssets/filters/annoyances-others.txt', diff --git a/platform/mv3/make-scriptlets.js b/platform/mv3/make-scriptlets.js index 7dfeb89b6..63cf9f27f 100644 --- a/platform/mv3/make-scriptlets.js +++ b/platform/mv3/make-scriptlets.js @@ -78,7 +78,7 @@ export function reset() { /******************************************************************************/ -export function compile(details, isTrusted) { +export function compile(details) { if ( details.args[0].endsWith('.js') === false ) { details.args[0] += '.js'; } @@ -88,7 +88,7 @@ export function compile(details, isTrusted) { const scriptletToken = details.args[0]; const resourceEntry = resourceDetails.get(scriptletToken); if ( resourceEntry === undefined ) { return; } - if ( resourceEntry.requiresTrust && isTrusted !== true ) { + if ( resourceEntry.requiresTrust && details.isTrusted !== true ) { console.log(`Rejecting ${scriptletToken}: source is not trusted`); return; } diff --git a/src/js/static-dnr-filtering.js b/src/js/static-dnr-filtering.js index 27194c6dc..2ccd2249f 100644 --- a/src/js/static-dnr-filtering.js +++ b/src/js/static-dnr-filtering.js @@ -122,6 +122,9 @@ function addExtendedToDNR(context, parser) { let details = context.scriptletFilters.get(argsToken); if ( details === undefined ) { context.scriptletFilters.set(argsToken, details = { args }); + if ( context.isTrusted ) { + details.isTrusted = true; + } } if ( not ) { if ( details.excludeMatches === undefined ) { @@ -247,6 +250,15 @@ function addToDNR(context, list) { parser.parse(line); + if ( parser.isComment() ) { + if ( line === `!#trusted on ${context.secret}` ) { + context.isTrusted = true; + } else if ( line === `!#trusted off ${context.secret}` ) { + context.isTrusted = false; + } + continue; + } + if ( parser.isFilter() === false ) { continue; } if ( parser.hasError() ) { continue; }