【解決方法】next.jsで外部ドメインの画像を呼び出した際に発生したCSPエラー回避の対応

Next.jsセキュリティーエラー解消express
【解決方法】next.jsで外部ドメインの画像を呼び出した際に発生したCSPエラー回避の対応
Memo
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

next.jsで外部ドメインの画像を呼び出した際に発生したCSPエラーを回避するための対応をメモしました。

経緯

next.jsのバージョンを10にあげたのと合わせて関連ライブラリのアップデートをこなった際に
外部ドメインからの画像呼び出しがCSPエラーとなり画像が表示されなくなってしまったことがきっかけになります。

環境

  • next 9.1.1 → 10.2.3
  • node 14.15.3
  • express 4.17.1
  • helmet 3.21.1 → 4.6.0

発生したエラー

CSPに違反しているため、画像 '' のロードを拒否しましたというエラーが発生しています。

CSP(セキュリティポリシーディレクティブ)エラー

Refused to load the image '<URL>' because it violates the following Content Security Policy directive: "img-src 'self' data:".

画像呼び出しもとのHTMLタグ

imgタグで外部ドメインを指定して呼び出しを行なっています。

<img src="http://subdomain.t-cr.jp/smpale.jpg" />

CSPヘッダーへ追記して解決

CSPヘッダーへ指定ドメインの設定を追記することで解決できました。

next.jsの構成

next.jsの構成としてSSR(サーバーサイドレンダリング)をexpressで行ってます。
またexpressのセキュリティー設定としてhelmetを入れているためhelmetの設定で対応しました。

helmetの設定

helmetの設定を追記

今回は'self'ドメインを追加しました。

server/index.js
import helmet from "helmet"; import express from "express"; import next from "next"; const nextServer = next(); nextServer.prepare().then(() => { const app = express(); app.use( helmet.contentSecurityPolicy({ useDefaults: true, directives: { "img-src": ["'self'", "static.t-cr.jp"] } }) ); })

helmetの設定

ここでimg-srcへ追記しています。

    helmet.contentSecurityPolicy({
      useDefaults: true,
      directives: {
        "img-src": ["'self'", "static.t-cr.jp"]
      }
    })

必要に応じてhttps:data:などをあけてあげてください。

個別でCSPヘッダーを指定

helmetではなく個別でCSPヘッダーを指定する場合はexpress-csp-headerで設定できます。

express-csp-headerの設定

app.useでexpressCspHeaderの設定を渡してあげます。

server/index.js
import { expressCspHeader, SELF } from 'express-csp-header'; import express from "express"; import next from "next"; const nextServer = next(); nextServer.prepare().then(() => { const app = express(); app.use(expressCspHeader({ directives: { 'img-src': [SELF, 'subdomain.t-cr.jp'] } })); })

終わりに

最後までご覧いただきありがとうございます。
この記事では【解決方法】next.jsで外部ドメインの画像を呼び出した際に発生したCSPエラー回避の対応について紹介させていただきました。

これからも皆様の開発に役立つ情報を提供していきたいと考えています。
今後ともよろしくお願いいたします。