pom.xml、環境変数、Maven properties、system properties を横断して扱えるこの記事のテーマは、ひとことで言うと 「Mavenのビルドを、ただのビルドではなく“セキュリティを意識したビルド”に変えよう」 という話です。
ただし、著者が言っている問題は「Mavenでsecurity toolが使えない」という話ではありません。むしろ逆で、使える。でも、うまく揃わない のが問題だとしています。
たとえば、こんな感じです。
test、Dependency-Check、CycloneDX、SonarQube を実行しているこの状態を著者は security build drift と呼んでいます。
直訳っぽく言うと「セキュリティ関連のビルド設定のズレ」です。
ここ、かなり本質的だと思います。
自動化って、動いているだけだと安心しがちですが、実際は「各所でちょっとずつ違う」ことがいちばん危ない。しかもその違いは、最初は小さいので気づきにくいんですよね。怖い。
記事では、典型的なMavenのCI/CD設定として次のような流れを例にしています。
./mvnw test
./mvnw org.owasp:dependency-check-maven:check
./mvnw org.cyclonedx:cyclonedx-maven-plugin:makeBom
./mvnw sonar:sonar
この形、1リポジトリだけならまあ回ります。
でも、サービスが増えると話が変わります。
pom.xml 側にも一部設定があるつまり、設定が散らばるんです。
散らばると何が起きるか。著者はこうまとめています。
これは地味だけど、かなり痛いです。
「動いてはいるけど信用できない」状態が、いちばんコスト高なんですよね。
この問題に対して著者が作ったのが secure-maven-extension です。
ポイントは、scannerを新しく作ったわけではない こと。
JaCoCo、SonarQube、Dependency-Check、CycloneDX といった既存ツールを使いながら、Mavenのライフサイクルにsecurity workflowを埋め込む 発想です。
ここが面白いところです。
普通は、CI/CDのYAMLにコマンドを足していきます。
でもそれだと、プロジェクトごとに差が出やすい。
そこで著者は、CI/CDの外ではなく、Maven自体を“セキュリティ対応の実行基盤”にする方向へ寄せています。
個人的には、この発想はかなり筋がいいと思います。
CI/CDは本来「実行する場所」であって、「毎回どう実行するかの細かい流儀」を抱え込むには重すぎるんですよね。
その流儀をMaven側に寄せるのは、かなり自然です。
著者は、ただの Maven plugin ではなく core extension を選んでいます。
Maven pluginでも似たことはできますが、pluginだと各プロジェクトに明示的な設定が必要になりがちです。
それだと、結局 copy-paste が残る。
core extension は、もっと早い段階で Maven に入り込めます。
この拡張は .mvn/extensions.xml から読み込まれます。
<extensions>
<extension>
<groupId>io.github.niki1337.securebuild</groupId>
<artifactId>secure-maven-extension</artifactId>
<version>0.1.0</version>
</extension>
</extensions>
そして、Mavenの afterProjectsRead というタイミングで動きます。
このタイミングが重要です。
ここでは、すでに root POM や module POM を読んだ後なので、
などが見えます。
でも、まだライフサイクルは始まっていない。
つまり、実行前に“どういうセキュリティ設定を入れるか”を決められるわけです。
これはかなり賢い設計だと思います。
この extension がつなぐのは、主に以下のツールです。
jacoco-maven-pluginsonar-maven-plugindependency-check-mavencyclonedx-maven-pluginSBOMは、ざっくり言うと「このソフトが何でできているかの部品表」です。
食品の原材料表示みたいなものだと思うと近いです。
セキュリティやサプライチェーン対策では、かなり重要です。
使い方は見た目上、普通の Maven コマンドのままです。
mvn package
mvn verify
mvn sonar:sonar
でも内部では、これらがセキュリティを意識した動きになります。
たとえば:
mvn packagemvn verifymvn verify sonar:sonarつまり、見た目は普通の Maven、でも中身は security-aware。
この「見た目は変えない」が、現場ではかなり効くと思います。
ここも実務っぽくて良い点です。
現場って、きれいに一枚岩ではありません。
-D... を付けたいpom.xml に置きたいこの記事の extension は、こうした複数の設定源を受け入れます。
つまり、設定の“書き方”を強制しない。
代わりに、最終的に解決された挙動を揃えるのがゴールです。
この考え方はかなり現実的です。
理想論で「全部 pom.xml に統一しましょう」みたいに言われても、実際は難しいですからね。
環境ごとの事情を認めたうえで、結果だけを揃える。大人の設計です。
Coverage(テスト網羅率)は、地味にAppSecの品質に効きます。
SonarQube自体は coverage なしでも動きますが、当然ながら分析の質は下がります。
よくある失敗は、
というパターンです。
著者の extension は、Java の jar/war project で JaCoCo が未設定なら自動注入します。
流れはこうです。
initialize -> jacoco:prepare-agent
verify -> jacoco:report
そして XML レポートは次の場所に出ます。
target/site/jacoco/jacoco.xml
さらに、そのパスを SonarQube の
sonar.coverage.jacoco.xmlReportPaths
に渡します。
このあたり、ほんとに「わざわざ手でやるほどではないけど、ミスると痛い」領域です。
だからこそ自動化向き。
著者の問題意識はここでかなり一貫しています。
SonarQube連携って、ありがちなのが「URL・project key・tokenがあればOKでしょ」という雑な理解です。
でも実際には、もっと情報が要ります。

たとえば Java project では、
などが必要になります。
この記事の extension は、こうした設定をまとめて準備します。
sonar.sources
sonar.tests
sonar.java.binaries
sonar.java.test.binaries
sonar.coverage.jacoco.xmlReportPaths
sonar.exclusions
sonar.test.exclusions
sonar.cpd.exclusions
sonar.coverage.exclusions
さらに、GitLab の merge request pipeline では、CI変数を SonarQube の pull request 分析に対応させます。
CI_MERGE_REQUEST_IID -> sonar.pullrequest.key
CI_MERGE_REQUEST_SOURCE_BRANCH_NAME -> sonar.pullrequest.branch
CI_MERGE_REQUEST_TARGET_BRANCH_NAME -> sonar.pullrequest.base
普通の branch pipeline なら branch analysis metadata を設定するとのことです。
ここは、手で pipeline に書くとすぐ壊れます。
だからこそ、一度 core extension の中に閉じ込めて、バージョン管理された再利用可能な仕組みにする。
この判断はかなり筋がいいと思います。

Dependency-Check は、依存ライブラリの脆弱性を調べるツールです。
いわば「使っている部品に危ないものが入っていないか」を見るものですね。
著者は、これも lifecycle に組み込みます。
single-module: verify -> dependency-check:check
multi-module: verify -> dependency-check:aggregate
出力形式も統一します。
そして、レポートの出力先は
target/reports/dependency-check
に揃えるとのことです。

さらに興味深いのは、デフォルトでネットワーク依存の analyzer を無効にしている点です。
RetireJS、Node audit、Node package analyzer、OSS Index、hosted suppressions などですね。
これは重要です。
外部サービスに依存すると、
ということが起こります。
セキュリティチェックは本来、できるだけ再現性が大事なので、ここを切り離すのは理にかなっています。
必要なら、Dependency-Track のような内部ミラーを使える設計も示されています。
DT_API_URL を使う例も出ていました。
個人的に、この文章でいちばん面白いのは、表向きは AppSec の話なのに、実態はかなり 開発者体験と運用設計の話 だという点です。
「脆弱性スキャンを入れよう」は誰でも言えます。
でも本当に難しいのは、そのあとです。

ここを解決しないと、セキュリティはだんだん“形だけ”になります。
著者はそこをかなり正面から見ています。
地味だけど、すごく実務的です。
この記事の主張を一言でまとめるなら、
セキュリティチェックをCI/CDのオプションとして足すのではなく、Mavenビルドの基本動作にするべき
ということだと思います。
これによって、
ことを狙っています。
もちろん、どの現場でもすぐ同じやり方がハマるとは限りません。
でも、「scannerを足す」ではなく「ビルドにセキュリティを埋め込む」という発想は、かなり有望ではないかと思います。
特に、複数サービスを運用している組織ほど、この手の drift はじわじわ効いてきます。
なので、この記事は単なるツール紹介というより、**“セキュリティを運用可能な形にする設計論”** として読むとかなり面白いです。
参考: Making Maven Builds Security-Aware: AppSec Checks Without CI/CD Drift