0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Chrome拡張機能でWebアプリの誤操作を防止し、同種インシデントを0件にした話

0
Last updated at Posted at 2026-07-01

はじめに

本記事は、過去に私が実施した施策を記載したものです。私はネットワーク監視・運用・保守を主務とする客先常駐エンジニアで、現場の稼働削減と初動対応の迅速化を目的として、通常業務と並行しながら、プログラミングを通した運用改善に取り組んでいます。

ベストプラクティスではない部分はあるかと思いますが、今回の実装環境とアプローチに関しては同様の制約を持つ現場でも応用できる部分があると考えています。

同様の課題をお持ちの方の一助になればと思います。

経緯

お客様~現場間のチケット管理のために提供しているWebアプリにおいて、現場側のオペレーターによる誤操作でチケットをキャンセルしてしまう事案が、短期間で複数回発生しました。

発生事案から、キャンセルするボタンを押下してしまったものかと思われますが、無意識だったのか、ヒアリングしても押下した経緯ははっきりしませんでした。

また当該ボタンには確認ダイアログなどの安全装置がなく、1クリックでキャンセルが実行されてしまうため、オペレーターの努力では防止が難しいものと判断されました。

ミッション

運用の中で注意を払っていても事故を起こすならば、再発防止を目的としたシステム上の抑止機構を設計・導入し、誤操作の恒久的な排除を実現しようと考えました。

要件

  • オペレーター全員への配布が容易な形にする
  • オペレーターの意図しない当該操作または誤操作を防止する
  • 随時有効・無効を切り替え可能なものにする

制限

利用規約を守るため、

  • Webアプリのサーバ側のアプリケーション資産や通信処理に変更を加える実装を禁止
  • Webアプリのリバースエンジニアリングを禁止

実装方法

一旦フラットな状態で検討した実装方法は以下です。

  1. 当該ボタンが発火させるイベントによって送信されるリクエストをフィルターする

  2. 当該ボタンをDOM上から削除する

  3. 当該ボタンに対して確認ダイアログの表示を割り当て、確認ダイアログのYESボタンに本来のイベントを割り当てる

  4. 当該ボタンをDOM上で操作不可にする

このうち、1と2はサーバ側のアプリケーション資産や通信処理に変更を加え得る実装にあたるものとして除外しました。

3はお客様から制限されていない翻訳やセキュリティ拡張機能などのアクセシビリティ拡張機能と動作が同じではあるものの、クリックイベントに介入することがWebアプリの通信処理の変更にあたる可能性があり、また仕様変更があった場合の追従が難しいことから除外しました。

したがって、

  • 当該ボタンをDOM上で操作不可にする

この形で実装する方針に固まりました。

実装結果

実装の結果、次の成果が得られました。

  • オペレーター端末導入率100%
  • 導入後、誤操作によるインシデント発生0件

作業工程

実装方法検討

まず、実装方法について現場責任者と協議しました。

当該操作は関係者への影響が大きく、同種事案が短期間に複数回発生していたことから、早期に再発防止策を導入する必要がありました。しかし、Webアプリの改善は提供元ではないこちらが行うことは難しいため、今回は、

  • サーバ側のアプリケーション資産や通信処理には変更を加えず、クライアント端末のブラウザ上で表示および操作性のみを制御する方式とする

という条件で合意しました。

Chrome拡張機能での実装

次に、テスト用のWebサーバを起動してChrome拡張機能のテストをしました。Chrome拡張機能は以下のシンプルな記述で実装しました。

manifest.json

拡張機能が動作するURLを必要最小限に限定し、対象外のWebページではスクリプトが実行されない構成としました。

{
  "manifest_version": 3,
  "name": "Operation Guard",
  "version": "1.0.0",
  "content_scripts": [
    {
      "matches": [
        "https://当該Webアプリ/チケット管理画面/*"
      ],
      "js": [
        "content.js"
      ],
      "run_at": "document_start"
    }
  ]
}

本体

(() => {
  const targetId = "無効化したいエレメントのID";

  const disableElement = () => {
    const el = document.getElementById(targetId);

    if (!el) {
      return;
    }

    el.style.setProperty("display", "none", "important"); // 非表示・クリックできないように
    el.disabled = true; // 無効化
  };

  disableElement(); // 読み込み時に一回実施
  setInterval(disableElement, 1000); // 以後動的に生成されても無効化
})();

これで当該ボタンは動的に生成されてもすぐに無効化されますし、要素自体はDOM上から削除せずに残すことで、アプリケーション内部から当該要素を参照していた場合の参照切れリスクを抑えました。

また緊急時に元の操作を必要とする場合は、管理者の指示の下でChrome拡張機能を一時的に無効化する運用としました。

オペレーターへの配布方法の検討

本来Chrome拡張機能の配布はポリシーを使って行った方が安定するのですが、今回は現場担当部署へ依頼が間に合わなかったためローカル配布で実施する流れになりました。

仕様変更があった場合に適宜アップデートするため、ネットワークドライブ上に配置し、オペレーターが自分でChrome拡張機能を登録する形式でテストしました。

ここで当該環境では、Chrome起動時にネットワーク共有へ到達できない場合、共有フォルダ上から読み込んだ拡張機能が利用不能になる事象を確認しました。

そこでネットワークドライブからローカルへのインストーラ.batを作り、オペレーターにはローカルにインストールされた拡張機能をChromeへ登録してもらうこととしました。

またアップデートに関しては、以下の.batでローカルの拡張機能を上書きする形式で実装。アップデータをスタートアップフォルダへ登録し、ユーザーのサインイン時に共有フォルダから最新版を取得する構成としました。

また常に最新版をオペレーターに使用してもらうため、Chromeの起動前にローカルファイルを更新し、次回のChrome起動時に更新版を読み込ませる運用としました。

アップデート.bat

@echo off
setlocal

rem ===== 設定 =====
set "SOURCE=\\server\share\TargetFolder"
set "DESTINATION=C:\extensions\TargetFolder"
set "RETRY_INTERVAL=5"
set "MAX_RETRY=60"

set /a RETRY_COUNT=0

echo ネットワーク共有への接続を待機しています...

:WAIT_NETWORK
if exist "%SOURCE%\" goto NETWORK_READY

set /a RETRY_COUNT+=1

if %RETRY_COUNT% GEQ %MAX_RETRY% (
    echo [ERROR] ネットワーク共有に接続できませんでした。
    echo 対象: %SOURCE%
    exit /b 1
)

echo 接続待機中... %RETRY_COUNT%/%MAX_RETRY%
timeout /t %RETRY_INTERVAL% /nobreak >nul
goto WAIT_NETWORK

:NETWORK_READY
echo [INFO] ネットワーク共有への接続を確認しました。

if not exist "%DESTINATION%\" (
    mkdir "%DESTINATION%"
    if errorlevel 1 (
        echo [ERROR] コピー先フォルダを作成できませんでした。
        exit /b 2
    )
)

robocopy "%SOURCE%" "%DESTINATION%" /MIR /COPY:DAT /DCOPY:DAT /R:2 /W:2

set "RESULT=%ERRORLEVEL%"

if %RESULT% GEQ 8 (
    echo [ERROR] コピーに失敗しました。終了コード: %RESULT%
    exit /b %RESULT%
)

echo [SUCCESS] コピーが完了しました。
exit /b 0

オペレーターへの配布

インストーラ・アップデータを作成後、ローカルのChrome拡張機能の導入手順書を作成し、現場責任者に依頼して展開していただきました。誤操作によるインシデント発生から2週間後に、全オペレーターへの配布が完了し、本施策は保守フェーズへ移行しました。

学んだこと

今回初めてChrome拡張機能の実装を経験しました。この経験によって、この後実施したDOM監視による動態検知・音声通知ツール施策にも応用できました。

Chrome拡張機能は制約が多く、また作法も独特なため苦戦しましたが、非破壊的にWebアプリを変更することができる非常に便利なものであることを学びました。

また余談ですが、本施策では、実装そのものの複雑さよりも、制約条件を整理したうえで実現可能な方式を選定し、関係者との合意形成、全端末への展開、更新方式の構築まで一貫して実施した点が評価され、関係部門責任者から表彰を受けました。小規模な実装であっても、業務上のリスクを正確に捉え、導入・定着まで完遂することで、大きな改善効果を生み出せることを学びました。

さいごに

最後までお読みいただきありがとうございます。

今回は過去に実施した施策のうち、Chrome拡張機能を使ったWebアプリの非破壊的変更による誤操作防止について記載しました。なお、本方式はサーバ側のアプリケーション資産には変更を加えませんが、ブラウザ上のDOM表示および操作性には変更を加えます。適用に当たっては、契約、利用規約およびシステム管理者の判断を確認してください。

同じような課題をお持ちの方の参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?