安全なNode.jsアプリケーションのベストプラクティス

Node.jsセキュリティの基礎ガイド:入力検証、認証、セッション/JWT、ヘッダー、シークレット管理、ログ衛生、ワークフロー検査。

ダット・ザン
HDWEBSOFT CTO
入力検証、認証、セキュアなセッション、セキュリティヘッダーなど、Node.jsアプリの基本セキュリティを示すイラスト。

メディア関係のお問い合わせ

HDWEBSOFTはメディア取材・掲載のご相談を歓迎します

ITやデジタルイノベーションを取り上げる記者、ブロガー、インフルエンサー、登壇者の方に向けて、当社の専門家が実務経験と知見を共有し、価値あるコンテンツづくりをサポートします。

お問い合わせ →

安全なNode.jsアプリケーションとは、一般的な攻撃(インジェクションやアカウント乗っ取りなど)を防ぎ、偶発的なデータ露出を減らし、ランタイムと依存関係におけるリスクの高い挙動を排除することで、ユーザーデータとシステムの整合性を保護するアプリケーションです。

本記事は、開発初期から「安全なNode.jsアプリケーションのベストプラクティス」を適用したい開発者・チームリード向けの基礎ガイドです。プロジェクトをセキュリティ研究の取り組みに変えることなく、ベースラインセキュリティを向上させる、実践的で繰り返し可能な習慣に焦点を当てます。

最初にやるべきこと

  1. すべての入力を厳格なスキーマで検証する。
  2. パラメータ化クエリを使い、ユーザー入力をクエリに連結しない。
  3. パスワードはArgon2id(利用不可ならbcrypt)でハッシュ化する。
  4. セッションとトークンを安全に保護する(Cookieフラグ、JWTの衛生)。
  5. セキュリティヘッダーと厳格なCORS許可リストなどのベースライン保護を適用する。
  6. ログ衛生を実践する:セキュリティイベントは記録し、シークレットやトークンは記録しない。
  7. 依存関係とセキュリティのチェックを自動化し、保証ではなくシグナルとして扱う。

入力検証、認証、セッション、ヘッダー、シークレット管理、ワークフロー検査など、Node.jsアプリの基礎セキュリティ層を示すイラスト。

Node.jsアプリのセキュリティ基盤(ここから始める)

クリーンな基盤から始めましょう。多くのインシデントは高度な手法の不足ではなく、危険なデフォルト設定が放置されることで発生します。

  • 本番ではサポートされているNode.js LTSバージョンを使用する。
  • ランタイムと依存関係を最新に保つ。
  • 開発と本番の設定を分離する(機能フラグ、環境変数、ログレベル)。
  • x-powered-byなど不要なサーバー情報の露出を無効化する。
  • 本番レスポンスにスタックトレースを返さない。

公式の簡潔なチェックリストは Node.js security best practices を参照してください。

例:サーバー情報の露出を抑え、エラーをサニタイズする

情報チェックリスト:Node.jsセキュリティ基盤(LTS、更新、dev/prod分離、x-powered-by無効化、スタックトレース非公開)。

// Express example
app.disable('x-powered-by');

app.use((err, req, res, next) => {
  req.log?.error({ err }, 'Unhandled error');
  res.status(500).json({ error: 'Something went wrong.' });
});

入力検証とインジェクション対策

原則を押さえ、そのうえでツールを選びます。

原則1:境界で検証する

入力はできるだけ早く検証します — ビジネスロジックの前、そしてデータベース呼び出しの前に行います。JoiやZodなどのスキーマ検証ライブラリが役立ちますが、核心は「期待した値だけを受け入れる」ことです。

原則2:パラメータ化クエリを使う

ユーザー入力でクエリ文字列を組み立てないでください。ORMやクエリビルダーを通じてパラメータ化クエリを使用します。Prisma、Drizzle、Knex、およびほとんどの成熟したデータベースクライアントがパラメータ化をサポートしています。

原則3:文脈に応じて出力をエンコードする

アプリケーションがユーザー生成コンテンツをレンダリングする場合、使用される場所(HTML、属性、URL)に応じて出力をエンコードします。DOMPurifyのようなHTMLサニタイザーは、アプリが実際にHTMLを受け入れるまたはレンダリングする場合にのみ検討します。

例:API境界でのスキーマ検証

装飾イラスト:データが検証フィルターを通ってからNode.js APIコアに到達する入力境界。

// Zod example (library choice is optional)
const { z } = require('zod');

const createUserSchema = z.object({
  email: z.string().email(),
  password: z.string().min(12).max(128),
});

const parsed = createUserSchema.safeParse(req.body);
if (!parsed.success) {
  return res.status(400).json({ error: 'Invalid input.' });
}

認証とセッションセキュリティを正しく実装する

認証のミスは小さなバグを完全なアカウント侵害に変える可能性があります。実装は退屈で、よく理解されているものに保ちましょう。

パスワードハッシュ:Argon2id優先、bcryptはフォールバック

スタックがサポートしている場合はArgon2idを優先します。Argon2idが使えない場合や、既存のパスワードストアとの互換性が必要な場合、bcryptは成熟したフォールバックです。

安全なパラメータ設定の指針については、OWASP password storage guidance を参照してください。

セッションとトークンを安全に

  • 該当する場合はセキュアクッキーフラグを使う:httpOnly、secure、sameSite。
  • JWTは短命の資格情報として扱う。ペイロードに機密データを入れない。
  • トークンをXSSにさらす弱い保管パターンを避ける。

管理者アカウントにMFAを追加する

すべてのユーザーにMFAを強制しない場合でも、管理者および高権限アカウントにはMFAを強制しましょう。

ログイン/トークンエンドポイントにレート制限をかける

const rateLimit = require('express-rate-limit');

const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,
  standardHeaders: true,
});

app.post('/auth/login', authLimiter, loginHandler);

基礎を超えて本番向けの完全なセキュリティプログラムが必要な場合は、本番環境でのNode.jsセキュリティ の高度なガイドを参照してください。

シークレットと機密データを安全に扱う

  • .envはローカル開発には便利ですが、本番のシークレット管理ソリューションではありません。
  • 本番では、KMS、Secrets Manager、Vault、またはプラットフォームの組み込みシークレット管理を優先します。
  • HTTPSを使用し、適切な場合は保存時の暗号化も適用します。
  • デフォルトでシークレット、パスワード、トークン、完全なリクエストボディをログに出さないでください。

プログラムレベルの実践に関するより広い視点については、データセキュリティ管理 のガイドを参照してください。

開発ワークフローにセキュリティチェックを組み込む

npm auditを使う(ただし単独では不十分)

npm auditは既知の脆弱性の発見に役立ちますが、それだけでは不十分です。多くのシグナルの一つとして扱いましょう。

軽量なチェックを追加する

  • ESLintセキュリティプラグイン(一般的な危険なパターンを検出)
  • 基本的なSASTスキャン(少なくともプルリクエストで)
  • 認可ルールのユニットテスト(重要なルート)
  • シンプルなPRセキュリティチェックリスト(入力、認可、シークレット、ログ)

安全なNode.jsアプリケーションチェックリスト

情報グラフィック:検証、クエリ、パスワードハッシュ、Cookie、ログ、よくある間違いの回避に関する簡潔な指針を含む安全なNode.jsのDo / Don'tチェックリスト。

  • サポートされているNode.js LTSバージョンを使用する。
  • 依存関係を更新し、未使用パッケージを削除する。
  • 厳格なスキーマで入力を検証する。
  • パラメータ化クエリを使い、文字列連結を避ける。
  • パスワードはArgon2id(フォールバックはbcrypt)でハッシュ化する。
  • セキュアクッキーフラグとJWTの衛生を適用する。
  • 基本的なセキュリティヘッダーと厳格なCORS許可リストを設定する。
  • 本番でスタックトレースを露出しない。
  • シークレット、トークン、機密ペイロードをログに出さない。
  • npm auditを定期実行し、出発点として扱う。
  • CIとPRレビューに基本的なセキュリティチェックを追加する。

よくある質問

安全なNode.jsアプリケーションのベストプラクティスは?

ベストプラクティスは、最初から攻撃面を減らすことに焦点を当てます。すべての入力を検証し、パラメータ化クエリを使い、パスワードはArgon2id(またはbcrypt)でハッシュ化し、セッションとトークンを安全に保護し、セキュリティヘッダーと厳格なCORSを設定し、シークレットをコードやログから排除し、依存関係とセキュリティのチェックをワークフローに自動化します。

Node.jsはデフォルトで安全ですか?

Node.js自体がデフォルトで危険というわけではありませんが、セキュリティはアプリケーションのコードと設定に依存します。安全なNode.jsアプリには、入力検証、認証、エラーハンドリング、シークレット管理、依存関係の保守に関する意図的なデフォルト設定が必要です。

Node.jsでパスワードを保存する最適な方法は?

スタックがサポートしている場合はArgon2idを優先します。bcryptは成熟し、広く互換性のあるフォールバックです。パスワードを平文で保存してはいけません。また、パスワード保存にMD5やSHA1のような高速ハッシュを使わないでください。

Node.js APIで入力を検証するには?

システム境界で厳格なスキーマ検証を行います(例:JoiやZodのようなライブラリ)。スキーマ検証にパラメータ化クエリと文脈に応じた出力エンコーディングを組み合わせ、インジェクションとXSSのリスクを減らします。

Node.jsでJWT認証を安全にするには?

JWTは短命にし、ペイロードに機密データを入れず、安全な保管・送受信パターンを選びます。適切な場合はセキュアクッキーを使い、必要に応じてトークンのローテーションを実装し、ログインとトークンのエンドポイントにレート制限をかけます。

npm auditだけで十分ですか?

いいえ。npm auditは既知の脆弱性の発見に有用ですが、アプリケーション全体のセキュリティを保証するものではありません。セキュアコーディング、テスト、レビュープロセスと組み合わせて、現実のリスクを減らしてください。

結論

Node.jsのセキュリティ開発は主に一貫した基礎に関わります:入力を検証し、認証を保護し、シークレットをコードやログから排除し、セキュリティチェックをワークフローに組み込むことです。本ガイドのベースライン実践から始め、アプリケーションの成長に合わせてレベルを上げていってください。

安全な基盤を持つNode.jsアプリケーションの構築に支援が必要な場合、HDWEBSOFTはNode.js開発サービスを提供しています。

ダット・ザン

実践的で革新的なアウトソーシングソフトウェア開発ソリューションを、誠実に提供することに注力する経験豊富な開発者。

contact@hdwebsoft.com +84 (0)28 66809403 15 Thep Moi, Bay Hien Ward, Ho Chi Minh City, Vietnam