@slashgear/gdpr-cookie-scanner 1.0.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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +44 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +24 -0
- package/.github/workflows/ci.yml +38 -0
- package/.github/workflows/release.yml +57 -0
- package/.idea/gdpr-report.iml +8 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/CHANGELOG.md +7 -0
- package/CLAUDE.md +75 -0
- package/CODE_OF_CONDUCT.md +41 -0
- package/CONTRIBUTING.md +79 -0
- package/LICENSE +21 -0
- package/README.md +127 -0
- package/SECURITY.md +15 -0
- package/dist/analyzers/compliance.d.ts +13 -0
- package/dist/analyzers/compliance.d.ts.map +1 -0
- package/dist/analyzers/compliance.js +171 -0
- package/dist/analyzers/compliance.js.map +1 -0
- package/dist/analyzers/wording.d.ts +13 -0
- package/dist/analyzers/wording.d.ts.map +1 -0
- package/dist/analyzers/wording.js +91 -0
- package/dist/analyzers/wording.js.map +1 -0
- package/dist/classifiers/cookie-classifier.d.ts +8 -0
- package/dist/classifiers/cookie-classifier.d.ts.map +1 -0
- package/dist/classifiers/cookie-classifier.js +108 -0
- package/dist/classifiers/cookie-classifier.js.map +1 -0
- package/dist/classifiers/network-classifier.d.ts +9 -0
- package/dist/classifiers/network-classifier.d.ts.map +1 -0
- package/dist/classifiers/network-classifier.js +51 -0
- package/dist/classifiers/network-classifier.js.map +1 -0
- package/dist/classifiers/tracker-list.d.ts +16 -0
- package/dist/classifiers/tracker-list.d.ts.map +1 -0
- package/dist/classifiers/tracker-list.js +86 -0
- package/dist/classifiers/tracker-list.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +110 -0
- package/dist/cli.js.map +1 -0
- package/dist/report/generator.d.ts +19 -0
- package/dist/report/generator.d.ts.map +1 -0
- package/dist/report/generator.js +552 -0
- package/dist/report/generator.js.map +1 -0
- package/dist/scanner/browser.d.ts +11 -0
- package/dist/scanner/browser.d.ts.map +1 -0
- package/dist/scanner/browser.js +38 -0
- package/dist/scanner/browser.js.map +1 -0
- package/dist/scanner/consent-modal.d.ts +5 -0
- package/dist/scanner/consent-modal.d.ts.map +1 -0
- package/dist/scanner/consent-modal.js +244 -0
- package/dist/scanner/consent-modal.js.map +1 -0
- package/dist/scanner/cookies.d.ts +11 -0
- package/dist/scanner/cookies.d.ts.map +1 -0
- package/dist/scanner/cookies.js +30 -0
- package/dist/scanner/cookies.js.map +1 -0
- package/dist/scanner/index.d.ts +9 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +146 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/network.d.ts +8 -0
- package/dist/scanner/network.d.ts.map +1 -0
- package/dist/scanner/network.js +41 -0
- package/dist/scanner/network.js.map +1 -0
- package/dist/types.d.ts +105 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
- package/renovate.json +17 -0
- package/src/analyzers/compliance.ts +203 -0
- package/src/analyzers/wording.ts +112 -0
- package/src/classifiers/cookie-classifier.ts +125 -0
- package/src/classifiers/network-classifier.ts +65 -0
- package/src/classifiers/tracker-list.ts +105 -0
- package/src/cli.ts +134 -0
- package/src/report/generator.ts +703 -0
- package/src/scanner/browser.ts +52 -0
- package/src/scanner/consent-modal.ts +276 -0
- package/src/scanner/cookies.ts +43 -0
- package/src/scanner/index.ts +163 -0
- package/src/scanner/network.ts +51 -0
- package/src/types.ts +134 -0
- package/tsconfig.json +18 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
export type CookieCategory =
|
|
2
|
+
| "strictly-necessary"
|
|
3
|
+
| "analytics"
|
|
4
|
+
| "advertising"
|
|
5
|
+
| "social"
|
|
6
|
+
| "personalization"
|
|
7
|
+
| "unknown";
|
|
8
|
+
|
|
9
|
+
export type ConsentButtonType = "accept" | "reject" | "preferences" | "close" | "unknown";
|
|
10
|
+
|
|
11
|
+
export interface ScannedCookie {
|
|
12
|
+
name: string;
|
|
13
|
+
domain: string;
|
|
14
|
+
path: string;
|
|
15
|
+
value: string;
|
|
16
|
+
expires: number | null; // timestamp, null = session cookie
|
|
17
|
+
httpOnly: boolean;
|
|
18
|
+
secure: boolean;
|
|
19
|
+
sameSite: string | null;
|
|
20
|
+
category: CookieCategory;
|
|
21
|
+
requiresConsent: boolean;
|
|
22
|
+
capturedAt: "before-interaction" | "after-accept" | "after-reject";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface NetworkRequest {
|
|
26
|
+
url: string;
|
|
27
|
+
method: string;
|
|
28
|
+
resourceType: string;
|
|
29
|
+
initiator: string | null;
|
|
30
|
+
isThirdParty: boolean;
|
|
31
|
+
trackerCategory: TrackerCategory | null;
|
|
32
|
+
trackerName: string | null;
|
|
33
|
+
capturedAt: "before-interaction" | "after-accept" | "after-reject";
|
|
34
|
+
responseStatus: number | null;
|
|
35
|
+
contentType: string | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type TrackerCategory =
|
|
39
|
+
| "analytics"
|
|
40
|
+
| "advertising"
|
|
41
|
+
| "social"
|
|
42
|
+
| "fingerprinting"
|
|
43
|
+
| "pixel"
|
|
44
|
+
| "cdn"
|
|
45
|
+
| "unknown";
|
|
46
|
+
|
|
47
|
+
export interface ConsentButton {
|
|
48
|
+
type: ConsentButtonType;
|
|
49
|
+
text: string;
|
|
50
|
+
selector: string;
|
|
51
|
+
isVisible: boolean;
|
|
52
|
+
boundingBox: { x: number; y: number; width: number; height: number } | null;
|
|
53
|
+
fontSize: number | null;
|
|
54
|
+
backgroundColor: string | null;
|
|
55
|
+
textColor: string | null;
|
|
56
|
+
contrastRatio: number | null;
|
|
57
|
+
clickDepth: number; // how many clicks needed to reach this button
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface ConsentCheckbox {
|
|
61
|
+
name: string;
|
|
62
|
+
label: string;
|
|
63
|
+
isCheckedByDefault: boolean;
|
|
64
|
+
category: CookieCategory;
|
|
65
|
+
selector: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ConsentModal {
|
|
69
|
+
detected: boolean;
|
|
70
|
+
selector: string | null;
|
|
71
|
+
text: string;
|
|
72
|
+
buttons: ConsentButton[];
|
|
73
|
+
checkboxes: ConsentCheckbox[];
|
|
74
|
+
hasGranularControls: boolean;
|
|
75
|
+
layerCount: number; // number of clicks to reach full options
|
|
76
|
+
screenshotPath: string | null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface DarkPatternIssue {
|
|
80
|
+
type: DarkPatternType;
|
|
81
|
+
severity: "critical" | "warning" | "info";
|
|
82
|
+
description: string;
|
|
83
|
+
evidence: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export type DarkPatternType =
|
|
87
|
+
| "asymmetric-prominence" // Accept more visible than Reject
|
|
88
|
+
| "click-asymmetry" // More clicks needed to reject
|
|
89
|
+
| "pre-ticked" // Checkboxes pre-ticked
|
|
90
|
+
| "misleading-wording" // Ambiguous button labels
|
|
91
|
+
| "cookie-wall" // No access without consent
|
|
92
|
+
| "nudging" // Visual nudging toward accept
|
|
93
|
+
| "no-reject-button" // No clear reject option
|
|
94
|
+
| "buried-reject" // Reject buried in sub-menus
|
|
95
|
+
| "auto-consent" // Scroll/navigation as consent
|
|
96
|
+
| "missing-info"; // Missing required information
|
|
97
|
+
|
|
98
|
+
export interface ComplianceScore {
|
|
99
|
+
total: number; // 0-100
|
|
100
|
+
breakdown: {
|
|
101
|
+
consentValidity: number; // 0-25: freely given, specific, informed, unambiguous
|
|
102
|
+
easyRefusal: number; // 0-25: reject as easy as accept
|
|
103
|
+
transparency: number; // 0-25: clear info, partner names, purposes
|
|
104
|
+
cookieBehavior: number; // 0-25: no cookies before consent, cookies respected
|
|
105
|
+
};
|
|
106
|
+
issues: DarkPatternIssue[];
|
|
107
|
+
grade: "A" | "B" | "C" | "D" | "F";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface ScanOptions {
|
|
111
|
+
url: string;
|
|
112
|
+
outputDir: string;
|
|
113
|
+
timeout: number; // ms
|
|
114
|
+
screenshots: boolean;
|
|
115
|
+
locale: string;
|
|
116
|
+
verbose: boolean;
|
|
117
|
+
userAgent?: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface ScanResult {
|
|
121
|
+
url: string;
|
|
122
|
+
scanDate: string;
|
|
123
|
+
duration: number; // ms
|
|
124
|
+
modal: ConsentModal;
|
|
125
|
+
cookiesBeforeInteraction: ScannedCookie[];
|
|
126
|
+
cookiesAfterAccept: ScannedCookie[];
|
|
127
|
+
cookiesAfterReject: ScannedCookie[];
|
|
128
|
+
networkBeforeInteraction: NetworkRequest[];
|
|
129
|
+
networkAfterAccept: NetworkRequest[];
|
|
130
|
+
networkAfterReject: NetworkRequest[];
|
|
131
|
+
compliance: ComplianceScore;
|
|
132
|
+
screenshotPaths: string[];
|
|
133
|
+
errors: string[];
|
|
134
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"rootDir": "src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"declaration": true,
|
|
12
|
+
"declarationMap": true,
|
|
13
|
+
"sourceMap": true,
|
|
14
|
+
"resolveJsonModule": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*"],
|
|
17
|
+
"exclude": ["node_modules", "dist"]
|
|
18
|
+
}
|