概要
htmlのmetaタグにCSPを記述してもレスポンスヘッダー側のCSPが優先される。
CSPで問題が発生したらまずブラウザのレスポンスヘッダーを確認しましょう。
人様のミドルウェアを使うときはきちんとドキュメントを読もう。
発生した問題
GCP上(GAE/CloudFirestore/CloudStorage)で動くExpress.js+Vue.jsなWebアプリを趣味で製作していたときのこと、HTML上でCSPを記述しているのにGoogle アナリティクスが読み込めないという不具合が発生。ローカルで動かしていた分には発生しなかったが、GAE上にデプロイすると読み込めなくなる
とりあえずmetaタグに書く
そもそもCSPとは
コンテンツセキュリティポリシー (CSP) - HTTP | MDN
HTML上からアクセスできるリソース、通信先を明示してセキュリティを保つ仕組みらしい。
記述方法は2種類あり(ここ大事)
httpレスポンスヘッダ
html上のmetaタグ
に書けばいいらしい。とりあえず楽に対応できそうなmetaタグでの対応を試みた。
index.html
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https:; script-src-elem https://www.googletagmanager.com">
</head>
しかし変化がない。というかエラーメッセージ上では記述した内容が反映されていない。コンソール曰く
because it violates the following Content Security Policy directive: "script-src 'self'".
Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
レスポンスヘッダーを見る
空白の入れ方を変えたり、GAEの静的ファイルにレスポンスヘッダをつけたり色々やったが改善せず、悶々としていたところでふとレスポンスヘッダの中身を確認したことがないという事に気づく。
見てみるとかなり厳しい内容になっててワロタ。
// helmetの公式ドキュメントから抜粋。だいたいこんな感じだった。
default-src 'self';
base-uri 'self';
block-all-mixed-content;
font-src 'self' https: data:;
frame-ancestors 'self';
img-src 'self' data:;
object-src 'none';
script-src 'self';
script-src-attr 'none';
style-src 'self' https: 'unsafe-inline';
upgrade-insecure-requests
helmetの設定変更
原因はExpress.jsに導入していたhelmetというミドルウェア。Express.jsの公式Webサイトでも紹介されているミドルウェアで、セキュリティを色々強化してくれる。
紹介ページにはこのような記述
Helmet は、実際には、セキュリティー関連の HTTP ヘッダーを設定する 9 個の小さなミドルウェア関数の単なる集合です。
- csp は、クロスサイト・スクリプティング攻撃やその他のクロスサイト・インジェクションを防止するために Content-Security-Policy ヘ> ッダーを設定します。
これです。対処方法としてはcspを無効化して、metaタグ側のcspを読み込ませるか、自分で記述すればいい。
app.ts
// これだと全部有効になるので
app.use(helmet())
// cspミドルウェアだけを無効にする
app.use(
helmet({
contentSecurityPolicy: false,
})
);
作っているWebアプリ
なんか他のリプレイアップローダーが全滅してしまったので作ってます。(タイトルの文字化けは面白いのでしばらく放置)
↧