privalint 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.de.md +89 -0
- package/README.md +222 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +183 -0
- package/dist/cli.js.map +1 -0
- package/dist/consent.d.ts +12 -0
- package/dist/consent.js +185 -0
- package/dist/consent.js.map +1 -0
- package/dist/data/third-parties.d.ts +13 -0
- package/dist/data/third-parties.js +42 -0
- package/dist/data/third-parties.js.map +1 -0
- package/dist/data/trackers.d.ts +21 -0
- package/dist/data/trackers.js +135 -0
- package/dist/data/trackers.js.map +1 -0
- package/dist/i18n.d.ts +5 -0
- package/dist/i18n.js +3 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/legal.d.ts +10 -0
- package/dist/legal.js +99 -0
- package/dist/legal.js.map +1 -0
- package/dist/meta.d.ts +3 -0
- package/dist/meta.js +6 -0
- package/dist/meta.js.map +1 -0
- package/dist/reporters/index.d.ts +11 -0
- package/dist/reporters/index.js +19 -0
- package/dist/reporters/index.js.map +1 -0
- package/dist/reporters/json.d.ts +2 -0
- package/dist/reporters/json.js +2 -0
- package/dist/reporters/json.js.map +1 -0
- package/dist/reporters/markdown.d.ts +9 -0
- package/dist/reporters/markdown.js +49 -0
- package/dist/reporters/markdown.js.map +1 -0
- package/dist/reporters/messages.d.ts +21 -0
- package/dist/reporters/messages.js +62 -0
- package/dist/reporters/messages.js.map +1 -0
- package/dist/reporters/sarif.d.ts +10 -0
- package/dist/reporters/sarif.js +84 -0
- package/dist/reporters/sarif.js.map +1 -0
- package/dist/reporters/shared.d.ts +3 -0
- package/dist/reporters/shared.js +17 -0
- package/dist/reporters/shared.js.map +1 -0
- package/dist/reporters/text.d.ts +2 -0
- package/dist/reporters/text.js +56 -0
- package/dist/reporters/text.js.map +1 -0
- package/dist/rules/google-fonts.d.ts +2 -0
- package/dist/rules/google-fonts.js +68 -0
- package/dist/rules/google-fonts.js.map +1 -0
- package/dist/rules/impressum-link.d.ts +2 -0
- package/dist/rules/impressum-link.js +59 -0
- package/dist/rules/impressum-link.js.map +1 -0
- package/dist/rules/index.d.ts +11 -0
- package/dist/rules/index.js +20 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/links.d.ts +8 -0
- package/dist/rules/links.js +16 -0
- package/dist/rules/links.js.map +1 -0
- package/dist/rules/pre-consent-trackers.d.ts +2 -0
- package/dist/rules/pre-consent-trackers.js +45 -0
- package/dist/rules/pre-consent-trackers.js.map +1 -0
- package/dist/rules/privacy-policy-link.d.ts +2 -0
- package/dist/rules/privacy-policy-link.js +33 -0
- package/dist/rules/privacy-policy-link.js.map +1 -0
- package/dist/rules/reject-option.d.ts +2 -0
- package/dist/rules/reject-option.js +66 -0
- package/dist/rules/reject-option.js.map +1 -0
- package/dist/rules/third-party-cdns.d.ts +2 -0
- package/dist/rules/third-party-cdns.js +30 -0
- package/dist/rules/third-party-cdns.js.map +1 -0
- package/dist/rules/third-party-embeds.d.ts +2 -0
- package/dist/rules/third-party-embeds.js +30 -0
- package/dist/rules/third-party-embeds.js.map +1 -0
- package/dist/rules/third-party-hits.d.ts +4 -0
- package/dist/rules/third-party-hits.js +13 -0
- package/dist/rules/third-party-hits.js.map +1 -0
- package/dist/rules/tracker-hits.d.ts +11 -0
- package/dist/rules/tracker-hits.js +40 -0
- package/dist/rules/tracker-hits.js.map +1 -0
- package/dist/rules/trackers-after-reject.d.ts +2 -0
- package/dist/rules/trackers-after-reject.js +39 -0
- package/dist/rules/trackers-after-reject.js.map +1 -0
- package/dist/scanner.d.ts +39 -0
- package/dist/scanner.js +175 -0
- package/dist/scanner.js.map +1 -0
- package/dist/types.d.ts +105 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/url.d.ts +26 -0
- package/dist/url.js +71 -0
- package/dist/url.js.map +1 -0
- package/package.json +65 -4
package/dist/consent.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Button selectors of common consent managers. Best effort: vendors change
|
|
3
|
+
* their markup, so the label heuristic below is the fallback for everything
|
|
4
|
+
* that isn't listed or no longer matches.
|
|
5
|
+
*/
|
|
6
|
+
const KNOWN_CMPS = [
|
|
7
|
+
{
|
|
8
|
+
name: 'Cookiebot',
|
|
9
|
+
accept: '#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll, #CybotCookiebotDialogBodyButtonAccept',
|
|
10
|
+
reject: '#CybotCookiebotDialogBodyButtonDecline',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'OneTrust',
|
|
14
|
+
accept: '#onetrust-accept-btn-handler',
|
|
15
|
+
reject: '#onetrust-reject-all-handler',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: 'Usercentrics',
|
|
19
|
+
accept: '[data-testid="uc-accept-all-button"]',
|
|
20
|
+
reject: '[data-testid="uc-deny-all-button"]',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'Borlabs Cookie',
|
|
24
|
+
accept: '#BorlabsCookieBox [data-cookie-accept-all]',
|
|
25
|
+
reject: '#BorlabsCookieBox [data-cookie-refuse]',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'Complianz',
|
|
29
|
+
accept: '.cmplz-cookiebanner .cmplz-accept',
|
|
30
|
+
reject: '.cmplz-cookiebanner .cmplz-deny',
|
|
31
|
+
},
|
|
32
|
+
{ name: 'CookieYes', accept: '.cky-btn-accept', reject: '.cky-btn-reject' },
|
|
33
|
+
{
|
|
34
|
+
name: 'Didomi',
|
|
35
|
+
accept: '#didomi-notice-agree-button',
|
|
36
|
+
reject: '#didomi-notice-disagree-button',
|
|
37
|
+
},
|
|
38
|
+
{ name: 'consentmanager', accept: '.cmpboxbtnyes', reject: '.cmpboxbtnno' },
|
|
39
|
+
{ name: 'iubenda', accept: '.iubenda-cs-accept-btn', reject: '.iubenda-cs-reject-btn' },
|
|
40
|
+
{ name: 'Klaro', accept: '.klaro .cm-btn-success', reject: '.klaro .cm-btn-decline' },
|
|
41
|
+
{
|
|
42
|
+
name: 'CookieConsent',
|
|
43
|
+
accept: '#cc-main [data-role="all"]',
|
|
44
|
+
reject: '#cc-main [data-role="necessary"]',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
// Unanchored on purpose: "Alle Cookies akzeptieren" and "Accept all cookies" must both match.
|
|
48
|
+
// Labels that also match REJECT_LABEL ("Nur notwendige akzeptieren") are never treated as accept.
|
|
49
|
+
const ACCEPT_LABEL = /akzeptieren|annehmen|zustimmen|einwilligen|einverstanden|alles? (cookies )?(zulassen|erlauben)|\baccept|\ballow all|\bagree\b|accepter|aceptar|accetta|accepteren|alles toestaan/i;
|
|
50
|
+
const REJECT_LABEL = /ablehnen|verweigern|nur (technisch )?(notwendige|essenzielle|erforderliche)|\breject|\bdecline|\bdeny\b|\brefuse|(only|use) (strictly )?(necessary|essential|required)|refuser|continuer sans accepter|rechazar|rifiuta|weigeren|alleen noodzakelijke/i;
|
|
51
|
+
/** Second option on "pay or OK" banners: accept tracking or take out a subscription. */
|
|
52
|
+
const SUBSCRIBE = /abonn|\babo\b|subscri|werbefrei|ohne werbung|ad-free|without ads|\bpur\b/i;
|
|
53
|
+
/** A frame without any of these words is not showing a consent banner. */
|
|
54
|
+
const CONSENT_CONTEXT = /cookie|consent|einwillig|tracking|datenschutz|privacy/i;
|
|
55
|
+
const CLICKABLE = 'button, [role="button"], a, input[type="button"], input[type="submit"]';
|
|
56
|
+
/**
|
|
57
|
+
* Looks for a consent banner, clicks its reject button if there is one,
|
|
58
|
+
* reloads the page and records what still gets loaded. The page must already
|
|
59
|
+
* be loaded; `requests` is the live array the page's request listener writes to.
|
|
60
|
+
*/
|
|
61
|
+
export async function observeConsent(page, context, requests, options) {
|
|
62
|
+
const banner = await findBanner(page);
|
|
63
|
+
if (banner === undefined) {
|
|
64
|
+
return { bannerFound: false, rejected: false };
|
|
65
|
+
}
|
|
66
|
+
const observation = {
|
|
67
|
+
bannerFound: true,
|
|
68
|
+
rejected: false,
|
|
69
|
+
...(banner.cmp === undefined ? {} : { cmp: banner.cmp }),
|
|
70
|
+
...(banner.acceptLabel === undefined ? {} : { acceptLabel: banner.acceptLabel }),
|
|
71
|
+
...(banner.rejectLabel === undefined ? {} : { rejectLabel: banner.rejectLabel }),
|
|
72
|
+
...(banner.payOrOk ? { payOrOk: true } : {}),
|
|
73
|
+
};
|
|
74
|
+
if (banner.reject === undefined) {
|
|
75
|
+
return observation;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const cookiesBefore = new Set((await context.cookies()).map(cookieKey));
|
|
79
|
+
const firstRequest = requests.length;
|
|
80
|
+
await banner.reject.click({ timeout: 5_000 });
|
|
81
|
+
await settle(page, options);
|
|
82
|
+
await page.reload({ waitUntil: 'load', timeout: options.timeoutMs });
|
|
83
|
+
await settle(page, options);
|
|
84
|
+
const cookies = (await context.cookies())
|
|
85
|
+
.filter((cookie) => !cookiesBefore.has(cookieKey(cookie)))
|
|
86
|
+
.map(({ name, domain, path, expires }) => ({ name, domain, path, expires }));
|
|
87
|
+
return {
|
|
88
|
+
...observation,
|
|
89
|
+
rejected: true,
|
|
90
|
+
afterReject: { requests: requests.slice(firstRequest), cookies },
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
95
|
+
return { ...observation, error: message.split('\n')[0] ?? message };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function findBanner(page) {
|
|
99
|
+
for (const cmp of KNOWN_CMPS) {
|
|
100
|
+
const accept = await firstVisible(page.locator(cmp.accept));
|
|
101
|
+
if (accept !== undefined) {
|
|
102
|
+
const reject = await firstVisible(page.locator(cmp.reject));
|
|
103
|
+
return describe(accept, reject, cmp.name);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Unknown or self-built banners: go by button labels, in every frame.
|
|
107
|
+
for (const frame of page.frames()) {
|
|
108
|
+
const text = await frame
|
|
109
|
+
.locator('body')
|
|
110
|
+
.innerText({ timeout: 2_000 })
|
|
111
|
+
.catch(() => '');
|
|
112
|
+
if (!CONSENT_CONTEXT.test(text)) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const clickable = frame.locator(CLICKABLE);
|
|
116
|
+
const accept = await firstVisible(clickable.filter({ hasText: ACCEPT_LABEL }).filter({ hasNotText: REJECT_LABEL }));
|
|
117
|
+
if (accept !== undefined) {
|
|
118
|
+
const reject = await firstVisible(clickable.filter({ hasText: REJECT_LABEL }));
|
|
119
|
+
return describe(accept, reject);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
async function describe(accept, reject, cmp) {
|
|
125
|
+
const banner = { acceptLabel: await label(accept) };
|
|
126
|
+
if (reject === undefined && (await offersSubscription(accept))) {
|
|
127
|
+
banner.payOrOk = true;
|
|
128
|
+
}
|
|
129
|
+
if (cmp !== undefined) {
|
|
130
|
+
banner.cmp = cmp;
|
|
131
|
+
}
|
|
132
|
+
if (reject !== undefined) {
|
|
133
|
+
banner.reject = reject;
|
|
134
|
+
banner.rejectLabel = await label(reject);
|
|
135
|
+
}
|
|
136
|
+
return banner;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Walks up from the accept button to the banner's outermost container below
|
|
140
|
+
* <body> and looks for a subscription offer among its buttons and links. The
|
|
141
|
+
* site's own navigation lives outside that container, so its "Abo" link
|
|
142
|
+
* doesn't count.
|
|
143
|
+
*/
|
|
144
|
+
async function offersSubscription(accept) {
|
|
145
|
+
return accept
|
|
146
|
+
.evaluate((element, source) => {
|
|
147
|
+
const pattern = new RegExp(source, 'i');
|
|
148
|
+
const parentOf = (node) => {
|
|
149
|
+
const root = node.getRootNode();
|
|
150
|
+
return node.parentElement ?? (root instanceof ShadowRoot ? root.host : null);
|
|
151
|
+
};
|
|
152
|
+
let container = element;
|
|
153
|
+
for (let parent = parentOf(container); parent !== null; parent = parentOf(container)) {
|
|
154
|
+
if (parent === document.body || parent === document.documentElement) {
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
container = parent;
|
|
158
|
+
}
|
|
159
|
+
return [...container.querySelectorAll('a, button, [role="button"]')].some((control) => pattern.test(control.innerText ?? ''));
|
|
160
|
+
}, SUBSCRIBE.source)
|
|
161
|
+
.catch(() => false);
|
|
162
|
+
}
|
|
163
|
+
async function firstVisible(locator) {
|
|
164
|
+
const count = await locator.count().catch(() => 0);
|
|
165
|
+
for (let i = 0; i < Math.min(count, 10); i++) {
|
|
166
|
+
const candidate = locator.nth(i);
|
|
167
|
+
if (await candidate.isVisible().catch(() => false)) {
|
|
168
|
+
return candidate;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
async function label(locator) {
|
|
174
|
+
const text = await locator.innerText({ timeout: 1_000 }).catch(() => '');
|
|
175
|
+
const value = text.trim() || ((await locator.getAttribute('value').catch(() => null)) ?? '');
|
|
176
|
+
return value.replace(/\s+/g, ' ').trim().slice(0, 80);
|
|
177
|
+
}
|
|
178
|
+
async function settle(page, options) {
|
|
179
|
+
await page.waitForLoadState('networkidle', { timeout: options.timeoutMs }).catch(() => {
|
|
180
|
+
// See capturePage: some pages never go idle.
|
|
181
|
+
});
|
|
182
|
+
await page.waitForTimeout(options.settleMs);
|
|
183
|
+
}
|
|
184
|
+
const cookieKey = (cookie) => `${cookie.name}|${cookie.domain}|${cookie.path}`;
|
|
185
|
+
//# sourceMappingURL=consent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent.js","sourceRoot":"","sources":["../src/consent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type HostPattern } from '../url.js';
|
|
2
|
+
export interface ThirdParty extends HostPattern {
|
|
3
|
+
vendor: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Embedded content that transfers the visitor's IP address (and often sets
|
|
7
|
+
* cookies) as soon as it loads. Trackers are listed separately in trackers.ts.
|
|
8
|
+
*/
|
|
9
|
+
export declare const embeds: readonly ThirdParty[];
|
|
10
|
+
/** Public CDNs for scripts, styles and icon fonts. */
|
|
11
|
+
export declare const cdns: readonly ThirdParty[];
|
|
12
|
+
export declare const findEmbed: (url: string) => ThirdParty | undefined;
|
|
13
|
+
export declare const findCdn: (url: string) => ThirdParty | undefined;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { findByUrl } from '../url.js';
|
|
2
|
+
/**
|
|
3
|
+
* Embedded content that transfers the visitor's IP address (and often sets
|
|
4
|
+
* cookies) as soon as it loads. Trackers are listed separately in trackers.ts.
|
|
5
|
+
*/
|
|
6
|
+
export const embeds = [
|
|
7
|
+
{ vendor: 'YouTube', domains: ['youtube.com', 'youtube-nocookie.com', 'ytimg.com'] },
|
|
8
|
+
{ vendor: 'Vimeo', domains: ['player.vimeo.com', 'vimeocdn.com'] },
|
|
9
|
+
{
|
|
10
|
+
vendor: 'Google Maps',
|
|
11
|
+
domains: ['maps.googleapis.com', 'maps.gstatic.com', 'maps.google.com'],
|
|
12
|
+
},
|
|
13
|
+
{ vendor: 'Google Maps', domains: ['google.com'], paths: ['/maps/'] },
|
|
14
|
+
{ vendor: 'Google reCAPTCHA', domains: ['recaptcha.net'] },
|
|
15
|
+
{ vendor: 'Google reCAPTCHA', domains: ['google.com', 'gstatic.com'], paths: ['/recaptcha/'] },
|
|
16
|
+
{ vendor: 'Gravatar', domains: ['gravatar.com'] },
|
|
17
|
+
{ vendor: 'X (Twitter) embed', domains: ['platform.twitter.com', 'syndication.twitter.com'] },
|
|
18
|
+
{ vendor: 'Instagram embed', domains: ['instagram.com', 'cdninstagram.com'] },
|
|
19
|
+
{ vendor: 'Facebook plugin', domains: ['facebook.com'], paths: ['/plugins/'] },
|
|
20
|
+
{ vendor: 'Spotify embed', domains: ['open.spotify.com'], paths: ['/embed/'] },
|
|
21
|
+
{ vendor: 'Disqus', domains: ['disqus.com', 'disquscdn.com'] },
|
|
22
|
+
];
|
|
23
|
+
/** Public CDNs for scripts, styles and icon fonts. */
|
|
24
|
+
export const cdns = [
|
|
25
|
+
{ vendor: 'jsDelivr', domains: ['cdn.jsdelivr.net'] },
|
|
26
|
+
{ vendor: 'unpkg', domains: ['unpkg.com'] },
|
|
27
|
+
{ vendor: 'cdnjs', domains: ['cdnjs.cloudflare.com'] },
|
|
28
|
+
{ vendor: 'Google Hosted Libraries', domains: ['ajax.googleapis.com'] },
|
|
29
|
+
{ vendor: 'jQuery CDN', domains: ['code.jquery.com'] },
|
|
30
|
+
{
|
|
31
|
+
vendor: 'BootstrapCDN',
|
|
32
|
+
domains: ['stackpath.bootstrapcdn.com', 'maxcdn.bootstrapcdn.com'],
|
|
33
|
+
},
|
|
34
|
+
{ vendor: 'Tailwind Play CDN', domains: ['cdn.tailwindcss.com'] },
|
|
35
|
+
{
|
|
36
|
+
vendor: 'Font Awesome CDN',
|
|
37
|
+
domains: ['use.fontawesome.com', 'kit.fontawesome.com', 'ka-f.fontawesome.com'],
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
export const findEmbed = (url) => findByUrl(embeds, url);
|
|
41
|
+
export const findCdn = (url) => findByUrl(cdns, url);
|
|
42
|
+
//# sourceMappingURL=third-parties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"third-parties.js","sourceRoot":"","sources":["../../src/data/third-parties.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,WAAW,CAAC;AAMxD;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAA0B;IAC3C,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,aAAa,EAAE,sBAAsB,EAAE,WAAW,CAAC,EAAE;IACpF,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,kBAAkB,EAAE,cAAc,CAAC,EAAE;IAClE;QACE,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE,CAAC,qBAAqB,EAAE,kBAAkB,EAAE,iBAAiB,CAAC;KACxE;IACD,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE;IACrE,EAAE,MAAM,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,eAAe,CAAC,EAAE;IAC1D,EAAE,MAAM,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC,aAAa,CAAC,EAAE;IAC9F,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,cAAc,CAAC,EAAE;IACjD,EAAE,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,EAAE;IAC7F,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,eAAe,EAAE,kBAAkB,CAAC,EAAE;IAC7E,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,EAAE;IAC9E,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE;IAC9E,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,YAAY,EAAE,eAAe,CAAC,EAAE;CAC/D,CAAC;AAEF,sDAAsD;AACtD,MAAM,CAAC,MAAM,IAAI,GAA0B;IACzC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC,EAAE;IACrD,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE;IAC3C,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,sBAAsB,CAAC,EAAE;IACtD,EAAE,MAAM,EAAE,yBAAyB,EAAE,OAAO,EAAE,CAAC,qBAAqB,CAAC,EAAE;IACvE,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,iBAAiB,CAAC,EAAE;IACtD;QACE,MAAM,EAAE,cAAc;QACtB,OAAO,EAAE,CAAC,4BAA4B,EAAE,yBAAyB,CAAC;KACnE;IACD,EAAE,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,CAAC,qBAAqB,CAAC,EAAE;IACjE;QACE,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,CAAC,qBAAqB,EAAE,qBAAqB,EAAE,sBAAsB,CAAC;KAChF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACjE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type HostPattern } from '../url.js';
|
|
2
|
+
export type TrackerCategory = 'analytics' | 'advertising' | 'session-replay' | 'social' | 'marketing-automation' | 'tag-manager';
|
|
3
|
+
export interface Tracker extends HostPattern {
|
|
4
|
+
vendor: string;
|
|
5
|
+
category: TrackerCategory;
|
|
6
|
+
/**
|
|
7
|
+
* Cookies the vendor's script sets, including on the first-party domain.
|
|
8
|
+
* Strings are name prefixes; use a RegExp where a prefix would be too broad.
|
|
9
|
+
*/
|
|
10
|
+
cookies?: Array<string | RegExp>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Hand-maintained and MIT licensed, so it can ship with the package.
|
|
14
|
+
* Order matters: the first entry that matches wins, so put path-specific
|
|
15
|
+
* entries before broader ones on the same domain.
|
|
16
|
+
*
|
|
17
|
+
* Adding a vendor? See CONTRIBUTING.md.
|
|
18
|
+
*/
|
|
19
|
+
export declare const trackers: readonly Tracker[];
|
|
20
|
+
export declare function findTrackerByUrl(url: string): Tracker | undefined;
|
|
21
|
+
export declare function findTrackerByCookie(name: string): Tracker | undefined;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { findByUrl } from '../url.js';
|
|
2
|
+
/**
|
|
3
|
+
* Hand-maintained and MIT licensed, so it can ship with the package.
|
|
4
|
+
* Order matters: the first entry that matches wins, so put path-specific
|
|
5
|
+
* entries before broader ones on the same domain.
|
|
6
|
+
*
|
|
7
|
+
* Adding a vendor? See CONTRIBUTING.md.
|
|
8
|
+
*/
|
|
9
|
+
export const trackers = [
|
|
10
|
+
{
|
|
11
|
+
vendor: 'Google Analytics',
|
|
12
|
+
category: 'analytics',
|
|
13
|
+
domains: ['google-analytics.com', 'analytics.google.com'],
|
|
14
|
+
cookies: ['_ga', '_gid', '_gat'],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
vendor: 'Google Analytics',
|
|
18
|
+
category: 'analytics',
|
|
19
|
+
domains: ['googletagmanager.com'],
|
|
20
|
+
paths: ['/gtag/'],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
vendor: 'Google Tag Manager',
|
|
24
|
+
category: 'tag-manager',
|
|
25
|
+
domains: ['googletagmanager.com'],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
vendor: 'Google Ads',
|
|
29
|
+
category: 'advertising',
|
|
30
|
+
domains: ['googleadservices.com', 'doubleclick.net', 'googlesyndication.com'],
|
|
31
|
+
cookies: ['_gcl_'],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
vendor: 'Meta Pixel',
|
|
35
|
+
category: 'advertising',
|
|
36
|
+
domains: ['connect.facebook.net'],
|
|
37
|
+
cookies: ['_fbp', '_fbc'],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
vendor: 'Meta Pixel',
|
|
41
|
+
category: 'advertising',
|
|
42
|
+
domains: ['facebook.com'],
|
|
43
|
+
paths: ['/tr'],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
vendor: 'Hotjar',
|
|
47
|
+
category: 'session-replay',
|
|
48
|
+
domains: ['hotjar.com', 'hotjar.io'],
|
|
49
|
+
cookies: ['_hj'],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
vendor: 'Microsoft Clarity',
|
|
53
|
+
category: 'session-replay',
|
|
54
|
+
domains: ['clarity.ms'],
|
|
55
|
+
cookies: ['_clck', '_clsk'],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
vendor: 'Microsoft Advertising',
|
|
59
|
+
category: 'advertising',
|
|
60
|
+
domains: ['bat.bing.com'],
|
|
61
|
+
cookies: ['_uetsid', '_uetvid'],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
vendor: 'LinkedIn Insight',
|
|
65
|
+
category: 'advertising',
|
|
66
|
+
domains: ['snap.licdn.com', 'px.ads.linkedin.com'],
|
|
67
|
+
cookies: ['li_fat_id'],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
vendor: 'TikTok Pixel',
|
|
71
|
+
category: 'advertising',
|
|
72
|
+
domains: ['analytics.tiktok.com'],
|
|
73
|
+
cookies: ['_ttp'],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
vendor: 'X (Twitter) Pixel',
|
|
77
|
+
category: 'advertising',
|
|
78
|
+
domains: ['static.ads-twitter.com', 'analytics.twitter.com'],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
vendor: 'Pinterest Tag',
|
|
82
|
+
category: 'advertising',
|
|
83
|
+
domains: ['ct.pinterest.com'],
|
|
84
|
+
cookies: ['_pin_unauth'],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
vendor: 'Snap Pixel',
|
|
88
|
+
category: 'advertising',
|
|
89
|
+
domains: ['sc-static.net', 'tr.snapchat.com'],
|
|
90
|
+
cookies: ['_scid'],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
vendor: 'Yandex Metrica',
|
|
94
|
+
category: 'analytics',
|
|
95
|
+
domains: ['mc.yandex.ru', 'mc.yandex.com'],
|
|
96
|
+
cookies: ['_ym_'],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
vendor: 'HubSpot',
|
|
100
|
+
category: 'marketing-automation',
|
|
101
|
+
domains: ['js.hs-scripts.com', 'js.hs-analytics.net', 'track.hubspot.com'],
|
|
102
|
+
cookies: ['__hstc', 'hubspotutk'],
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
vendor: 'Segment',
|
|
106
|
+
category: 'analytics',
|
|
107
|
+
domains: ['cdn.segment.com', 'api.segment.io'],
|
|
108
|
+
cookies: ['ajs_'],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
vendor: 'Mixpanel',
|
|
112
|
+
category: 'analytics',
|
|
113
|
+
domains: ['cdn.mxpnl.com', 'api-js.mixpanel.com'],
|
|
114
|
+
cookies: [/^mp_\w+_mixpanel$/],
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
vendor: 'Amplitude',
|
|
118
|
+
category: 'analytics',
|
|
119
|
+
domains: ['cdn.amplitude.com', 'api2.amplitude.com'],
|
|
120
|
+
cookies: ['AMP_'],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
vendor: 'Matomo',
|
|
124
|
+
category: 'analytics',
|
|
125
|
+
domains: ['matomo.cloud'],
|
|
126
|
+
cookies: ['_pk_'],
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
export function findTrackerByUrl(url) {
|
|
130
|
+
return findByUrl(trackers, url);
|
|
131
|
+
}
|
|
132
|
+
export function findTrackerByCookie(name) {
|
|
133
|
+
return trackers.find((tracker) => tracker.cookies?.some((pattern) => typeof pattern === 'string' ? name.startsWith(pattern) : pattern.test(name)));
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=trackers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trackers.js","sourceRoot":"","sources":["../../src/data/trackers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,WAAW,CAAC;AAoBxD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAuB;IAC1C;QACE,MAAM,EAAE,kBAAkB;QAC1B,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,CAAC,sBAAsB,EAAE,sBAAsB,CAAC;QACzD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC;KACjC;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,CAAC,sBAAsB,CAAC;QACjC,KAAK,EAAE,CAAC,QAAQ,CAAC;KAClB;IACD;QACE,MAAM,EAAE,oBAAoB;QAC5B,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,CAAC,sBAAsB,CAAC;KAClC;IACD;QACE,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,CAAC,sBAAsB,EAAE,iBAAiB,EAAE,uBAAuB,CAAC;QAC7E,OAAO,EAAE,CAAC,OAAO,CAAC;KACnB;IACD;QACE,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,CAAC,sBAAsB,CAAC;QACjC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;KAC1B;IACD;QACE,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,CAAC,cAAc,CAAC;QACzB,KAAK,EAAE,CAAC,KAAK,CAAC;KACf;IACD;QACE,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,gBAAgB;QAC1B,OAAO,EAAE,CAAC,YAAY,EAAE,WAAW,CAAC;QACpC,OAAO,EAAE,CAAC,KAAK,CAAC;KACjB;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,QAAQ,EAAE,gBAAgB;QAC1B,OAAO,EAAE,CAAC,YAAY,CAAC;QACvB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC;KAC5B;IACD;QACE,MAAM,EAAE,uBAAuB;QAC/B,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,CAAC,cAAc,CAAC;QACzB,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;KAChC;IACD;QACE,MAAM,EAAE,kBAAkB;QAC1B,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;QAClD,OAAO,EAAE,CAAC,WAAW,CAAC;KACvB;IACD;QACE,MAAM,EAAE,cAAc;QACtB,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,CAAC,sBAAsB,CAAC;QACjC,OAAO,EAAE,CAAC,MAAM,CAAC;KAClB;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,CAAC,wBAAwB,EAAE,uBAAuB,CAAC;KAC7D;IACD;QACE,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,CAAC,kBAAkB,CAAC;QAC7B,OAAO,EAAE,CAAC,aAAa,CAAC;KACzB;IACD;QACE,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,aAAa;QACvB,OAAO,EAAE,CAAC,eAAe,EAAE,iBAAiB,CAAC;QAC7C,OAAO,EAAE,CAAC,OAAO,CAAC;KACnB;IACD;QACE,MAAM,EAAE,gBAAgB;QACxB,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;QAC1C,OAAO,EAAE,CAAC,MAAM,CAAC;KAClB;IACD;QACE,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,sBAAsB;QAChC,OAAO,EAAE,CAAC,mBAAmB,EAAE,qBAAqB,EAAE,mBAAmB,CAAC;QAC1E,OAAO,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC;KAClC;IACD;QACE,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,CAAC,iBAAiB,EAAE,gBAAgB,CAAC;QAC9C,OAAO,EAAE,CAAC,MAAM,CAAC;KAClB;IACD;QACE,MAAM,EAAE,UAAU;QAClB,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,CAAC,eAAe,EAAE,qBAAqB,CAAC;QACjD,OAAO,EAAE,CAAC,mBAAmB,CAAC;KAC/B;IACD;QACE,MAAM,EAAE,WAAW;QACnB,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,CAAC,mBAAmB,EAAE,oBAAoB,CAAC;QACpD,OAAO,EAAE,CAAC,MAAM,CAAC;KAClB;IACD;QACE,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,CAAC,cAAc,CAAC;QACzB,OAAO,EAAE,CAAC,MAAM,CAAC;KAClB;CACF,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAC/B,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAChC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAC5E,CACF,CAAC;AACJ,CAAC"}
|
package/dist/i18n.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const LANGS: readonly ['en', 'de'];
|
|
2
|
+
export type Lang = (typeof LANGS)[number];
|
|
3
|
+
/** One string per language. Adding a language makes every missing translation a type error. */
|
|
4
|
+
export type Text = Record<Lang, string>;
|
|
5
|
+
export declare const say: (lang: Lang, text: Text) => string;
|
package/dist/i18n.js
ADDED
package/dist/i18n.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,IAAI,CAAU,CAAC;AAM3C,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,IAAU,EAAE,IAAU,EAAU,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { type Tracker, type TrackerCategory, trackers } from './data/trackers.js';
|
|
2
|
+
export { LANGS, type Lang, type Text } from './i18n.js';
|
|
3
|
+
export { legalReferences, REGIONS, type Region } from './legal.js';
|
|
4
|
+
export { defaultRules, googleFonts, impressumLink, preConsentTrackers, privacyPolicyLink, rejectOption, thirdPartyCdns, thirdPartyEmbeds, trackersAfterReject, } from './rules/index.js';
|
|
5
|
+
export { type ScanOptions, scan } from './scanner.js';
|
|
6
|
+
export type * from './types.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { trackers } from './data/trackers.js';
|
|
2
|
+
export { LANGS } from './i18n.js';
|
|
3
|
+
export { legalReferences, REGIONS } from './legal.js';
|
|
4
|
+
export { defaultRules, googleFonts, impressumLink, preConsentTrackers, privacyPolicyLink, rejectOption, thirdPartyCdns, thirdPartyEmbeds, trackersAfterReject, } from './rules/index.js';
|
|
5
|
+
export { scan } from './scanner.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,KAAK,EAAwB,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,OAAO,EAAe,MAAM,YAAY,CAAC;AACnE,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAoB,IAAI,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/legal.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Finding } from './types.js';
|
|
2
|
+
export declare const REGIONS: readonly ['de', 'at', 'ch', 'eu'];
|
|
3
|
+
export type Region = (typeof REGIONS)[number];
|
|
4
|
+
export declare const legalReferences: (ruleId: string, region: Region) => string[] | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* Attaches the legal basis of the chosen country to each finding and adjusts
|
|
7
|
+
* its severity where that country's law is softer or stricter. Findings of
|
|
8
|
+
* custom rules without an entry above are left as they are.
|
|
9
|
+
*/
|
|
10
|
+
export declare function applyRegion(findings: readonly Finding[], region: Region): Finding[];
|
package/dist/legal.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export const REGIONS = ['de', 'at', 'ch', 'eu'];
|
|
2
|
+
/**
|
|
3
|
+
* Legal basis per rule and country, cited the way lawyers in that country
|
|
4
|
+
* would cite it. `eu` is for sites outside Germany, Austria and Switzerland
|
|
5
|
+
* and refers to the EU instruments directly.
|
|
6
|
+
*/
|
|
7
|
+
const LEGAL = {
|
|
8
|
+
'pre-consent-trackers': {
|
|
9
|
+
de: ['§ 25 Abs. 1 TDDDG', 'Art. 6 Abs. 1 lit. a DSGVO', 'EuGH C-673/17 (Planet49)'],
|
|
10
|
+
at: ['§ 165 Abs. 3 TKG 2021', 'Art. 6 Abs. 1 lit. a DSGVO', 'EuGH C-673/17 (Planet49)'],
|
|
11
|
+
ch: ['Art. 45c FMG', 'Art. 6 DSG'],
|
|
12
|
+
eu: ['Art. 5(3) ePrivacy Directive', 'Art. 6(1)(a) GDPR', 'CJEU C-673/17 (Planet49)'],
|
|
13
|
+
},
|
|
14
|
+
'trackers-after-reject': {
|
|
15
|
+
de: ['§ 25 Abs. 1 TDDDG', 'Art. 7 Abs. 3 DSGVO'],
|
|
16
|
+
at: ['§ 165 Abs. 3 TKG 2021', 'Art. 7 Abs. 3 DSGVO'],
|
|
17
|
+
ch: ['Art. 45c FMG', 'Art. 30 Abs. 2 lit. b DSG'],
|
|
18
|
+
eu: ['Art. 5(3) ePrivacy Directive', 'Art. 7(3) GDPR'],
|
|
19
|
+
},
|
|
20
|
+
'reject-option': {
|
|
21
|
+
de: [
|
|
22
|
+
'§ 25 Abs. 1 TDDDG',
|
|
23
|
+
'Art. 4 Nr. 11 DSGVO',
|
|
24
|
+
'EDSA Cookie-Banner-Taskforce, 17.01.2023',
|
|
25
|
+
'DSK-Beschluss, 22.03.2023 (Pur-Abo-Modelle)',
|
|
26
|
+
],
|
|
27
|
+
at: [
|
|
28
|
+
'§ 165 Abs. 3 TKG 2021',
|
|
29
|
+
'Art. 4 Nr. 11 DSGVO',
|
|
30
|
+
'EDSA Cookie-Banner-Taskforce, 17.01.2023',
|
|
31
|
+
],
|
|
32
|
+
ch: ['Art. 45c FMG', 'EDÖB, Leitfaden zu Cookies (2025)'],
|
|
33
|
+
eu: ['Art. 4(11) GDPR', 'Art. 7(3) GDPR', 'EDPB Cookie Banner Taskforce report, 17.01.2023'],
|
|
34
|
+
},
|
|
35
|
+
'google-fonts': {
|
|
36
|
+
de: ['Art. 6 Abs. 1 DSGVO', 'LG München I, 20.01.2022, Az. 3 O 17493/20'],
|
|
37
|
+
at: ['Art. 6 Abs. 1 DSGVO'],
|
|
38
|
+
ch: ['Art. 6 DSG'],
|
|
39
|
+
eu: ['Art. 6(1) GDPR'],
|
|
40
|
+
},
|
|
41
|
+
'third-party-embeds': {
|
|
42
|
+
de: ['Art. 6 Abs. 1 DSGVO', '§ 25 Abs. 1 TDDDG'],
|
|
43
|
+
at: ['Art. 6 Abs. 1 DSGVO', '§ 165 Abs. 3 TKG 2021'],
|
|
44
|
+
ch: ['Art. 6 DSG', 'Art. 45c FMG'],
|
|
45
|
+
eu: ['Art. 6(1) GDPR', 'Art. 5(3) ePrivacy Directive'],
|
|
46
|
+
},
|
|
47
|
+
'third-party-cdns': {
|
|
48
|
+
de: ['Art. 6 Abs. 1 DSGVO'],
|
|
49
|
+
at: ['Art. 6 Abs. 1 DSGVO'],
|
|
50
|
+
ch: ['Art. 6 DSG'],
|
|
51
|
+
eu: ['Art. 6(1) GDPR'],
|
|
52
|
+
},
|
|
53
|
+
'impressum-link': {
|
|
54
|
+
de: ['§ 5 DDG', 'BGH, 20.07.2006, Az. I ZR 228/03'],
|
|
55
|
+
at: ['§ 5 ECG', '§ 25 MedienG'],
|
|
56
|
+
ch: ['Art. 3 Abs. 1 lit. s UWG'],
|
|
57
|
+
eu: ['Art. 5 Directive 2000/31/EC (e-commerce)'],
|
|
58
|
+
},
|
|
59
|
+
'privacy-policy-link': {
|
|
60
|
+
de: ['Art. 12 DSGVO', 'Art. 13 DSGVO'],
|
|
61
|
+
at: ['Art. 12 DSGVO', 'Art. 13 DSGVO'],
|
|
62
|
+
ch: ['Art. 19 DSG'],
|
|
63
|
+
eu: ['Art. 12 GDPR', 'Art. 13 GDPR'],
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
export const legalReferences = (ruleId, region) => LEGAL[ruleId]?.[region];
|
|
67
|
+
/**
|
|
68
|
+
* Attaches the legal basis of the chosen country to each finding and adjusts
|
|
69
|
+
* its severity where that country's law is softer or stricter. Findings of
|
|
70
|
+
* custom rules without an entry above are left as they are.
|
|
71
|
+
*/
|
|
72
|
+
export function applyRegion(findings, region) {
|
|
73
|
+
return findings.map((finding) => {
|
|
74
|
+
const references = legalReferences(finding.ruleId, region);
|
|
75
|
+
return {
|
|
76
|
+
...finding,
|
|
77
|
+
severity: severityFor(finding, region),
|
|
78
|
+
...(references === undefined ? {} : { references }),
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Switzerland uses an opt-out model for cookies and tracking (Art. 45c FMG) and
|
|
84
|
+
* requires an imprint only for offers in electronic commerce, so those findings
|
|
85
|
+
* drop one level there. Ignoring an explicit refusal stays as serious as anywhere.
|
|
86
|
+
*/
|
|
87
|
+
const SOFTER_IN_SWITZERLAND = new Set([
|
|
88
|
+
'pre-consent-trackers',
|
|
89
|
+
'third-party-embeds',
|
|
90
|
+
'impressum-link',
|
|
91
|
+
]);
|
|
92
|
+
function severityFor(finding, region) {
|
|
93
|
+
if (region === 'ch' && SOFTER_IN_SWITZERLAND.has(finding.ruleId)) {
|
|
94
|
+
return lower(finding.severity);
|
|
95
|
+
}
|
|
96
|
+
return finding.severity;
|
|
97
|
+
}
|
|
98
|
+
const lower = (severity) => (severity === 'error' ? 'warning' : 'info');
|
|
99
|
+
//# sourceMappingURL=legal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legal.js","sourceRoot":"","sources":["../src/legal.ts"],"names":[],"mappings":"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"}
|
package/dist/meta.d.ts
ADDED
package/dist/meta.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
3
|
+
export const VERSION = pkg.version;
|
|
4
|
+
export const REPOSITORY_URL = 'https://github.com/jexcellence/privalint';
|
|
5
|
+
export const ruleDocsUrl = (ruleId) => `${REPOSITORY_URL}/blob/main/docs/rules/${ruleId}.md`;
|
|
6
|
+
//# sourceMappingURL=meta.js.map
|
package/dist/meta.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.js","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAEvF,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;AACnC,MAAM,CAAC,MAAM,cAAc,GAAG,0CAA0C,CAAC;AAEzE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,EAAE,CAC5C,GAAG,cAAc,yBAAyB,MAAM,KAAK,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ScanResult } from '../types.js';
|
|
2
|
+
import { formatJson } from './json.js';
|
|
3
|
+
import { formatMarkdown } from './markdown.js';
|
|
4
|
+
import { formatSarif } from './sarif.js';
|
|
5
|
+
import { formatText } from './text.js';
|
|
6
|
+
export declare const FORMATS: readonly ['text', 'json', 'markdown', 'sarif'];
|
|
7
|
+
export type Format = (typeof FORMATS)[number];
|
|
8
|
+
export declare function format(result: ScanResult, kind: Format, options?: {
|
|
9
|
+
color?: boolean;
|
|
10
|
+
}): string;
|
|
11
|
+
export { formatJson, formatMarkdown, formatSarif, formatText };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { formatJson } from './json.js';
|
|
2
|
+
import { formatMarkdown } from './markdown.js';
|
|
3
|
+
import { formatSarif } from './sarif.js';
|
|
4
|
+
import { formatText } from './text.js';
|
|
5
|
+
export const FORMATS = ['text', 'json', 'markdown', 'sarif'];
|
|
6
|
+
export function format(result, kind, options = {}) {
|
|
7
|
+
switch (kind) {
|
|
8
|
+
case 'json':
|
|
9
|
+
return formatJson(result);
|
|
10
|
+
case 'markdown':
|
|
11
|
+
return formatMarkdown(result);
|
|
12
|
+
case 'sarif':
|
|
13
|
+
return formatSarif(result);
|
|
14
|
+
default:
|
|
15
|
+
return formatText(result, options.color);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export { formatJson, formatMarkdown, formatSarif, formatText };
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reporters/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAU,CAAC;AAGtE,MAAM,UAAU,MAAM,CAAC,MAAkB,EAAE,IAAY,EAAE,OAAO,GAAwB,EAAE;IACxF,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM;YACT,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;QAC5B,KAAK,UAAU;YACb,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;QAChC,KAAK,OAAO;YACV,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;QAC7B;YACE,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC"}
|