Simplified CSP HTTP header injection, avoiding report-to until actually supported by browsers.
This commit is contained in:
parent
c9c7b7aefe
commit
209d50b0c1
|
@ -1,6 +1,13 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function ReportingCSP(reportURI, reportGroup) {
|
function ReportingCSP(reportURI, reportGroup) {
|
||||||
|
const REPORT_TO_SUPPORTED = false;
|
||||||
|
// TODO: figure out if we're running on a browser supporting the report-to
|
||||||
|
// CSP directive, breaking report-uri, see
|
||||||
|
// 1. https://www.w3.org/TR/CSP3/#directive-report-uri
|
||||||
|
// 2. https://bugs.chromium.org/p/chromium/issues/detail?id=726634
|
||||||
|
// 3. https://bugzilla.mozilla.org/show_bug.cgi?id=1391243
|
||||||
|
|
||||||
const REPORT_TO = {
|
const REPORT_TO = {
|
||||||
name: "Report-To",
|
name: "Report-To",
|
||||||
value: JSON.stringify({ "url": reportURI,
|
value: JSON.stringify({ "url": reportURI,
|
||||||
|
@ -9,31 +16,32 @@ function ReportingCSP(reportURI, reportGroup) {
|
||||||
};
|
};
|
||||||
return Object.assign(
|
return Object.assign(
|
||||||
new CapsCSP(new NetCSP(
|
new CapsCSP(new NetCSP(
|
||||||
`report-uri ${reportURI};`,
|
REPORT_TO_SUPPORTED ? `;report-to ${reportGroup};`
|
||||||
`;report-to ${reportGroup};`
|
: `report-uri ${reportURI};`
|
||||||
)),
|
)),
|
||||||
{
|
{
|
||||||
reportURI,
|
reportURI,
|
||||||
reportGroup,
|
reportGroup,
|
||||||
patchHeaders(responseHeaders, capabilities) {
|
patchHeaders(responseHeaders, capabilities) {
|
||||||
let header = null;
|
let header = null;
|
||||||
let hasReportTo = false;
|
let needsReportTo = REPORT_TO_SUPPORTED;
|
||||||
for (let h of responseHeaders) {
|
for (let h of responseHeaders) {
|
||||||
if (this.isMine(h)) {
|
if (this.isMine(h)) {
|
||||||
header = h;
|
header = h;
|
||||||
h.value = this.inject(h.value, "");
|
h.value = "";
|
||||||
} else if (h.name === REPORT_TO.name && h.value === REPORT_TO.value) {
|
} else if (needsReportTo &&
|
||||||
hasReportTo = true;
|
h.name === REPORT_TO.name && h.value === REPORT_TO.value) {
|
||||||
|
needsReportTo = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let blocker = capabilities && this.buildFromCapabilities(capabilities);
|
let blocker = capabilities && this.buildFromCapabilities(capabilities);
|
||||||
if (blocker) {
|
if (blocker) {
|
||||||
if (!hasReportTo) {
|
if (needsReportTo) {
|
||||||
responseHeaders.push(REPORT_TO);
|
responseHeaders.push(REPORT_TO);
|
||||||
}
|
}
|
||||||
if (header) {
|
if (header) {
|
||||||
header.value = this.inject(header.value, blocker);
|
header.value = blocker;
|
||||||
} else {
|
} else {
|
||||||
header = this.asHeader(blocker);
|
header = this.asHeader(blocker);
|
||||||
responseHeaders.push(header);
|
responseHeaders.push(header);
|
||||||
|
|
|
@ -1,30 +1,18 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
class NetCSP extends CSP {
|
class NetCSP extends CSP {
|
||||||
constructor(start, end) {
|
constructor(start) {
|
||||||
super();
|
super();
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isMine(header) {
|
isMine(header) {
|
||||||
let {name, value} = header;
|
let {name, value} = header;
|
||||||
if (name.toLowerCase() !== CSP.headerName) return false;
|
return name.toLowerCase() === CSP.headerName && value.startsWith(this.start);
|
||||||
let startIdx = value.indexOf(this.start);
|
|
||||||
return startIdx > -1 && startIdx < value.lastIndexOf(this.end);
|
|
||||||
}
|
|
||||||
|
|
||||||
inject(headerValue, mine) {
|
|
||||||
let startIdx = headerValue.indexOf(this.start);
|
|
||||||
if (startIdx < 0) return `${headerValue};${mine}`;
|
|
||||||
let endIdx = headerValue.lastIndexOf(this.end);
|
|
||||||
let retValue = `${headerValue.substring(0, startIdx)}${mine}`;
|
|
||||||
|
|
||||||
return endIdx < 0 ? retValue : `${retValue}${headerValue.substring(endIdx + this.end.length + 1)}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
build(...directives) {
|
build(...directives) {
|
||||||
return `${this.start}${super.build(...directives)}${this.end}`;
|
return `${this.start}${super.build(...directives)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup(headers) {
|
cleanup(headers) {
|
||||||
|
|
Loading…
Reference in New Issue