privalint 0.2.0 → 0.4.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/README.de.md +68 -2
- package/README.md +77 -13
- package/dist/assessment.d.ts +6 -0
- package/dist/assessment.js +115 -0
- package/dist/assessment.js.map +1 -0
- package/dist/capture.d.ts +5 -0
- package/dist/capture.js +162 -0
- package/dist/capture.js.map +1 -0
- package/dist/cli.js +48 -14
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +21 -0
- package/dist/config.js +113 -0
- package/dist/config.js.map +1 -0
- package/dist/consent.d.ts +3 -0
- package/dist/consent.js +81 -12
- package/dist/consent.js.map +1 -1
- package/dist/coverage.d.ts +13 -0
- package/dist/coverage.js +86 -0
- package/dist/coverage.js.map +1 -0
- package/dist/data/third-parties.js +9 -0
- package/dist/data/third-parties.js.map +1 -1
- package/dist/diagnostics.d.ts +28 -0
- package/dist/diagnostics.js +202 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/network.d.ts +68 -0
- package/dist/network.js +237 -0
- package/dist/network.js.map +1 -0
- package/dist/observations.d.ts +3 -0
- package/dist/observations.js +4 -0
- package/dist/observations.js.map +1 -0
- package/dist/policy.d.ts +6 -0
- package/dist/policy.js +37 -0
- package/dist/policy.js.map +1 -0
- package/dist/report-contract.d.ts +13 -0
- package/dist/report-contract.js +16 -0
- package/dist/report-contract.js.map +1 -0
- package/dist/reporters/capture.d.ts +5 -0
- package/dist/reporters/capture.js +87 -0
- package/dist/reporters/capture.js.map +1 -0
- package/dist/reporters/markdown.js +13 -1
- package/dist/reporters/markdown.js.map +1 -1
- package/dist/reporters/messages.d.ts +1 -0
- package/dist/reporters/messages.js +18 -6
- package/dist/reporters/messages.js.map +1 -1
- package/dist/reporters/sarif.js +48 -10
- package/dist/reporters/sarif.js.map +1 -1
- package/dist/reporters/shared.js +3 -2
- package/dist/reporters/shared.js.map +1 -1
- package/dist/reporters/text.js +10 -2
- package/dist/reporters/text.js.map +1 -1
- package/dist/rules/google-fonts.js +2 -1
- package/dist/rules/google-fonts.js.map +1 -1
- package/dist/rules/reject-option.js +6 -4
- package/dist/rules/reject-option.js.map +1 -1
- package/dist/rules/third-party-embeds.js +2 -2
- package/dist/rules/third-party-embeds.js.map +1 -1
- package/dist/rules/third-party-hits.js +2 -1
- package/dist/rules/third-party-hits.js.map +1 -1
- package/dist/rules/tracker-hits.js +2 -1
- package/dist/rules/tracker-hits.js.map +1 -1
- package/dist/scan-options.d.ts +45 -0
- package/dist/scan-options.js +2 -0
- package/dist/scan-options.js.map +1 -0
- package/dist/scanner.d.ts +4 -38
- package/dist/scanner.js +177 -114
- package/dist/scanner.js.map +1 -1
- package/dist/types.d.ts +119 -0
- package/package.json +7 -1
- package/schemas/report-1.0.0.schema.json +813 -0
- package/schemas/report-1.1.0.schema.json +833 -0
- package/schemas/sarif-properties-1.0.0.schema.json +785 -0
- package/schemas/sarif-properties-1.1.0.schema.json +810 -0
|
@@ -19,6 +19,15 @@ export const embeds = [
|
|
|
19
19
|
{ vendor: 'Facebook plugin', domains: ['facebook.com'], paths: ['/plugins/'] },
|
|
20
20
|
{ vendor: 'Spotify embed', domains: ['open.spotify.com'], paths: ['/embed/'] },
|
|
21
21
|
{ vendor: 'Disqus', domains: ['disqus.com', 'disquscdn.com'] },
|
|
22
|
+
{ vendor: 'hCaptcha', domains: ['hcaptcha.com'] },
|
|
23
|
+
{
|
|
24
|
+
vendor: 'Cloudflare Turnstile',
|
|
25
|
+
domains: ['challenges.cloudflare.com'],
|
|
26
|
+
paths: ['/turnstile/'],
|
|
27
|
+
},
|
|
28
|
+
{ vendor: 'OpenStreetMap tiles', domains: ['tile.openstreetmap.org'] },
|
|
29
|
+
{ vendor: 'TikTok embed', domains: ['tiktok.com'], paths: ['/embed', '/embed.js', '/player/'] },
|
|
30
|
+
{ vendor: 'Calendly', domains: ['calendly.com'] },
|
|
22
31
|
];
|
|
23
32
|
/** Public CDNs for scripts, styles and icon fonts. */
|
|
24
33
|
export const cdns = [
|
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"third-parties.js","sourceRoot":"","sources":["../../src/data/third-parties.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { BrowserContext, Request } from 'playwright';
|
|
2
|
+
import type { CapturePhase, LoadDiagnostic, LoadDiagnostics, LoadIssueKind, RecordedRequest, SkipReason } from './types.js';
|
|
3
|
+
/** Safe for diagnostics and operational logs. Raw URLs remain internal rule input. */
|
|
4
|
+
export declare function diagnosticUrl(raw: string): string;
|
|
5
|
+
/** Classify known transport codes; never persist arbitrary exception messages. */
|
|
6
|
+
export declare function classifyLoadError(error: unknown): LoadIssueKind;
|
|
7
|
+
export declare class Diagnostics {
|
|
8
|
+
private readonly maxIssues;
|
|
9
|
+
private readonly maxRecords;
|
|
10
|
+
readonly data: LoadDiagnostics;
|
|
11
|
+
phase: CapturePhase;
|
|
12
|
+
private readonly pending;
|
|
13
|
+
private readonly earlyFailures;
|
|
14
|
+
private stopped;
|
|
15
|
+
private readonly phaseIssues;
|
|
16
|
+
constructor(maxIssues: number, maxRecords?: number);
|
|
17
|
+
attach(context: BrowserContext, records: RecordedRequest[]): void;
|
|
18
|
+
private finish;
|
|
19
|
+
/** Defer storage until requestfailed to avoid counting adapter + browser errors twice. */
|
|
20
|
+
fail(request: Request, kind: LoadIssueKind, limit?: LoadDiagnostic['limit'], skippedReason?: SkipReason): void;
|
|
21
|
+
failUrl(url: string, kind: LoadIssueKind, limit?: LoadDiagnostic['limit'], skippedReason?: SkipReason): void;
|
|
22
|
+
add(kind: LoadIssueKind, url: string, extra?: Pick<LoadDiagnostic, 'status' | 'limit'>, phase?: CapturePhase): void;
|
|
23
|
+
private store;
|
|
24
|
+
hasIssues(phase: CapturePhase): boolean;
|
|
25
|
+
/** Freeze before closing the context: teardown errors are not resource failures. */
|
|
26
|
+
stop(): void;
|
|
27
|
+
private terminalFailure;
|
|
28
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/** Safe for diagnostics and operational logs. Raw URLs remain internal rule input. */
|
|
2
|
+
export function diagnosticUrl(raw) {
|
|
3
|
+
try {
|
|
4
|
+
const url = new URL(raw);
|
|
5
|
+
return /^https?:$/.test(url.protocol) ? `${url.origin}/[redacted]` : '[redacted]';
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return '[redacted]';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** Classify known transport codes; never persist arbitrary exception messages. */
|
|
12
|
+
export function classifyLoadError(error) {
|
|
13
|
+
const parts = [];
|
|
14
|
+
let cause = error;
|
|
15
|
+
for (let depth = 0; depth < 4 && cause instanceof Error; depth++) {
|
|
16
|
+
parts.push(cause.message, 'code' in cause ? String(cause.code) : '');
|
|
17
|
+
cause = cause.cause;
|
|
18
|
+
}
|
|
19
|
+
const text = parts.length > 0 ? parts.join(' ') : String(error);
|
|
20
|
+
if (/ERR_NAME_NOT_RESOLVED|ENOTFOUND|EAI_AGAIN/i.test(text))
|
|
21
|
+
return 'dns';
|
|
22
|
+
if (/ERR_CERT|ERR_SSL|CERT_|TLS|SELF_SIGNED|UNABLE_TO_VERIFY_LEAF/i.test(text))
|
|
23
|
+
return 'tls';
|
|
24
|
+
if (/timeout|timed.?out|ETIMEDOUT/i.test(text))
|
|
25
|
+
return 'timeout';
|
|
26
|
+
if (/ERR_CONNECTION|ECONN|ENETUNREACH|EHOSTUNREACH|socket hang up/i.test(text)) {
|
|
27
|
+
return 'connection';
|
|
28
|
+
}
|
|
29
|
+
return 'browser-failure';
|
|
30
|
+
}
|
|
31
|
+
export class Diagnostics {
|
|
32
|
+
maxIssues;
|
|
33
|
+
maxRecords;
|
|
34
|
+
data = {
|
|
35
|
+
requests: 0,
|
|
36
|
+
skippedRequests: 0,
|
|
37
|
+
failedRequests: 0,
|
|
38
|
+
securityBlockedRequests: 0,
|
|
39
|
+
omittedRequests: 0,
|
|
40
|
+
responses: 0,
|
|
41
|
+
finished: 0,
|
|
42
|
+
failed: 0,
|
|
43
|
+
blocked: 0,
|
|
44
|
+
httpErrors: 0,
|
|
45
|
+
bytes: 0,
|
|
46
|
+
issueCount: 0,
|
|
47
|
+
dropped: 0,
|
|
48
|
+
issues: [],
|
|
49
|
+
};
|
|
50
|
+
phase = 'before-consent';
|
|
51
|
+
pending = new Map();
|
|
52
|
+
earlyFailures = new Map();
|
|
53
|
+
stopped = false;
|
|
54
|
+
phaseIssues = { 'before-consent': 0, 'after-reject': 0 };
|
|
55
|
+
constructor(maxIssues, maxRecords = 5_000) {
|
|
56
|
+
this.maxIssues = maxIssues;
|
|
57
|
+
this.maxRecords = maxRecords;
|
|
58
|
+
}
|
|
59
|
+
attach(context, records) {
|
|
60
|
+
context.on('request', (request) => {
|
|
61
|
+
if (this.stopped)
|
|
62
|
+
return;
|
|
63
|
+
const record = {
|
|
64
|
+
url: request.url(),
|
|
65
|
+
resourceType: request.resourceType(),
|
|
66
|
+
outcome: 'pending',
|
|
67
|
+
};
|
|
68
|
+
if (records.length < this.maxRecords)
|
|
69
|
+
records.push(record);
|
|
70
|
+
else {
|
|
71
|
+
this.data.omittedRequests++;
|
|
72
|
+
if (this.data.omittedRequests === 1)
|
|
73
|
+
this.add('resource-limit', request.url(), { limit: 'requests' });
|
|
74
|
+
}
|
|
75
|
+
const early = this.earlyFailures.get(request.url());
|
|
76
|
+
const issue = early?.shift();
|
|
77
|
+
if (early?.length === 0)
|
|
78
|
+
this.earlyFailures.delete(request.url());
|
|
79
|
+
this.pending.set(request, { record, phase: this.phase, ...(issue ? { issue } : {}) });
|
|
80
|
+
this.data.requests++;
|
|
81
|
+
});
|
|
82
|
+
context.on('response', (response) => {
|
|
83
|
+
if (this.stopped)
|
|
84
|
+
return;
|
|
85
|
+
const entry = this.pending.get(response.request());
|
|
86
|
+
if (entry === undefined)
|
|
87
|
+
return;
|
|
88
|
+
entry.record.outcome = 'response';
|
|
89
|
+
entry.record.status = response.status();
|
|
90
|
+
this.data.responses++;
|
|
91
|
+
if (response.status() >= 400) {
|
|
92
|
+
this.data.httpErrors++;
|
|
93
|
+
this.add('http-error', response.url(), { status: response.status() }, entry.phase);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
context.on('requestfinished', (request) => this.finish(request));
|
|
97
|
+
context.on('requestfailed', (request) => {
|
|
98
|
+
const entry = this.pending.get(request);
|
|
99
|
+
if (entry === undefined || this.stopped)
|
|
100
|
+
return;
|
|
101
|
+
entry.record.outcome = 'failed';
|
|
102
|
+
const issue = entry.issue ?? {
|
|
103
|
+
kind: classifyLoadError(request.failure()?.errorText),
|
|
104
|
+
url: diagnosticUrl(request.url()),
|
|
105
|
+
phase: entry.phase,
|
|
106
|
+
};
|
|
107
|
+
this.terminalFailure(issue.kind);
|
|
108
|
+
this.store(issue);
|
|
109
|
+
this.data.failed++;
|
|
110
|
+
this.pending.delete(request);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
finish(request) {
|
|
114
|
+
if (this.stopped || !this.pending.delete(request))
|
|
115
|
+
return;
|
|
116
|
+
this.data.finished++;
|
|
117
|
+
}
|
|
118
|
+
/** Defer storage until requestfailed to avoid counting adapter + browser errors twice. */
|
|
119
|
+
fail(request, kind, limit, skippedReason) {
|
|
120
|
+
const entry = this.pending.get(request);
|
|
121
|
+
if (entry === undefined)
|
|
122
|
+
return;
|
|
123
|
+
entry.issue = {
|
|
124
|
+
kind,
|
|
125
|
+
phase: entry.phase,
|
|
126
|
+
url: diagnosticUrl(request.url()),
|
|
127
|
+
...(limit === undefined ? {} : { limit }),
|
|
128
|
+
...(skippedReason === undefined ? {} : { skippedReason }),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
failUrl(url, kind, limit, skippedReason) {
|
|
132
|
+
if (this.stopped)
|
|
133
|
+
return;
|
|
134
|
+
for (const [request, entry] of this.pending) {
|
|
135
|
+
if (request.url() === url && entry.issue === undefined) {
|
|
136
|
+
this.fail(request, kind, limit, skippedReason);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// CDP can pause a request before Playwright emits it. Associate the reason on arrival.
|
|
141
|
+
const early = this.earlyFailures.get(url) ?? [];
|
|
142
|
+
early.push({
|
|
143
|
+
kind,
|
|
144
|
+
url: diagnosticUrl(url),
|
|
145
|
+
phase: this.phase,
|
|
146
|
+
...(limit === undefined ? {} : { limit }),
|
|
147
|
+
...(skippedReason === undefined ? {} : { skippedReason }),
|
|
148
|
+
});
|
|
149
|
+
this.earlyFailures.set(url, early);
|
|
150
|
+
}
|
|
151
|
+
add(kind, url, extra = {}, phase = this.phase) {
|
|
152
|
+
if (!this.stopped)
|
|
153
|
+
this.store({ kind, phase, url: diagnosticUrl(url), ...extra });
|
|
154
|
+
}
|
|
155
|
+
store(issue) {
|
|
156
|
+
this.phaseIssues[issue.phase]++;
|
|
157
|
+
this.data.issueCount++;
|
|
158
|
+
if (this.data.issues.length < this.maxIssues)
|
|
159
|
+
this.data.issues.push(issue);
|
|
160
|
+
else
|
|
161
|
+
this.data.dropped++;
|
|
162
|
+
}
|
|
163
|
+
hasIssues(phase) {
|
|
164
|
+
return this.phaseIssues[phase] > 0;
|
|
165
|
+
}
|
|
166
|
+
/** Freeze before closing the context: teardown errors are not resource failures. */
|
|
167
|
+
stop() {
|
|
168
|
+
if (this.stopped)
|
|
169
|
+
return;
|
|
170
|
+
for (const [request, entry] of this.pending) {
|
|
171
|
+
entry.record.outcome = 'failed';
|
|
172
|
+
const issue = entry.issue ?? {
|
|
173
|
+
kind: 'timeout',
|
|
174
|
+
phase: entry.phase,
|
|
175
|
+
url: diagnosticUrl(request.url()),
|
|
176
|
+
};
|
|
177
|
+
this.terminalFailure(issue.kind);
|
|
178
|
+
this.store(issue);
|
|
179
|
+
this.data.failed++;
|
|
180
|
+
}
|
|
181
|
+
this.pending.clear();
|
|
182
|
+
for (const issues of this.earlyFailures.values()) {
|
|
183
|
+
for (const issue of issues)
|
|
184
|
+
this.store(issue);
|
|
185
|
+
}
|
|
186
|
+
this.earlyFailures.clear();
|
|
187
|
+
this.stopped = true;
|
|
188
|
+
}
|
|
189
|
+
terminalFailure(kind) {
|
|
190
|
+
if (kind === 'security-blocked') {
|
|
191
|
+
this.data.blocked++;
|
|
192
|
+
this.data.securityBlockedRequests = (this.data.securityBlockedRequests ?? 0) + 1;
|
|
193
|
+
}
|
|
194
|
+
else if (['skipped', 'unsupported-method', 'unsupported-protocol'].includes(kind)) {
|
|
195
|
+
this.data.skippedRequests = (this.data.skippedRequests ?? 0) + 1;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
this.data.failedRequests = (this.data.failedRequests ?? 0) + 1;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
export { loadConfig, type PrivalintConfig, parseConfig } from './config.js';
|
|
2
|
+
export { type ConsentCheckOptions, observeConsent } from './consent.js';
|
|
3
|
+
export { assessCoverage, type CoverageAssessment, type CoverageIssue } from './coverage.js';
|
|
1
4
|
export { type Tracker, type TrackerCategory, trackers } from './data/trackers.js';
|
|
5
|
+
export { diagnosticUrl } from './diagnostics.js';
|
|
2
6
|
export { LANGS, type Lang, type Text } from './i18n.js';
|
|
3
7
|
export { legalReferences, REGIONS, type Region } from './legal.js';
|
|
8
|
+
export { type NetworkAdapter, NetworkError, type NetworkLimits, type NetworkRequest, type NetworkResponse, } from './network.js';
|
|
9
|
+
export { identifyReportSchema, REPORT_SCHEMA_VERSION, type ReportSchemaIdentity, SUPPORTED_REPORT_SCHEMAS, } from './report-contract.js';
|
|
4
10
|
export { defaultRules, googleFonts, impressumLink, preConsentTrackers, privacyPolicyLink, rejectOption, thirdPartyCdns, thirdPartyEmbeds, trackersAfterReject, } from './rules/index.js';
|
|
5
11
|
export { type ScanOptions, scan } from './scanner.js';
|
|
6
12
|
export type * from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
export { loadConfig, parseConfig } from './config.js';
|
|
2
|
+
export { observeConsent } from './consent.js';
|
|
3
|
+
export { assessCoverage } from './coverage.js';
|
|
1
4
|
export { trackers } from './data/trackers.js';
|
|
5
|
+
export { diagnosticUrl } from './diagnostics.js';
|
|
2
6
|
export { LANGS } from './i18n.js';
|
|
3
7
|
export { legalReferences, REGIONS } from './legal.js';
|
|
8
|
+
export { NetworkError, } from './network.js';
|
|
9
|
+
export { identifyReportSchema, REPORT_SCHEMA_VERSION, SUPPORTED_REPORT_SCHEMAS, } from './report-contract.js';
|
|
4
10
|
export { defaultRules, googleFonts, impressumLink, preConsentTrackers, privacyPolicyLink, rejectOption, thirdPartyCdns, thirdPartyEmbeds, trackersAfterReject, } from './rules/index.js';
|
|
5
11
|
export { scan } from './scanner.js';
|
|
6
12
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAwB,WAAW,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAA4B,cAAc,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,cAAc,EAA+C,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAsC,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAwB,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,OAAO,EAAe,MAAM,YAAY,CAAC;AACnE,OAAO,EAEL,YAAY,GAIb,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EAErB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { BrowserContext, Page } from 'playwright';
|
|
2
|
+
import { type Diagnostics } from './diagnostics.js';
|
|
3
|
+
import type { LoadDiagnostic, LoadIssueKind, SkipReason } from './types.js';
|
|
4
|
+
export interface NetworkRequest {
|
|
5
|
+
url: string;
|
|
6
|
+
method: string;
|
|
7
|
+
headers: Record<string, string>;
|
|
8
|
+
body: Uint8Array | null;
|
|
9
|
+
resourceType: string;
|
|
10
|
+
/** Covers execution and body consumption. The adapter must honour cancellation. */
|
|
11
|
+
signal: AbortSignal;
|
|
12
|
+
}
|
|
13
|
+
export interface NetworkResponse {
|
|
14
|
+
status: number;
|
|
15
|
+
headers?: Record<string, string | string[]>;
|
|
16
|
+
/** Stream bodies to enforce byte limits before buffering the entire response. */
|
|
17
|
+
body?: string | Uint8Array | AsyncIterable<Uint8Array>;
|
|
18
|
+
}
|
|
19
|
+
/** Fetch exactly ONE HTTP hop, never follow redirects. Caller owns shared transport clients. */
|
|
20
|
+
export type NetworkAdapter = (request: NetworkRequest) => Promise<NetworkResponse>;
|
|
21
|
+
export interface NetworkLimits {
|
|
22
|
+
concurrency?: number;
|
|
23
|
+
maxRequests?: number;
|
|
24
|
+
maxResponseBytes?: number;
|
|
25
|
+
maxTotalBytes?: number;
|
|
26
|
+
maxRedirects?: number;
|
|
27
|
+
/** Starts on dequeue; queue wait is bounded separately by captureTimeoutMs. */
|
|
28
|
+
requestTimeoutMs?: number;
|
|
29
|
+
}
|
|
30
|
+
export declare const NETWORK_DEFAULTS: {
|
|
31
|
+
concurrency: number;
|
|
32
|
+
maxRequests: number;
|
|
33
|
+
maxResponseBytes: number;
|
|
34
|
+
maxTotalBytes: number;
|
|
35
|
+
maxRedirects: number;
|
|
36
|
+
requestTimeoutMs: number;
|
|
37
|
+
};
|
|
38
|
+
export declare class NetworkError extends Error {
|
|
39
|
+
readonly kind: Exclude<LoadIssueKind, 'http-error'>;
|
|
40
|
+
readonly limit?: LoadDiagnostic['limit'];
|
|
41
|
+
readonly skippedReason?: SkipReason | undefined;
|
|
42
|
+
constructor(kind: Exclude<LoadIssueKind, 'http-error'>, limit?: LoadDiagnostic['limit'], skippedReason?: SkipReason | undefined);
|
|
43
|
+
}
|
|
44
|
+
export declare function networkLimits(options?: NetworkLimits): Required<NetworkLimits>;
|
|
45
|
+
/** Chromium Fetch interception includes redirect hops that Playwright route() auto-continues. */
|
|
46
|
+
export declare class ControlledNetwork {
|
|
47
|
+
private readonly adapter;
|
|
48
|
+
private readonly limits;
|
|
49
|
+
private readonly diagnostics;
|
|
50
|
+
private readonly signal;
|
|
51
|
+
private readonly queue;
|
|
52
|
+
private readonly tasks;
|
|
53
|
+
private readonly sessions;
|
|
54
|
+
private active;
|
|
55
|
+
private admitted;
|
|
56
|
+
private closed;
|
|
57
|
+
constructor(adapter: NetworkAdapter, limits: Required<NetworkLimits>, diagnostics: Diagnostics, signal: AbortSignal);
|
|
58
|
+
attach(context: BrowserContext): Promise<void>;
|
|
59
|
+
attachPage(page: Page): Promise<void>;
|
|
60
|
+
private intercept;
|
|
61
|
+
private pump;
|
|
62
|
+
private handle;
|
|
63
|
+
private readBody;
|
|
64
|
+
private abort;
|
|
65
|
+
close(): Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
/** Abort without retaining caller reasons or leaving listeners attached. */
|
|
68
|
+
export declare function withSignal<T>(operation: Promise<T>, signal: AbortSignal): Promise<T>;
|
package/dist/network.js
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { classifyLoadError } from './diagnostics.js';
|
|
2
|
+
export const NETWORK_DEFAULTS = {
|
|
3
|
+
concurrency: 6,
|
|
4
|
+
maxRequests: 500,
|
|
5
|
+
maxResponseBytes: 5 * 1024 * 1024,
|
|
6
|
+
maxTotalBytes: 20 * 1024 * 1024,
|
|
7
|
+
maxRedirects: 10,
|
|
8
|
+
requestTimeoutMs: 10_000,
|
|
9
|
+
};
|
|
10
|
+
export class NetworkError extends Error {
|
|
11
|
+
kind;
|
|
12
|
+
limit;
|
|
13
|
+
skippedReason;
|
|
14
|
+
constructor(kind, limit, skippedReason) {
|
|
15
|
+
super(kind);
|
|
16
|
+
this.kind = kind;
|
|
17
|
+
this.limit = limit;
|
|
18
|
+
this.skippedReason = skippedReason;
|
|
19
|
+
this.name = 'NetworkError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function networkLimits(options = {}) {
|
|
23
|
+
const limits = { ...NETWORK_DEFAULTS, ...options };
|
|
24
|
+
for (const [key, value] of Object.entries(limits)) {
|
|
25
|
+
const min = key === 'maxRedirects' ? 0 : 1;
|
|
26
|
+
if (!Number.isSafeInteger(value) || value < min)
|
|
27
|
+
throw new RangeError(`${key} must be a safe integer of at least ${min}`);
|
|
28
|
+
}
|
|
29
|
+
return limits;
|
|
30
|
+
}
|
|
31
|
+
function requestBody(request) {
|
|
32
|
+
if (request.postDataEntries !== undefined) {
|
|
33
|
+
if (request.postDataEntries.some((entry) => entry.bytes === undefined)) {
|
|
34
|
+
throw new NetworkError('unsupported-method');
|
|
35
|
+
}
|
|
36
|
+
return Buffer.concat(request.postDataEntries.map((entry) => Buffer.from(entry.bytes ?? '', 'base64')));
|
|
37
|
+
}
|
|
38
|
+
if (request.postData !== undefined)
|
|
39
|
+
return Buffer.from(request.postData);
|
|
40
|
+
if (request.hasPostData)
|
|
41
|
+
throw new NetworkError('unsupported-method');
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
function failureKind(error, signal, timeout) {
|
|
45
|
+
if (signal.aborted) {
|
|
46
|
+
return signal.reason instanceof DOMException && signal.reason.name === 'TimeoutError'
|
|
47
|
+
? 'timeout'
|
|
48
|
+
: 'aborted';
|
|
49
|
+
}
|
|
50
|
+
if (timeout.aborted)
|
|
51
|
+
return 'timeout';
|
|
52
|
+
return error instanceof NetworkError ? error.kind : classifyLoadError(error);
|
|
53
|
+
}
|
|
54
|
+
/** Chromium Fetch interception includes redirect hops that Playwright route() auto-continues. */
|
|
55
|
+
export class ControlledNetwork {
|
|
56
|
+
adapter;
|
|
57
|
+
limits;
|
|
58
|
+
diagnostics;
|
|
59
|
+
signal;
|
|
60
|
+
queue = [];
|
|
61
|
+
tasks = new Set();
|
|
62
|
+
sessions = new Map();
|
|
63
|
+
active = 0;
|
|
64
|
+
admitted = 0;
|
|
65
|
+
closed = false;
|
|
66
|
+
constructor(adapter, limits, diagnostics, signal) {
|
|
67
|
+
this.adapter = adapter;
|
|
68
|
+
this.limits = limits;
|
|
69
|
+
this.diagnostics = diagnostics;
|
|
70
|
+
this.signal = signal;
|
|
71
|
+
}
|
|
72
|
+
async attach(context) {
|
|
73
|
+
context.on('page', (page) => {
|
|
74
|
+
void this.attachPage(page).catch(() => this.diagnostics.add('browser-failure', page.url()));
|
|
75
|
+
});
|
|
76
|
+
await context.routeWebSocket('**/*', (socket) => {
|
|
77
|
+
this.diagnostics.add('unsupported-protocol', socket.url());
|
|
78
|
+
socket.close();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
attachPage(page) {
|
|
82
|
+
const existing = this.sessions.get(page);
|
|
83
|
+
if (existing)
|
|
84
|
+
return existing;
|
|
85
|
+
const attaching = this.intercept(page);
|
|
86
|
+
this.sessions.set(page, attaching);
|
|
87
|
+
return attaching;
|
|
88
|
+
}
|
|
89
|
+
async intercept(page) {
|
|
90
|
+
const session = await page.context().newCDPSession(page);
|
|
91
|
+
const redirects = new Map();
|
|
92
|
+
session.on('Fetch.requestPaused', (event) => {
|
|
93
|
+
const count = event.redirectedRequestId
|
|
94
|
+
? (redirects.get(event.redirectedRequestId) ?? 0) + 1
|
|
95
|
+
: 0;
|
|
96
|
+
if (event.redirectedRequestId)
|
|
97
|
+
redirects.delete(event.redirectedRequestId);
|
|
98
|
+
const request = { event, session, redirects: count, redirectCounts: redirects };
|
|
99
|
+
if (this.closed || this.signal.aborted) {
|
|
100
|
+
void this.abort(request, 'aborted');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this.admitted++;
|
|
104
|
+
if (this.admitted > this.limits.maxRequests) {
|
|
105
|
+
void this.abort(request, 'resource-limit', 'requests');
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
this.queue.push(request);
|
|
109
|
+
this.pump();
|
|
110
|
+
});
|
|
111
|
+
await session.send('Fetch.enable', {
|
|
112
|
+
patterns: [{ urlPattern: '*', requestStage: 'Request' }],
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
pump() {
|
|
116
|
+
while (!this.closed && !this.signal.aborted && this.active < this.limits.concurrency) {
|
|
117
|
+
const request = this.queue.shift();
|
|
118
|
+
if (request === undefined)
|
|
119
|
+
return;
|
|
120
|
+
this.active++;
|
|
121
|
+
const task = this.handle(request).finally(() => {
|
|
122
|
+
this.active--;
|
|
123
|
+
this.tasks.delete(task);
|
|
124
|
+
this.pump();
|
|
125
|
+
});
|
|
126
|
+
this.tasks.add(task);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async handle(intercepted) {
|
|
130
|
+
const { event, session, redirects, redirectCounts } = intercepted;
|
|
131
|
+
const { request } = event;
|
|
132
|
+
const controller = new AbortController();
|
|
133
|
+
const timeout = AbortSignal.timeout(this.limits.requestTimeoutMs);
|
|
134
|
+
const signal = AbortSignal.any([this.signal, timeout, controller.signal]);
|
|
135
|
+
try {
|
|
136
|
+
if (!/^https?:$/.test(new URL(request.url).protocol))
|
|
137
|
+
throw new NetworkError('unsupported-protocol');
|
|
138
|
+
if (redirects > this.limits.maxRedirects)
|
|
139
|
+
throw new NetworkError('resource-limit', 'redirects');
|
|
140
|
+
if (this.diagnostics.data.bytes >= this.limits.maxTotalBytes)
|
|
141
|
+
throw new NetworkError('resource-limit', 'total-bytes');
|
|
142
|
+
const response = await withSignal(this.adapter({
|
|
143
|
+
url: request.url,
|
|
144
|
+
method: request.method,
|
|
145
|
+
headers: request.headers,
|
|
146
|
+
body: requestBody(request),
|
|
147
|
+
resourceType: event.resourceType.toLowerCase(),
|
|
148
|
+
signal,
|
|
149
|
+
}), signal);
|
|
150
|
+
const body = await this.readBody(response.body, signal);
|
|
151
|
+
signal.throwIfAborted();
|
|
152
|
+
if (!Number.isInteger(response.status) || response.status < 200 || response.status > 599)
|
|
153
|
+
throw new NetworkError('browser-failure');
|
|
154
|
+
if ([301, 302, 303, 307, 308].includes(response.status))
|
|
155
|
+
redirectCounts.set(event.requestId, redirects);
|
|
156
|
+
await session.send('Fetch.fulfillRequest', {
|
|
157
|
+
requestId: event.requestId,
|
|
158
|
+
responseCode: response.status,
|
|
159
|
+
responseHeaders: Object.entries(response.headers ?? {}).flatMap(([name, value]) => (Array.isArray(value) ? value : [value]).map((item) => ({ name, value: item }))),
|
|
160
|
+
body: body.toString('base64'),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
const kind = failureKind(error, this.signal, timeout);
|
|
165
|
+
await this.abort(intercepted, kind, error instanceof NetworkError ? error.limit : undefined, error instanceof NetworkError ? error.skippedReason : undefined);
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
controller.abort();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async readBody(body, signal) {
|
|
172
|
+
const chunks = [];
|
|
173
|
+
let size = 0;
|
|
174
|
+
const append = (chunk) => {
|
|
175
|
+
size += chunk.byteLength;
|
|
176
|
+
this.diagnostics.data.bytes += chunk.byteLength;
|
|
177
|
+
if (size > this.limits.maxResponseBytes)
|
|
178
|
+
throw new NetworkError('resource-limit', 'response-bytes');
|
|
179
|
+
if (this.diagnostics.data.bytes > this.limits.maxTotalBytes)
|
|
180
|
+
throw new NetworkError('resource-limit', 'total-bytes');
|
|
181
|
+
chunks.push(chunk);
|
|
182
|
+
};
|
|
183
|
+
if (body === undefined)
|
|
184
|
+
return Buffer.alloc(0);
|
|
185
|
+
if (typeof body === 'string' || body instanceof Uint8Array) {
|
|
186
|
+
append(typeof body === 'string' ? Buffer.from(body) : body);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
const iterator = body[Symbol.asyncIterator]();
|
|
190
|
+
try {
|
|
191
|
+
while (true) {
|
|
192
|
+
const chunk = await withSignal(iterator.next(), signal);
|
|
193
|
+
if (chunk.done)
|
|
194
|
+
break;
|
|
195
|
+
append(chunk.value);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
void iterator.return?.().catch(() => { });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return Buffer.concat(chunks, size);
|
|
203
|
+
}
|
|
204
|
+
async abort(request, kind, limit, skippedReason) {
|
|
205
|
+
this.diagnostics.failUrl(request.event.request.url, kind, limit, skippedReason);
|
|
206
|
+
await request.session
|
|
207
|
+
.send('Fetch.failRequest', {
|
|
208
|
+
requestId: request.event.requestId,
|
|
209
|
+
errorReason: 'BlockedByClient',
|
|
210
|
+
})
|
|
211
|
+
.catch(() => { });
|
|
212
|
+
}
|
|
213
|
+
async close() {
|
|
214
|
+
this.closed = true;
|
|
215
|
+
await Promise.all(this.queue.splice(0).map((request) => this.abort(request, 'aborted')));
|
|
216
|
+
await Promise.all(this.tasks);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/** Abort without retaining caller reasons or leaving listeners attached. */
|
|
220
|
+
export async function withSignal(operation, signal) {
|
|
221
|
+
if (signal.aborted) {
|
|
222
|
+
void operation.catch(() => { });
|
|
223
|
+
throw new DOMException('Operation aborted', 'AbortError');
|
|
224
|
+
}
|
|
225
|
+
let onAbort = () => { };
|
|
226
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
227
|
+
onAbort = () => reject(new DOMException('Operation aborted', 'AbortError'));
|
|
228
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
229
|
+
});
|
|
230
|
+
try {
|
|
231
|
+
return await Promise.race([operation, aborted]);
|
|
232
|
+
}
|
|
233
|
+
finally {
|
|
234
|
+
signal.removeEventListener('abort', onAbort);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Legacy records remain valid; failed, pending and HTTP-error responses are not loaded vendors. */
|
|
2
|
+
export const observedRequests = (requests) => requests.filter((request) => request.outcome === undefined ||
|
|
3
|
+
(request.outcome === 'response' && (request.status ?? 200) < 400));
|
|
4
|
+
//# sourceMappingURL=observations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observations.js","sourceRoot":"","sources":["../src/observations.ts"],"names":[],"mappings":"AAEA,oGAAoG;AACpG,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAoC,EAAqB,EAAE,CAC1F,QAAQ,CAAC,MAAM,CACb,CAAC,OAAO,EAAE,EAAE,CACV,OAAO,CAAC,OAAO,KAAK,SAAS;IAC7B,CAAC,OAAO,CAAC,OAAO,KAAK,UAAU,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,CACpE,CAAC"}
|
package/dist/policy.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Finding, Rule, RuleSettings } from './types.js';
|
|
2
|
+
export declare function validateRuleSettings(settings: RuleSettings, rules: readonly Rule[]): void;
|
|
3
|
+
/** Inherited properties such as constructor must never become severity overrides. */
|
|
4
|
+
export declare function ruleSetting(settings: RuleSettings | undefined, ruleId: string): RuleSettings[string] | undefined;
|
|
5
|
+
/** Apply local policy after region classification. Allowed vendors stay visible as info. */
|
|
6
|
+
export declare function applyPolicy(findings: readonly Finding[], settings?: RuleSettings, allowedVendors?: readonly string[]): Finding[];
|