【ITニュース解説】DevGuard: A Zero-Dependency Security Scanner Built from Python's Standard Library
2026年09月08日に「Dev.to」が公開したITニュース「DevGuard: A Zero-Dependency Security Scanner Built from Python's Standard Library」について初心者にもわかりやすく解説しています。
ITニュース概要
DevGuardは、Python標準機能のみで構築された、依存関係ゼロの軽量セキュリティスキャナーだ。コード内の秘密情報や機密ファイルを検出し、危険度をスコア化し、具体的な修正案を提示する。システムエンジニアを目指す初心者も手軽に利用でき、安全な開発を支援する。
ITニュース解説
DevGuardは、Pythonの標準ライブラリだけを使用して作られた、依存関係を全く持たない(ゼロ依存)のセキュリティスキャナーである。これは、通常利用される様々なセキュリティライブラリを使わずに、コードベースやその依存関係を検査する実用的な開発者向けセキュリティツールを構築できるか、というエンジニアリング上の挑戦から生まれた。開発の主な制約は、サードパーティ製のランタイムパッケージに一切頼らずに、有用なツールを作り出すことだった。この制約が、DevGuardのほぼ全ての設計思想に影響を与えている。
開発者が誤ってソースファイル、環境設定ファイル、プライベートキー、その他の機密性の高いプロジェクト資産を通じて資格情報などの秘密情報を公開してしまう事故は少なくない。DevGuardは、このような状況に対して、大規模なセキュリティスタックを必要とせずに、即座に第一層の保護を提供できる小さなセキュリティツールを目指して作られた。一般的な商用セキュリティプラットフォームの全ての機能を再現しようとするのではなく、実用的な三つの検査に焦点を当てている。
一つ目は「SecretScanner」で、コード内に直接書き込まれた秘密情報やプライベートキーの素材を検出する。
二つ目は「FileRiskScanner」で、.envファイル、SSHキー、資格情報ファイル、証明書コンテナなど、機密性の高いファイルを検出する。
三つ目は「DependencyScanner」で、requirements.txtやpackage.jsonといった依存関係マニフェストを解析し、宣言されている依存関係を記録する。このスキャナーは、特定の依存関係が自動的に脆弱であると断定することはせず、検出された依存関係の情報だけを提供する。
DevGuardの核となるアーキテクチャは、「全てのスキャナーが同じ種類の結果を返す」というシンプルな考え方に基づいている。各スキャナーは共通のインターフェースを実装し、標準化された「Finding(検出結果)」オブジェクトを返す。このFindingオブジェクトには、検出されたファイル名、行数、ルール、深刻度、メッセージなどの情報が含まれる。このようにすることで、検出ロジックと結果の報告・表示ロジックが分離され、新しいスキャナーを追加する際にもアプリケーション全体の再設計が不要となる。
DevGuardはコマンドラインインターフェース(CLI)だけでなく、軽量なローカルダッシュボードも提供する。このダッシュボードのバックエンドはPythonに組み込まれているhttp.serverモジュールを使用し、フロントエンドはプレーンなHTML、CSS、JavaScriptだけで構成されている。FlaskやFastAPI、Reactのようなサードパーティ製のフレームワークは一切使用していない。ローカルサーバーがスキャンAPIを公開し、ダッシュボードを直接提供する。ダッシュボードでは、全体的なセキュリティスコア、リスクレベル、深刻度別の検出件数、スキャナーごとの検出結果、詳細な検出情報、そして推奨される修正方法などが表示され、開発者が生の検出結果を素早く理解できるように工夫されている。
検出されたセキュリティ問題を単に報告するだけでなく、その全体的な影響を理解することはより重要である。DevGuardには、決定論的なリスクエンジンが組み込まれており、検出結果に基づいてセキュリティスコアを算出する。スコアは100から始まり、検出された問題の深刻度に応じて一定のペナルティが適用される。例えば、CRITICAL(危険度最高)な問題には-30、HIGH(高)には-15、MEDIUM(中)には-7、LOW(低)には-2がそれぞれ減点される。最終スコアは0から100の間に収まり、そのスコアに応じてリスクレベル(LOW、MEDIUM、HIGH、CRITICAL)が割り当てられる。この計算は意図的にシンプルで分かりやすく保たれており、開発者は単に数字を信頼するだけでなく、なぜスコアが変化したのかを理解できる。
秘密情報の検出は、単に「password」のようなキーワードを検索するだけでは不十分である。例えば、password = os.getenv("PASSWORD")のような環境変数から値を読み込むコードは、実際のパスワードをハードコードしているわけではないため、安全な場合が多い。DevGuardは、このような環境変数からの参照やプレースホルダーの値をチェックし、誤検知を減らすためのコンテキストを考慮して秘密情報を報告する。闇雲に多くのマッチを見つけることが、必ずしも優れたセキュリティスキャナーを作るわけではないという教訓に基づいている。
秘密情報は必ずしもソースコード内に現れるとは限らない。時にはファイル自体がリスクとなる場合もある。DevGuardは、.env、id_rsa、credentials.json、*.keyなどの機密性の高いファイルを検出する。しかし、.env.exampleのような一般的な安全なテンプレートファイルは、誤ってリスクとして報告しないように除外する。このような細かい実装の配慮が、スキャナーの実用性を大きく高めている。
依存関係スキャナーは、requirements.txt、package.json、go.modなど、複数の依存関係マニフェスト形式を認識する。そして、そこに宣言されている依存関係を解析し、マニフェスト自体を検出結果として報告する。しかし、特定の依存関係が存在するだけで脆弱であると主張することは意図的にしない。依存関係を検出することと、その依存関係に既知の脆弱性があるかどうかを判断することは異なる問題であり、DevGuardはこの境界線を明確に保つことで、誤解を招くセキュリティの主張を避けている。
DevGuardの開発において予想以上に難しかったのは、何を報告しないかを決めることだった。環境変数からのルックアップ、プレースホルダーの値、バイナリファイル、テストやフィクスチャディレクトリ、生成されたディレクトリ、安全な環境テンプレート、異なる依存関係マニフェスト形式への対応、そしてスキャナー間での一貫した検出結果など、様々な要素を考慮する必要があった。例えば、プロジェクトを盲目的にスキャンすると、.git/やnode_modules/のような関連性の低いディレクトリから大量のノイズとなる結果が生成されてしまう。そのため、DevGuardはプロジェクトレベルの除外設定を保持し、秘密情報スキャナーはバイナリファイルをスキップする。これらの細かい工夫は視覚的に目立つものではないが、開発者が実際にセキュリティスキャナーを信頼し、使用するかどうかを決定する重要な要素である。
ゼロ依存という制約は、Pythonの標準ライブラリを異なる視点で見つめ直すきっかけとなった。HTTPサーバーにはhttp.server、CLI解析にはargparse、JSON解析にはjson、TOML解析にはtomllib、ファイルやパスの処理にはpathlibやos、正規表現によるパターンマッチングにはreなど、コア機能の多くに標準ライブラリモジュールが使われている。サードパーティパッケージが悪いというわけではなく、成熟したソリューションを提供し開発時間を節約する点で価値があることは理解している。しかし、この開発を通して、「実際に必要な機能はどの程度か、そしてその機能のどれだけが既に標準ライブラリで利用可能か」という問いを深く考えることができた。DevGuardは、既存のサードパーティ製ライブラリ(例: requestsをurllib.requestで、clickをargparseで代替)の機能を、DevGuardが実際に必要とする最小限の要件に合わせて標準ライブラリで実装した。
DevGuardは、単に「何かがおかしい」と報告するだけでなく、開発者が次の行動に移れるよう、検出された問題に対する具体的な修正推奨事項も提供する。例えば、ハードコードされた秘密情報に対しては、値を環境変数や安全な秘密情報管理システムに移行するようアドバイスし、検出されたプライベートキーには、それを削除し、もし公開されていればローテーションまたは失効させるよう指示する。機密性の高いファイルには、.gitignoreや環境変数の利用に関するガイダンスを提供する。このように、出力が単に警告するだけでなく、具体的な行動につながるように設計されている。
テストに関しても、ゼロ依存の原則が適用されており、DevGuardはPythonに組み込まれているunittestフレームワークを使用する。秘密情報の検出、プライベートキーの検出、環境変数処理、バイナリファイル処理、機密ファイル検出、依存関係の解析、CLI連携、リスクスコアリング、リスクレベル計算、推奨ロジックなど、多岐にわたる領域がテストスイートでカバーされている。
DevGuardの開発から得られた最大の教訓は、サードパーティパッケージが不要だということではない。それらは必要である。本当の教訓は、依存関係は実際に抱えている問題を解決するために使うべきだということだ。普段使っているライブラリに頼らずに開発を進めることで、「スキャナーに本当に必要なものは何か」「検出結果をどのように表現すべきか」「誤検知をどう減らすべきか」「ダッシュボードはリスクをどう伝えるべきか」「実際にどの程度の解析が必要か」「依存関係が本当に価値を加えるのはどこか」といったことについて、より深く考える必要があった。標準ライブラリがDevGuardを魔法のように作り上げたわけではない。それは単なるビルディングブロックであり、開発チームはアーキテクチャを設計し、エッジケースを処理し、スキャナーの契約を定義し、リスクモデルを構築し、ツールが何を主張すべきで何を主張すべきでないかを決定する必要があった。
「ゼロ依存」という制約は、最初は制限のように感じられたが、最終的にはエンジニアリング上の興味深い課題となった。重要なのはpipコマンドを避けること自体ではなく、「我々が実際に解決しようとしている問題は何なのか」そして「構築できる最小限で信頼性の高い実装は何か」、最終的に「標準ライブラリは既に必要な部品を提供しているか」という問いを学ぶことであった。DevGuardは、これらの問いに対する答えであり、小規模でモジュール化されたアーキテクチャ、ローカルダッシュボード、説明可能なリスクモデル、実行可能な推奨事項、そしてサードパーティのセキュリティフレームワークに依存しないランタイムを備えたセキュリティスキャナーとして完成した。