Skip to content

Commit a63cf7d

Browse files
Add stack trace check to cookie protection (#349)
* Add stack trace check to cookie protection * Reinstate tracker expiry policy * Move tracker lookup out of cookiePolicy to save the effort of copying * Move args to class props * Clean up access of featureSettings * Add disclosure to code * Simplify passing of config keys * Move over tracker generation from the extension * Use import.meta.trackerLookup everywhere instead of json import * Add parsing of bundledConfig and made args private * Support file writing output of bundledTrackers * Handle updating the policy for non extension environments
1 parent be0b5f9 commit a63cf7d

23 files changed

+356
-114
lines changed

.eslintrc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
"$USER_PREFERENCES$": "readonly",
1212
"$USER_UNPROTECTED_DOMAINS$": "readonly",
1313
"$CONTENT_SCOPE$": "readonly",
14-
"$TRACKER_LOOKUP$": "readonly",
1514
"$BUNDLED_CONFIG$": "readonly",
1615
"windowsInteropPostMessage": "readonly",
1716
"windowsInteropAddEventListener": "readonly",

inject/android.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
import { load, init, update } from '../src/content-scope-features.js'
66
import { processConfig, isGloballyDisabled } from './../src/utils'
7+
import { isTrackerOrigin } from '../src/trackers'
78

89
const allowedMessages = [
910
'getClickToLoadState',
@@ -22,7 +23,9 @@ function initCode () {
2223
}
2324

2425
load({
25-
platform: processedConfig.platform
26+
platform: processedConfig.platform,
27+
trackerLookup: processedConfig.trackerLookup,
28+
documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup)
2629
})
2730

2831
const messageSecret = processedConfig.messageSecret

inject/apple.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
import { load, init } from '../src/content-scope-features.js'
66
import { processConfig, isGloballyDisabled } from './../src/utils'
7+
import { isTrackerOrigin } from '../src/trackers'
78

89
function initCode () {
910
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
@@ -13,7 +14,9 @@ function initCode () {
1314
}
1415

1516
load({
16-
platform: processedConfig.platform
17+
platform: processedConfig.platform,
18+
trackerLookup: processedConfig.trackerLookup,
19+
documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup)
1720
})
1821

1922
init(processedConfig)

inject/chrome-mv3.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import { isTrackerOrigin } from '../src/trackers'
77

88
const secret = (crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32).toString().replace('0.', '')
99

10+
const trackerLookup = import.meta.trackerLookup
11+
1012
load({
1113
platform: {
1214
name: 'extension'
1315
},
14-
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
15-
documentOriginIsTracker: isTrackerOrigin($TRACKER_LOOKUP$),
16+
trackerLookup,
17+
documentOriginIsTracker: isTrackerOrigin(trackerLookup),
1618
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
1719
bundledConfig: $BUNDLED_CONFIG$
1820
})

inject/chrome.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ function randomString () {
3838
}
3939

4040
function init () {
41-
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
42-
const documentOriginIsTracker = isTrackerOrigin($TRACKER_LOOKUP$)
41+
const trackerLookup = import.meta.trackerLookup
42+
const documentOriginIsTracker = isTrackerOrigin(trackerLookup)
4343
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
4444
const bundledConfig = $BUNDLED_CONFIG$
4545
const randomMethodName = '_d' + randomString()
@@ -52,6 +52,7 @@ function init () {
5252
platform: {
5353
name: 'extension'
5454
},
55+
trackerLookup: ${JSON.stringify(trackerLookup)},
5556
documentOriginIsTracker: ${documentOriginIsTracker},
5657
bundledConfig: ${JSON.stringify(bundledConfig)}
5758
})

inject/integration.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { load, init } from '../src/content-scope-features.js'
2+
import { isTrackerOrigin } from '../src/trackers'
23
function getTopLevelURL () {
34
try {
45
// FROM: https://stackoverflow.com/a/7739035/73479
@@ -15,6 +16,7 @@ function getTopLevelURL () {
1516

1617
function generateConfig (data, userList) {
1718
const topLevelUrl = getTopLevelURL()
19+
const trackerLookup = import.meta.trackerLookup
1820
return {
1921
debug: false,
2022
sessionKey: 'randomVal',
@@ -30,7 +32,8 @@ function generateConfig (data, userList) {
3032
'fingerprintingScreenSize',
3133
'navigatorInterface'
3234
]
33-
}
35+
},
36+
trackerLookup
3437
}
3538
}
3639

@@ -71,7 +74,9 @@ async function initCode () {
7174
const processedConfig = generateConfig()
7275

7376
load({
74-
platform: processedConfig.platform
77+
platform: processedConfig.platform,
78+
trackerLookup: processedConfig.trackerLookup,
79+
documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup)
7580
})
7681

7782
// mark this phase as loaded

inject/mozilla.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ function randomString () {
2121
}
2222

2323
function initCode () {
24+
const trackerLookup = import.meta.trackerLookup
2425
load({
2526
platform: {
2627
name: 'extension'
2728
},
28-
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
29-
documentOriginIsTracker: isTrackerOrigin($TRACKER_LOOKUP$),
29+
trackerLookup,
30+
documentOriginIsTracker: isTrackerOrigin(trackerLookup),
3031
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
3132
bundledConfig: $BUNDLED_CONFIG$
3233
})

inject/windows.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
import { load, init } from '../src/content-scope-features.js'
66
import { processConfig, isGloballyDisabled, windowsSpecificFeatures } from './../src/utils'
7+
import { isTrackerOrigin } from '../src/trackers'
78

89
function initCode () {
910
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
@@ -13,7 +14,9 @@ function initCode () {
1314
}
1415

1516
load({
16-
platform: processedConfig.platform
17+
platform: processedConfig.platform,
18+
trackerLookup: processedConfig.trackerLookup,
19+
documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup)
1720
})
1821

1922
init(processedConfig)

integration-test/test-pages.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('Test integration pages', () => {
2121
await teardown()
2222
})
2323

24-
it('Script that should not execute', async () => {
24+
it('Should be successful page script check', async () => {
2525
const pages = {
2626
'runtime-checks/pages/basic-run.html': 'runtime-checks/config/basic-run.json',
2727
'runtime-checks/pages/filter-props.html': 'runtime-checks/config/filter-props.json',

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"postinstall": "npm run copy-sjcl",
1111
"copy-sjcl": "node scripts/generateSJCL.js",
1212
"bundle-config": "node scripts/bundleConfig.mjs",
13-
"build": "npm run build-locales && npm run build-firefox && npm run build-chrome && npm run build-apple && npm run build-android && npm run build-windows && npm run build-integration && npm run build-chrome-mv3",
13+
"build": "npm run build-locales && npm run bundle-trackers && npm run build-firefox && npm run build-chrome && npm run build-apple && npm run build-android && npm run build-windows && npm run build-integration && npm run build-chrome-mv3",
1414
"build-locales": "node scripts/buildLocales.js --dir src/locales/click-to-load --output build/locales/ctl-locales.js",
1515
"build-firefox": "node scripts/inject.js --platform firefox",
1616
"build-chrome": "node scripts/inject.js --platform chrome",
@@ -19,6 +19,7 @@
1919
"build-android": "node scripts/inject.js --platform android",
2020
"build-windows": "node scripts/inject.js --platform windows",
2121
"build-integration": "node scripts/inject.js --platform integration",
22+
"bundle-trackers": "node scripts/bundleTrackers.mjs --output build/tracker-lookup.json",
2223
"docs": "typedoc",
2324
"docs-watch": "typedoc --watch",
2425
"postbuild": "npm run build --workspaces --if-present",

scripts/bundleTrackers.mjs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import fetch from 'node-fetch'
2+
import { writeFileSync } from 'fs'
3+
import { parseArgs, write } from './script-utils.js'
4+
5+
const tdsUrl = 'https://staticcdn.duckduckgo.com/trackerblocking/v4/tds.json'
6+
const resp = await fetch(tdsUrl)
7+
const tds = await resp.json()
8+
9+
// Build a trie of tracker domains, starting with the broadest subdomain. Leaves are set to 1 to indicate success
10+
// i.e. lookup['com']['example'] === 1 if example.com is a tracker domain
11+
const trackerLookupTrie = {}
12+
function insert (domainParts, node) {
13+
if (domainParts.length === 1) {
14+
node[domainParts[0]] = 1
15+
} else if (node[domainParts[0]]) {
16+
insert(domainParts.slice(1), node[domainParts[0]])
17+
} else {
18+
node[domainParts[0]] = {}
19+
insert(domainParts.slice(1), node[domainParts[0]])
20+
}
21+
}
22+
Object.keys(tds.trackers).forEach((tracker) => {
23+
insert(tracker.split('.').reverse(), trackerLookupTrie)
24+
})
25+
26+
const outputString = JSON.stringify(trackerLookupTrie)
27+
const args = parseArgs(process.argv.slice(2), [])
28+
if (args.output) {
29+
write([args.output], outputString)
30+
} else {
31+
// Used by the extension code
32+
console.log(outputString)
33+
}

scripts/generateSJCL.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
2-
import fs from 'fs/promises'
1+
import { readFile, writeFile } from 'fs/promises'
32
import { existsSync } from 'fs'
43
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
54
import util from 'util'
@@ -18,14 +17,14 @@ async function init () {
1817
}
1918

2019
await exec('cd node_modules/sjcl/ && perl ./configure --no-export --compress=none --without-all --with-hmac --with-codecHex && make')
21-
const sjclFileContents = await fs.readFile('node_modules/sjcl/sjcl.js')
20+
const sjclFileContents = await readFile('node_modules/sjcl/sjcl.js')
2221
// Reexport the file as es6 module format
2322
const contents = `// @ts-nocheck
2423
export const sjcl = (() => {
2524
${sjclFileContents}
2625
return sjcl;
2726
})()`
28-
fs.writeFile('lib/sjcl.js', contents)
27+
writeFile('lib/sjcl.js', contents)
2928
}
3029

3130
init()

scripts/utils/build.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import resolve from '@rollup/plugin-node-resolve'
55
import css from 'rollup-plugin-import-css'
66
import svg from 'rollup-plugin-svg-import'
77
import { runtimeInjected, platformSupport } from '../../src/features.js'
8+
import { readFileSync } from 'fs'
89

910
/**
1011
* This is a helper function to require all files in a directory
@@ -81,9 +82,11 @@ export async function rollupScript (params) {
8182
supportsMozProxies = false
8283
} = params
8384

85+
const trackerLookupData = readFileSync('./build/tracker-lookup.json', 'utf8')
86+
const extensions = ['firefox', 'chrome', 'chrome-mv3']
87+
const trackerLookup = extensions.includes(platform) ? '$TRACKER_LOOKUP$' : trackerLookupData
8488
// The code is using a global, that we define here which means once tree shaken we get a browser specific output.
8589
const mozProxies = supportsMozProxies
86-
8790
const plugins = [
8891
css(),
8992
svg({
@@ -98,7 +101,9 @@ export async function rollupScript (params) {
98101
values: {
99102
// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f
100103
mozProxies,
101-
'import.meta.injectName': JSON.stringify(platform)
104+
'import.meta.injectName': JSON.stringify(platform),
105+
// To be replaced by the extension, but prevents tree shaking
106+
'import.meta.trackerLookup': trackerLookup
102107
}
103108
}),
104109
prefixPlugin(prefixMessage)

0 commit comments

Comments
 (0)