大人の知識力テスト

なぜ、パスワード入力フォームは <input type="text">ではダメなのか?

相次ぐ情報漏洩。パスワードフォーム実装が招く、危険なセキュリティ破綻と漏洩リスクを解説します。

内藤 貴志(Web担編集部)

10月22日 7:05

パスワードを入力するフォームで、本来 <input type="password"> とすべきところを、いまだに <input type="text"> のままにしている Web サイトを見かけることがあります。

画面上で文字が見えるか隠れるかの違いだけでしょ?

JavaScript で後から伏字(●や*)に変換しているから大丈夫

このように考えているとしたら、それは大間違いです。コーディングの観点から見ると、これは単なるデザインの問題ではなく、重大なセキュリティリスクとアクセシビリティの低下を招く「やってはいけない実装」です。

なぜ <input type="text"> をパスワードフォームに使ってはいけないのか、フロントエンドの技術的な観点から詳しく解説します。

1. ブラウザの「パスワードマネージャー」が機能しなくなる

現代の Web ブラウザ(Chrome、Safari、Edge など)や OS には、安全なパスワードを生成・記憶して自動入力する「パスワードマネージャー」が標準搭載されています。

ブラウザは、HTML 内の <input type="password"> という属性や、周囲の autocomplete="current-password" などの属性を検知して、「ここはパスワードを入力する場所だな」と判断します。

ここを type="text" にしてしまうと、ブラウザはそれを「単なる一般的な文字列入力欄(ユーザー名や住所など)」と誤認します。その結果、次の機能が利用できなくなります:

  • 複雑で安全なパスワードの自動生成(強力なパスワードの推奨)
  • 保存されているパスワードの自動補完(オートフィル)
  • 新しく入力したパスワードをブラウザに保存するかどうかの確認ポップアップ

ユーザーに「過去に設定した複雑なパスワードを手入力させる」または「覚えやすい脆弱なパスワードを設定させる」ことを強制することになり、サイト全体のセキュリティレベルを著しく下げる原因になります。

2. ショルダーハック(のぞき見)の防止機能を自作するのは危険

type="text" でフォームを作り、JavaScript を使って「入力された先から文字を * や ● に書き換える」という実装をしている古いサイトがあります。しかし、これは車輪の再発明どころか、脆弱性を生む原因になります。

  • 入力の瞬間ののぞき見:
    ネイティブの type="password" は、文字が入力された一瞬だけその文字を表示し、次の瞬間に伏字にするような高度な制御が OS・ブラウザレベルで最適化されています。これを JavaScript で完全に再現するのは難しく、背後から画面を盗み見られる「ショルダーハック」のリスクが高まります。

  • イベント処理のバグ:
    JavaScript で値を書き換える制御をしていると、コピペ(コピー&ペースト)されたときや、キーボードの連打、バックスペースでの削除時などに挙動が乱れやすくなります。結果として、裏側で保持している「実際のパスワード文字列」と画面上の表示がズレる原因になります。

3. 拡張機能やアクセシビリティ(画面読み上げ)での致命的なバグ

Web サイトは、目で見える画面の美しさだけでなく、支援技術(スクリーンリーダーなど)を使うユーザーや、ブラウザの拡張機能にとっても正しく解釈できなければなりません。

  • 画面読み上げソフト(スクリーンリーダー)の暴走:
    type="password" であれば、視覚障害者向けのスクリーンリーダーはパスワードの文字をそのまま音読せず、「パスワード」や「ドット」のように発音してプライバシーを守ります。しかし type="text" になっていると、入力したパスワードのスペルをそのまま大声で読み上げてしまうという、恐ろしいプライバシー侵害が発生します。

  • サードパーティ製拡張機能によるデータ収集:
    翻訳ツールや画面キャプチャ、テキスト校正などのブラウザ拡張機能は、type="password" の要素を意図的に無視(スキップ)するように設計されているものが多くあります。ここが type="text" だと、それらの拡張機能が「一般テキスト」としてパスワードデータを読み取り、外部サーバーに送信してしまうリスク(サプライチェーン攻撃や意図しない漏洩)が生じます。

4. モバイル端末でのキーボード最適化が行われない

スマートフォンのブラウザは、<input> タグの type 属性を見て、表示するキーボードの種類を動的に切り替えています。

  • type="password" であれば、英数字が入力しやすいキーボードが自動で立ち上がり、かつキーボードの「予測変換(入力候補)」の学習機能が自動的にオフになります。

  • type="text" のままだと、スマホの予測変換辞書にユーザーの生パスワードが登録されてしまい、別のアプリで文字入力をしているときに予測変換候補としてパスワードがポロッと表示されてしまうというセカンダリ漏洩のリスクを引き起こします。

正しいコーディング:パスワードの「表示 / 非表示」を切り替えるには?

最近のトレンドである「目のアイコンをタップすると、パスワードの伏字とプレーンテキストが切り替わる機能」を実装したい場合でも、最初から type="text" で作ってはいけません。

正解は、「最初は type="password" で配置し、ユーザーがボタンを押した瞬間に JavaScript で type 属性の値を text に書き換える(トグルする)」という実装です。

模範的なコード例

<div class="password-field">
  <input type="password" id="myPassword" autocomplete="current-password" placeholder="パスワードを入力">
  <button type="button" id="togglePassword" aria-label="パスワードを表示する" aria-pressed="false">表示</button>
</div>

<script>
  // 属性を動的に切り替えることで、ブラウザの標準機能を壊さずに表示をコントロールする
  // 表示を変えるときにはアクセシビリティ関連の属性にも反映させる

  const passwordInput = document.getElementById('myPassword');
  const toggleButton = document.getElementById('togglePassword');

  toggleButton.addEventListener('click', () => {
    const isPassword = passwordInput.getAttribute('type') === 'password';
    const newType = isPassword ? 'text' : 'password';
    
    passwordInput.setAttribute('type', newType);
    toggleButton.textContent = isPassword ? '非表示' : '表示';
    toggleButton.setAttribute('aria-label', isPassword ? 'パスワードを非表示にする' : 'パスワードを表示する');
    toggleButton.setAttribute('aria-pressed', !isPassword);
  });
</script>

まとめ:HTML のセマンティクス(意味論)を厳守しよう

パスワードフォームに <input type="text"> を使う行為は、開発側のほんの一時の怠慢や知識不足によって、エンドユーザーにすべてのセキュリティリスクとしわ寄せを押し付ける結果になります。

HTML のタグや属性には、それぞれブラウザや OS と対話するための重要な「意味(セマンティクス)」があります。フォームを作成する際は、必ずそのデータに最適な type 属性を選択することを徹底しましょう。