Skip to content

Commit d8332ad

Browse files
committed
Force CSP inheritance for redirections to data: URIs on Gecko pre-69.
1 parent c44ab6f commit d8332ad

3 files changed

Lines changed: 41 additions & 8 deletions

File tree

src/bg/ReportingCSP.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,25 @@ function ReportingCSP(reportURI, reportGroup) {
2525
patchHeaders(responseHeaders, capabilities) {
2626
let header = null;
2727
let needsReportTo = REPORT_TO_SUPPORTED;
28+
29+
let blocker = capabilities && this.buildFromCapabilities(capabilities);
2830
for (let h of responseHeaders) {
2931
if (this.isMine(h)) {
3032
header = h;
3133
h.value = "";
3234
} else if (needsReportTo &&
3335
h.name === REPORT_TO.name && h.value === REPORT_TO.value) {
3436
needsReportTo = false;
37+
} else if (blocker && /^(Location|Refresh)$/i.test(h.name)) {
38+
let url = /^R/i.test(h.name)
39+
? h.value.replace(/^[^,;]*[,;]url[^\w=]*=\s*/i, "") : h.value;
40+
let patched = CSP.patchDataURI(url, blocker);
41+
if (patched !== url) {
42+
h.value = h.value.slice(0, -url.length) + patched;
43+
}
3544
}
3645
}
3746

38-
let blocker = capabilities && this.buildFromCapabilities(capabilities);
3947
if (blocker) {
4048
if (needsReportTo) {
4149
responseHeaders.push(REPORT_TO);

src/bg/RequestGuard.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,10 @@ var RequestGuard = (() => {
305305
normalizeRequest(request);
306306
try {
307307
let redirected = initPendingRequest(request);
308-
let {policy} = ns;
309-
let policyType = policyTypesMap[request.type];
310-
if (policyType) {
308+
let {policy} = ns
309+
let {type} = request;
310+
if (type in policyTypesMap) {
311+
let policyType = policyTypesMap[type];
311312
let {url, originUrl, documentUrl, tabId} = request;
312313
let isFetch = "fetch" === policyType;
313314

@@ -327,7 +328,7 @@ var RequestGuard = (() => {
327328

328329
if (/^(?:data|blob):/.test(url)) {
329330
request._dataUrl = url;
330-
request.url = url = documentUrl;
331+
request.url = url = documentUrl || originUrl;
331332
}
332333

333334
let allowed = Sites.isInternal(url);
@@ -340,10 +341,19 @@ var RequestGuard = (() => {
340341
allowed = !ns.isEnforced(tabId);
341342
}
342343
if (!allowed) {
343-
allowed = intersectCapabilities(
344+
let capabilities = intersectCapabilities(
344345
policy.get(url, documentUrl).perms,
345-
request
346-
).has(policyType);
346+
request);
347+
allowed = !policyType || capabilities.has(policyType);
348+
if (allowed && request._dataUrl && type.endsWith("frame")) {
349+
let blocker = csp.buildFromCapabilities(capabilities);
350+
if (blocker) {
351+
let redirectUrl = CSP.patchDataURI(request._dataUrl, blocker);
352+
if (redirectUrl !== request._dataUrl) {
353+
return {redirectUrl};
354+
}
355+
}
356+
}
347357
}
348358
}
349359
Content.reportTo(request, allowed, policyType);

src/lib/CSP.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,18 @@ class CSP {
2121

2222
CSP.isEmbedType = type => /\b(?:application|video|audio)\b/.test(type) && type !== "application/xhtml+xml";
2323
CSP.headerName = "content-security-policy";
24+
CSP.patchDataURI = (uri, blocker) => {
25+
let parts = /^data:(?:[^,;]*ml)(;[^,]*)?,/i.exec(uri);
26+
if (!(blocker && parts)) {
27+
// not an interesting data: URI, return as it is
28+
return uri;
29+
}
30+
if (parts[1]) {
31+
// extra encoding info, let's bailout (better safe than sorry)
32+
return "data:";
33+
}
34+
// It's a HTML/XML page, let's prepend our CSP blocker to the document
35+
let patch = parts[0] + encodeURIComponent(
36+
`<meta http-equiv="${CSP.headerName}" content="${blocker}">`);
37+
return uri.startsWith(patch) ? uri : patch + uri.substring(parts[0].length);
38+
}

0 commit comments

Comments
 (0)