Skip to content

Commit

Permalink
[mv3] Properly distinguish trust level when compiling scriptlets
Browse files Browse the repository at this point in the history
Since in uBOL filter lists from various sources are combined into
a single list, there must be a way to turn on/off trust level
inside the resulting combined filter list so as to be able to
validate the trust level of filters requiring trust.

This commit adds new parser directives understood only by MV3
compiler to turn on/off trust flag internally.
  • Loading branch information
gorhill committed Jun 23, 2023
1 parent ea4afc0 commit 7ba8547
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 6 deletions.
18 changes: 14 additions & 4 deletions platform/mv3/make-rulesets.js
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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',
Expand All @@ -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
Expand Down Expand Up @@ -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',
Expand All @@ -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',
Expand Down
4 changes: 2 additions & 2 deletions platform/mv3/make-scriptlets.js
Expand Up @@ -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';
}
Expand All @@ -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;
}
Expand Down
12 changes: 12 additions & 0 deletions src/js/static-dnr-filtering.js
Expand Up @@ -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 ) {
Expand Down Expand Up @@ -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; }

Expand Down

0 comments on commit 7ba8547

Please sign in to comment.