---
title: セキュリティ
description: HTTPS とセキュリティヘッダー、CSP、公開ディレクトリに置かないファイル、XSS を防ぐ DOM 操作、フォームの入力検証とスパム対策
---

Web サイトの制作で必要になる、基本的なセキュリティ対策をまとめています。
外部ライブラリの選び方と CDN から読み込むときの SRI は[ライブラリの利用](/frontend/js/libraries)、機密情報の管理は [GitHub 権限・セキュリティ](/git/security)を参照してください。

## HTTPS

すべてのページを HTTPS で配信し、HTTP へのアクセスは HTTPS へ 301 リダイレクトします。
ページ内で読み込む画像・スクリプト・フォームの送信先も、すべて `https://` にします。HTTPS のページから HTTP のリソースを読み込むと、ブラウザがブロックするか警告を表示します（混在コンテンツ）。

## セキュリティヘッダー

サーバーやホスティングサービスの設定で、次のレスポンスヘッダーを付けます。

| ヘッダー | 値の例 | 防ぐもの |
| --- | --- | --- |
| `Strict-Transport-Security` | `max-age=31536000` | HTTP での接続。一度アクセスしたブラウザは、以後 HTTPS でしか接続しない |
| `X-Content-Type-Options` | `nosniff` | ブラウザがファイルの種類を推測し、画像などをスクリプトとして実行すること |
| `Content-Security-Policy` | `frame-ancestors 'self'` | 他のサイトの `iframe` にページを埋め込み、ボタンを押させる攻撃（クリックジャッキング） |
| `Referrer-Policy` | `strict-origin-when-cross-origin` | 外部サイトへの遷移時に、ページの URL（パスやクエリ）が送られること |
| `Permissions-Policy` | `camera=(), microphone=(), geolocation=()` | サイトで使わないブラウザの機能を、埋め込んだ外部スクリプトが使うこと |

:::warning[Strict-Transport-Security の includeSubDomains]
`includeSubDomains` を付けると、サブドメインもすべて HTTPS でしか接続できなくなります。HTTPS に対応していないサブドメインがないことを確認してから付けてください。
:::

### 設定例

Cloudflare Pages では、ビルド成果物に `_headers` ファイルを置きます。

```text _headers
/*
  Strict-Transport-Security: max-age=31536000
  X-Content-Type-Options: nosniff
  Content-Security-Policy: frame-ancestors 'self'
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=()
```

Apache のレンタルサーバーでは、`.htaccess` に記述します。

```apache .htaccess
<IfModule mod_headers.c>
  Header always set Strict-Transport-Security "max-age=31536000"
  Header always set X-Content-Type-Options "nosniff"
  Header always set Content-Security-Policy "frame-ancestors 'self'"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
</IfModule>
```

## CSP（Content Security Policy）

CSP は、ページが読み込めるスクリプトや画像の読み込み元を制限し、XSS の被害を抑える仕組みです。
ただし、計測タグや埋め込みなど外部のスクリプトを多く使うサイトでは、許可する読み込み元の管理が難しくなります。案件の状況に応じて、次の段階で導入してください。

1. **最低限**: 上記の `frame-ancestors 'self'` に加え、`object-src 'none'` と `base-uri 'self'` を指定する。サイトの動作にほぼ影響しない
2. **読み込み元の制限**: `script-src` などで読み込み元を列挙する。まず `Content-Security-Policy-Report-Only` ヘッダーで違反をブラウザの Console に出すだけにして、必要な読み込み元を洗い出してから `Content-Security-Policy` に切り替える

```text
Content-Security-Policy: frame-ancestors 'self'; object-src 'none'; base-uri 'self'
```

:::note
Google Tag Manager でタグを追加すると、読み込み元が増えます。読み込み元を制限している案件では、タグを追加するときに CSP の更新も必要です。運用担当者にも共有してください。
:::

## 公開ディレクトリに置かないファイル

次のファイルは、サーバーの公開ディレクトリにアップロードしないでください。URL を推測されると、誰でもダウンロードできます。

- `.env` などの環境変数ファイル
- `.git` ディレクトリ
- データベースのバックアップ（`.sql` など）
- ビルド前のソースファイルや、作業用のファイル（`.psd`、`.fig` の書き出し元など）

[デプロイ](/deploy-release/deploy)をビルド成果物だけに限定すると、これらのファイルが混ざるのを防げます。

また、Vite では `VITE_` で始まる環境変数がビルド後の JavaScript に埋め込まれ、誰でも読める状態になります。API キーなどの秘密の値には `VITE_` を付けないでください。

## DOM 操作での XSS 対策

ユーザーの入力や URL のパラメータ、外部の API から受け取った文字列を、HTML として解釈させないでください。

```js
// ❌ 文字列に含まれるタグやスクリプトが実行される
message.innerHTML = params.get("name");

// ✅ 文字列をそのままテキストとして表示する
message.textContent = params.get("name");
```

`innerHTML`・`outerHTML`・`insertAdjacentHTML()` に渡してよいのは、コードに直接書いた固定の文字列だけです。
外部から受け取った URL を `href` や `src` に設定する場合は、`javascript:` などのスキームが使われていないことを確認してください。

```js
const url = new URL(input, location.href);
if (url.protocol === "https:" || url.protocol === "http:") {
  link.href = url.href;
}
```

## フォーム

- **入力検証はサーバー側で行う**: HTML の `required` や JavaScript での検証は、入力を助けるためのものです。ブラウザを通さずに送信することもできるため、サーバー側でも必ず検証してください。
- **スパム対策をする**: [Cloudflare Turnstile](https://www.cloudflare.com/ja-jp/application-services/products/turnstile/) や reCAPTCHA などのボット対策を入れます。
- **CSRF 対策をする**: CMS やフレームワークが用意しているトークンの仕組み（WordPress の nonce など）を使います。
- **メール送信は実績のある仕組みを使う**: 自作の `mail()` 関数の呼び出しは、ヘッダーインジェクションなどの脆弱性を作りやすいため避け、CMS のフォームプラグインやフォーム送信サービスを使います。
- **個人情報を扱うフォーム**: プライバシーポリシーへのリンクを送信ボタンの近くに置きます。

## 参考リソース

- [コンテンツセキュリティポリシー（MDN）](https://developer.mozilla.org/ja/docs/Web/HTTP/Guides/CSP)
- [HTTP Security Response Headers Cheat Sheet（OWASP）](https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html)
- [安全なウェブサイトの作り方（IPA）](https://www.ipa.go.jp/security/vuln/websecurity/about.html)
