Skip to content

Commit fa23d22

Browse files
authored
Tweaks in CPM rule generation (#147)
* add simple selector escaping * Fix existing rule detection: click is not always the first opt-out step
1 parent e8d1398 commit fa23d22

File tree

2 files changed

+17
-9
lines changed

2 files changed

+17
-9
lines changed

collectors/CookiePopups/scrapeScript.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@ function getButtons(el) {
9797
return Array.from(el.querySelectorAll('button, input[type="button"], input[type="submit"], a, [role="button"], [class*="button"]'));
9898
}
9999

100+
/**
101+
* Naive selector escaping. Use with caution.
102+
* @param {string} selector
103+
* @returns {string}
104+
*/
105+
function insecureEscapeSelectorPart(selector) {
106+
return selector.replace(/[.*+?^${}()|[\]\\"]/g, '\\$&');
107+
}
108+
100109
/**
101110
* Get the selector for an element
102111
* @param {HTMLElement} el - The element to get the selector for
@@ -134,7 +143,7 @@ function getSelector(el, specificity) {
134143

135144
if (specificity.ids) {
136145
if (element.id) {
137-
localSelector += `#${element.id}`;
146+
localSelector += `#${insecureEscapeSelectorPart(element.id)}`;
138147
} else if (!element.hasAttribute('id')) { // do not add it for id attribute without a value
139148
localSelector += `:not([id])`;
140149
}
@@ -143,15 +152,15 @@ function getSelector(el, specificity) {
143152
if (specificity.dataAttributes) {
144153
const dataAttributes = Array.from(element.attributes).filter(a => a.name.startsWith('data-'));
145154
dataAttributes.forEach(a => {
146-
const escapedValue = a.value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
155+
const escapedValue = insecureEscapeSelectorPart(a.value);
147156
localSelector += `[${a.name}="${escapedValue}"]`;
148157
});
149158
}
150159

151160
if (specificity.classes) {
152161
const classes = Array.from(element.classList);
153162
if (classes.length > 0) {
154-
localSelector += `.${classes.join('.')}`;
163+
localSelector += `.${classes.map(c => insecureEscapeSelectorPart(c)).join('.')}`;
155164
}
156165
}
157166

post-processing/generate-autoconsent-rules/generation.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,17 @@
66
* @returns {boolean} True if buttons are the same.
77
*/
88
function isSameRejectButton(newButton, existingRule) {
9-
if (!existingRule.optOut || existingRule.optOut.length === 0) {
9+
if (!existingRule.optOut) {
1010
return false;
1111
}
1212

13-
const existingOptOut = existingRule.optOut[0];
14-
15-
// Compare selector
16-
if (existingOptOut.waitForThenClick !== newButton.selector) {
13+
const existingOptOut = existingRule.optOut.find(optOut => optOut.waitForThenClick);
14+
if (!existingOptOut) {
1715
return false;
1816
}
1917

20-
return true;
18+
// Compare selector
19+
return existingOptOut.waitForThenClick === newButton.selector;
2120
}
2221

2322
/**

0 commit comments

Comments
 (0)