content-security-policy - Can't parser content of the CSP report
问题描述
I'm sending a CSP-report via report-to
directive:
app.use(express.json({
type: [
"application/json",
"application/csp-report",
"application/reports+json"
]
}));
const _reportCSP = {
endpoints: [
{
url: "https://myapp.com/reportCSP"
}
],
group: "csp-endpoint",
include_subdomains: true,
max_age: 31536000
};
res.setHeader("content-security-policy", `default-src 'none'; script-src https://*.someHost.com 'self' 'unsafe-eval' 'unsafe-inline'; style-src https://*.someHost.com 'self'; font-src https://*.someHost.com 'self'; img-src 'self'; connect-src https://*.someHost.com https://*.dropboxapi.co 'self'; frame-ancestors 'none'; report-to ${reportCSP.group};`);
res.setHeader("report-to", JSON.stringify(reportCSP));
An URL https://*.dropboxapi.co
is used for the CSP-reports testing purposes only.
Based on this sample, I handle a CSP-report request in the following manner:
function echoReports(request, response) {
for (const report of request.body) {
console.log(`Report content: ${report}`);
console.log(`Report content: ${JSON.stringify(report)}`);
}
}
app.post("/reportCSP",
async (req, res) => {
console.log(`${req.body.length} CSP violation reports:`);
echoReports(req, res);
}
);
As a result, I get on a server-side:
1 CSP violation reports:
Report content: [object Object]
Report content: "[object Object]"
In DevTools I see the correct error report:
Refused to connect to 'https://content.dropboxapi.com/…' because it violates the following Content Security Policy directive: "connect-src https://*.someHost.com https://*.dropboxapi.co 'self'"
Refused to connect to 'https://content.dropboxapi.com/…' because it violates the document's Content Security Policy.
JSON.stringify(request)
inside of echoReports(req, res)
leads to:
TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Socket'
| property 'parser' -> object with constructor 'HTTPParser'
--- property 'socket' closes the circle
at JSON.stringify (<anonymous>)
at echoReports (file:///app/src/server/app.mjs:2949:33)
Since I'm on Express.js 4.17.1, I don't use body-parser
but use express.json(…)
instead.
I've tried several approaches to print a content of the CSP-report on the server-side but no success.
Of course, any anti-banner, security and privacy protection software had been deactivated.
P.S. I've elaborated the question to make it more clear what's the problem I'm trying to solve.
解决方案
Check that the browser receives the
Report-To
HTTP header, the guide is here.Check network log using the
chrome://net-export/
andhttps://netlog-viewer.appspot.com
tools:
- For latest Chrome versions open the
chrome://net-export
page on a separate tab and enable recording of network log to disk. - Reload the tab with the page which publishes the
Report-To
header. - Stop recording of network log to disk with the
<Stop logging>
button at thechrome://net-export
page. - Open the
https://netlog-viewer.appspot.com
log viewer on a separate tab, and select the file of your log. - Select "Reports" in the left menu, and in the "Queued reports" section, click on the link "Show raw report". You'll see CSP reports created and queued or empty section if all reports have been sent.
Also have a look at the bottom of the "Per-origin config" table: In the "Uploads" column the number of sent reports will be indicated.
A complete step-by-step guide is here
The page itself that publishes a
Report-To
header must be loaded with HTTPS:, otherwise reports will not be sent. Endpoint's Url should be HTTPS: too.Note if you site works behind Cloudflare, the
Report-To
header will not work property.
update
It seems that this code snippet:
app.post("/policyViolationReport",
async (req) => {
console.log("Bingo! CSP Report occurred.");
});
will not receive violation reports because violation reports are not sended as an ordinary POST data (i.e. ¶m=value
). Browser sends just body of JSON.
Try to use this:
app.use(
bodyParser.json({
type: ['application/json', 'application/csp-report', 'application/reports+json'],
})
);
app.post('/policyViolationReport', (req, res) => {
console.log(req.body);
res.status(204).end();
});
推荐阅读
- django - 如何根据 Django ModelViewSet 中的另一个模型进行过滤?
- python - 如何在使用 tensorflow 2.5 时在 M1 mac 上运行 talib
- ssl - 无法对 Godaddy 域的 github 页面强制执行 https
- mysql - SQL 查询基于一个范围加上第一个之前的一行 #2
- python - Selenium Python:ElementNotInteractableException:对象没有大小和位置
- azure - 哪个 Azure 区域离我最近?
- kendo-ui - 如果剑道 UI 网格模板中的条件
- javascript - Socket.emit 仅在重新加载页面后有效
- sql-server - 随着时间的推移,SQL Server 对 GETDATE() 的结果是否有任何一致性?
- web-scraping - python抓取谷歌,获取requests.Response obj未知编码,无法读取任何内容所有内容都已加密