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?

Vue3 + DRF に SonarQube を入れる(後編)— 指摘の読み方と Quality Gate の落とし穴

0
Posted at

この記事は後編です

前編では、ホストに Node / Python / Java を一切入れず、Docker だけで SonarQube を立て、
Vue3 + Django REST Framework のプロジェクトを解析してカバレッジを取り込むところまでやりました。

前編の到達点はここです。

backend (DRF) frontend (Vue3)
Coverage 47.7% 52.0%
検出された指摘 14 件 26 件

ところが、この状態で Quality Gate を見ると「Passed」と表示されます。
これだけ指摘が出ているのにです。

後編はその正体から入り、指摘をどう読み、どう運用するかを扱います。
数値・ログ・エンドポイントはすべて実際に動かした結果です。

検証環境: SonarQube Community Build 26.9.0.129388 / Docker 28.2.2 / macOS (x86_64)

この記事の構成

章 内容
5 検出結果の一覧 — 実際に何が出たか
6 出なかった指摘の原因 — 3 パターンの切り分けと Quality Profile のカスタマイズ
7 Quality Gate が初回素通りする正体 — New Code とは何か
8 Fail → 修正 → Pass の実演 — 誤検知(False Positive)の扱いも
9 GitHub Actions 連携
10 静的解析の深さ — どこまで見るのか、脆弱性検出の限界
11 Community Build の線引き — 有償版が必要になる境界

S106 のような個別ルールの解説は、分量が多いので
**別記事「SonarQube ルール早見表(Vue3 + DRF 編)」**にまとめています。


5. 何が検出されたか

検証アプリには典型的な問題コードを仕込みました。修正前の backend で 14 件です。

ルール 種別 内容
secrets:S6687 Vulnerability (BLOCKER) SECRET_KEY のハードコード
python:S4507 Vulnerability DEBUG = True
python:S4502 ×2 Vulnerability (CRITICAL) CSRF 保護の無効化(@csrf_exempt と middleware 未設定)
python:S4790 Vulnerability (CRITICAL) MD5 でのハッシュ化
python:S2245 Vulnerability random をセキュリティ用途に使用
python:S4830 Vulnerability (CRITICAL) verify=False(TLS 検証の無効化)
python:S3752 Vulnerability HTTP メソッドの未指定
python:S1763 Bug return 後の到達不能コード
python:S1862 Bug 同じ条件の elif で到達しない分岐
python:S1192 Code Smell 3 回重複した文字列リテラル
python:S1135 Code Smell TODO コメント
python:S1481 Code Smell 未使用のローカル変数
python:S3776 Code Smell 認知的複雑度 28(上限 15)

frontend は 26 件。Vue3 特有のものを抜粋します。

ルール 種別 内容
typescript:S1656 Bug 自己代入(title = title)
typescript:S1862 Bug 同じ条件の else if
Web:InputWithoutLabelCheck Bug <input> に label が無い(アクセシビリティ)
typescript:S2245 Vulnerability Math.random()
typescript:S4144 ×2 Code Smell 実装が同一の関数(コピペ検出)
typescript:S1854 Code Smell 使われない代入
typescript:S2486 Code Smell 空の catch
typescript:S2699 Code Smell (BLOCKER) アサーションが無いテスト
typescript:S3776 Code Smell 認知的複雑度 22
typescript:S7781 Code Smell replace() より replaceAll() を使う

S2699(アサーション無しテスト)が BLOCKER で出るのは実用的だと感じました。
「通っているつもりのテスト」を検出できます。

Security Hotspot は 0 件だった

意外だったのですが、security_hotspots = 0 で、/api/hotspots/search も空でした。
従来 Security Hotspot に分類されていたルール(MD5、擬似乱数、TLS 検証無効化など。
メッセージが "Make sure ... is safe here" になっているもの)が、
26.9 では Vulnerability として集計されています。

先行記事にある「Overview に Security Hotspots が出る」という説明とは
挙動が変わっているので、バージョンによって読み替えが必要です。


6. つまずき④ 仕込んだのに検出されない指摘がある

ここが一番の発見でした。仕込んだのに出ないものが複数ありました。

原因は 3 種類に分かれます。/api/rules/show と /api/rules/search で切り分けました。

仕込んだもの 結果 原因
v-html での XSS 検出されない ルール自体が存在しない
ALLOWED_HOSTS = ["*"] 検出されない ルール自体が存在しない
eval() での動的実行 検出されない Python 用のルールが存在しない
console.log の残留 検出されない typescript:S106 はあるが Sonar way で無効
== による比較 検出されない typescript:S1440 が無効
any の使用 検出されない typescript:S4204 が無効
未使用の import(Python) 検出されない python:S1128 が無効
API トークンのハードコード 検出されない typescript:S2068 は有効だが変数名が合致せず
SQL インジェクション等 検出されない taint analysis は Developer Edition 以上

確認方法はこうです。

# ルールが存在するか・有効かを調べる
curl -s -u "admin:$PASS" "$SONAR_URL/api/rules/show?key=typescript:S106&actives=true"
# → rule は返るが actives が空 = 存在するが無効

# ルールキーが分からないときはキーワードで検索する
curl -s -u "admin:$PASS" "$SONAR_URL/api/rules/search?q=console&languages=js,ts"

ここから導ける運用方針

SonarQube だけで Vue3 / DRF の品質を担保しようとしないこと。

  • v-html の XSS は SonarQube では拾えないので、ESLint の vue/no-v-html が必要
  • console.log、==、any は ESLint / TypeScript の設定で止めるのが素直
  • Python の未使用 import は ruff / flake8 の担当

SonarQube の強みは、認知的複雑度・重複・カバレッジ・セキュリティ設定の指摘を
ダッシュボードで時系列に追えること
でした。リンターの置き換えではなく、
リンターが見ないレイヤを埋めるツールと考えるのが実態に合っています。

無効になっているルールは有効化できる

パターン B(存在するが無効)は、Quality Profile をカスタマイズすれば検出できます。
実際にやってみました。

  1. Quality Profiles → TypeScript の Sonar way を Copy
    (Sonar way は Built-in なので直接編集できません。コピーが必須)
    スクリーンショット 2026-09-21 23.00.50.png

  2. 作ったプロファイルで Activate More Rules → S106 と S4204 を Activate
    スクリーンショット 2026-09-21 21.04.20.png

  3. Projects タブで対象プロジェクトに適用
    スクリーンショット 2026-09-21 21.07.34.png

  4. 再解析(Quality Gate と同じで、プロファイルを変えても再解析しないと反映されません)

結果、指摘が 26 件 → 30 件に増えました。

ルール 増えた件数 検出された場所
typescript:S4204(any の使用) 3 件 composables/useTodos.ts、api/client.ts
typescript:S106(console.log の残留) 1 件 composables/useTodos.ts

「デフォルトが緩いなら締められる」 ということです。ただし ESLint で止めれば済む内容も
多いので、どちらの層で止めるかをチームで決めておくのが現実的です。

有効化するときの注意点 2 つ

① 同じルールが言語ごとに別キーで存在する

[無効] javascript:S106   Standard outputs should not be used...
[無効] typescript:S106   Standard outputs should not be used...

プロファイルは言語単位です。.js と .ts が混在するプロジェクトでは、
両方の言語のプロファイルで有効にしないと片方だけ検出されません。

② 同じ問題でも言語によって検出できるルールが違う

「空の例外ハンドラ」を両方に仕込んだところ、結果が非対称でした。

仕込んだコード 結果
frontend catch (error) { } ✅ typescript:S2486 で検出
backend except Exception: pass ❌ 該当ルールが Sonar way に無い

「Python で出たから TypeScript でも出る」とは限りません。 言語ごとにルールセットの
成熟度が違うので、両方のプロファイルを個別に確認する必要があります。


7. つまずき⑤ 初回スキャンで Quality Gate が必ず素通りする

初回スキャン直後、あれだけ指摘が出ているのに Quality Gate は OK でした。

理由は条件定義を見れば分かります。デフォルトの Sonar way はこうなっています。

new_violations                  GT 0
new_coverage                    LT 80
new_duplicated_lines_density    GT 3
new_security_hotspots_reviewed  LT 100

4 つ全部が new_*(New Code 側)です。
初回解析には比較対象の New Code が存在しないため、判定条件が 0 件になり、
そのまま合格になります。実際 API で見ると conditions が空でした。

これは設計思想で、Clean as You Code(既存の負債は一旦置き、
これから書くコードをきれいに保つ)という考え方です。新規プロジェクトには合いますが、
既存プロジェクトに後から入れて「今の品質」を可視化したい場合は条件を足す必要があります。

解決策

新しいQuality Gateを作成して、Conditions on Overall Code に条件を設定した上でプロジェクトを紐づける
スクリーンショット 2026-09-21 22.24.02.png

再度スキャンを行う
スクリーンショット 2026-09-21 20.41.50.png

何回スキャンしても New Code が空のままだった

スクリーンショット 2026-09-21 22.28.15.png

ここで当然の疑問が出ます。「2 回目・3 回目のスキャンなら、前回との差分が New Code に
なるのでは?」
— ところが、何回スキャンしても空のままでした。

原因は sonar-project.properties のこの 1 行です。

sonar.projectVersion=0.1.0

New Code の既定の定義は **PREVIOUS_VERSION(前回バージョン以降)**です。
API で確認すると理由がはっきりします。

New Code の定義:
  {"projectKey":"qube-test-backend","type":"PREVIOUS_VERSION","inherited":true}

解析履歴:
  11:22:33  projectVersion = "0.1.0"
  11:39:04  projectVersion = "0.1.0"    ← 2 回スキャンしたが同じ
  VERSION イベントは "0.1.0" の 1 つだけ

区切りはスキャン回数ではなく「バージョンが変わったかどうか」で決まります。
バージョンを固定していたため「前回のバージョン」が存在せず、基準点が定まりませんでした。

New Code が機能する条件は 2 つある

やること New Code はどうなるか
バージョンを上げるだけ 基準点はできるが、変更行が無いので 0 件
コードを変えるだけ 基準点が無いので 0 件のまま(今回の状態)
両方 変更分が New Code に現れる

どちらか一方では動きません。

実プロジェクトでは projectVersion を固定しない

検証用に固定で書いたのが原因なので、実務では CI で注入します。

# package.json から取る
-Dsonar.projectVersion=$(node -p "require('./package.json').version")

# git tag から取る
-Dsonar.projectVersion=$(git describe --tags --abbrev=0)

リリースごとに区切りができ、コードは日々変わるので New Code は自動的に機能します。

バージョン運用をしたくない場合は定義を変える

Administration → New Code で 4 種類から選べます。

定義 基準 向いている場面
Previous version(既定) 前回 projectVersion が変わった解析以降 リリース単位で区切る
Number of days 過去 N 日間に変更された行 リリースを切らない継続開発。一番扱いやすい
Specific analysis 指定した解析以降 既存プロジェクトへの導入直後
Reference branch 指定ブランチとの差分 Developer Edition 以上

既存プロジェクトに後から入れるなら Specific analysis で導入日を基準にするのが
実用的です。「今日以降に書いたコードだけを見る」状態が作れます。

git 管理下でないと精度が落ちる

もう 1 つ要因があります。この検証環境は git リポジトリではなかったため、
スキャンのたびにこの警告が出ていました。

WARN  SCM provider autodetection failed. Please use "sonar.scm.provider" to define
      SCM of your project, or disable the SCM Sensor in the project settings.

SonarQube は git の blame から行ごとの変更日を取得して New Code を判定します。
SCM が無いと行レベルの精度が落ちるため、実プロジェクトでは必ず git 管理下で
スキャンしてください(CI で fetch-depth: 0 が必要なのも同じ理由です)。

「既存の負債は据え置き、今回入れた指摘だけで落とす」 — これが SonarQube が
本来想定している運用の姿です。導入時にはご自身の環境で確認してください。

Overall Code を見る条件を追加する

curl -s -u "admin:$PASS" -X POST "$SONAR_URL/api/qualitygates/create" \
  --data-urlencode "name=qube-test strict"

# rating 系は 1=A, 2=B, ... 5=E なので「GT 1」で A 以外を落とす
for cond in "coverage:LT:70" "duplicated_lines_density:GT:3" \
            "reliability_rating:GT:1" "security_rating:GT:1"; do
  IFS=: read -r metric op err <<< "$cond"
  curl -s -u "admin:$PASS" -X POST "$SONAR_URL/api/qualitygates/create_condition" \
    --data-urlencode "gateName=qube-test strict" \
    --data-urlencode "metric=$metric" --data-urlencode "op=$op" \
    --data-urlencode "error=$err"
done

curl -s -u "admin:$PASS" -X POST "$SONAR_URL/api/qualitygates/select" \
  --data-urlencode "gateName=qube-test strict" \
  --data-urlencode "projectKey=qube-test-backend"

なお、新規作成した Quality Gate にはデフォルトの new_* 条件が最初から入っていました。
追加した 4 条件と合わせて 8 条件になります。
※画面上での設定の仕方は、先述した解決策を参照してください。

重要:ゲートを差し替えても再解析するまで判定は変わらない

差し替えた直後に判定を見たら OK のままでした。

qube-test-backend   適用ゲート: qube-test strict
 --- 判定: OK ---          ← 再解析していないので古い判定のまま

再スキャンしたら期待通り落ちました。

 --- 判定: ERROR ---
   [NG!] coverage                                 actual=52.0 (閾値 LT 70)
   [NG!] duplicated_lines                         actual=51 (閾値 GT 3)
   [OK ] new_violations                           actual=0 (閾値 GT 0)← New Code が無いので 0 件扱い
   [NG!] software_quality_reliability_rating      actual=3 (閾値 GT 1)
   [NG!] software_quality_security_rating         actual=3 (閾値 GT 1)    

Quality Gate の判定は解析時に評価されるので、CI で運用する場合は
「ゲートを変えたら次の解析から効く」と理解しておく必要があります。


8. Fail → 修正 → Pass をやってみる

backend の指摘を実際に直しました。主な修正内容です。

# 修正前
SECRET_KEY = "django-insecure-3k9v2m8x7q1w..."   # secrets:S6687
DEBUG = True                                      # python:S4507
ALLOWED_HOSTS = ["*"]

# 修正後
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY") or get_random_secret_key()
DEBUG = os.environ.get("DJANGO_DEBUG", "false").lower() == "true"
ALLOWED_HOSTS = [h.strip() for h in
                 os.environ.get("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1").split(",")]
# 修正前: python:S4790 / S2245 / S4830
return hashlib.md5(raw_password.encode()).hexdigest()
suffix = "".join(random.choice(alphabet) for _ in range(16))
requests.post(url, verify=False, timeout=5)

# 修正後
return make_password(raw_password)              # Django 標準(PBKDF2)
return f"{todo_id}-{secrets.token_urlsafe(12)}" # secrets モジュール
requests.post(url, timeout=5)                   # verify は既定(有効)のまま

認知的複雑度 28 の関数は、役割ごとに 3 つの関数へ分割しました
(_count_status / _count_priority / _collect_warnings)。
コピペされていた 3 つの CSV エクスポート関数は 1 つに統合しました。

そしてテストを追加してカバレッジを 96%(SonarQube 表示 78.9%)まで上げました。
スクリーンショット 2026-09-21 22.35.21.png

coverage.py の 96% と SonarQube の 78.9% がずれるのは、集計対象が違うためです。
.coveragerc の omit で除外したファイルも SonarQube 側では
「カバレッジ 0% のファイル」として計上されます。

画面上から問題箇所を特定するには

プロジェクト画面上のIssues を選択して表示されているものを選択
スクリーンショット 2026-09-21 22.48.11.png

詳細画面上には、その問題の該当箇所となぜ問題なのかを教えてくれます。
スクリーンショット 2026-09-21 22.48.30.png
スクリーンショット 2026-09-21 22.48.48.png

修正の結果、新しい指摘が出た

再スキャンしたら、直したはずが今度は別の 4 件が出ました。

ルール 場所 内容
python:S5863 ×2 tests/test_services.py 同じ式を左右に置いた assert
python:S5443 todos/services.py /tmp(誰でも書けるディレクトリ)の使用
python:S125 config/settings.py 「コメントアウトされたコード」

S5863 は自分のテストの書き方の問題でした。

# 指摘される
assert hash_password("same") != hash_password("same")

# 一度変数に受ける
first = hash_password("same")
second = hash_password("same")
assert first != second

S5443 は /tmp/todo-archive.log を既定値にしていたのが原因で、アプリ配下に変更。

最後の 1 件は誤検知だった

python:S125 が指した行はこれです。

# 環境変数から読み、無ければ実行ごとに使い捨ての鍵を生成する。

日本語のコメントを「コメントアウトされたコード」と誤検知していました。
日本語のコメントを書く日本語圏のプロジェクトでは、これは避けられません。

コードを歪めて回避するのではなく、理由を添えて False Positive として解決するのが
正しい運用です。画面なら指摘を開いて False Positive を選ぶだけ。API ならこうです。

# 理由をコメントとして残す(後から判断を追えるように)
curl -s -u "admin:$PASS" -X POST "$SONAR_URL/api/issues/add_comment" \
  --data-urlencode "issue=$ISSUE_KEY" \
  --data-urlencode "text=日本語コメントをコードと誤認した誤検知のため"

curl -s -u "admin:$PASS" -X POST "$SONAR_URL/api/issues/do_transition" \
  --data-urlencode "issue=$ISSUE_KEY" \
  --data-urlencode "transition=falsepositive"

画面操作からなら
スクリーンショット 2026-09-21 21.15.19.png
スクリーンショット 2026-09-21 22.52.10.png

Quality Gate の差し替えと違い、False Positive のマークは即座に反映されました。
この操作だけで判定が ERROR → OK に変わりました。

qube-test-backend   適用ゲート: qube-test strict
 --- 判定: OK ---

余談:git 管理下でスキャンする

検証中ずっとこの警告が出ていました。

WARN  SCM provider autodetection failed. Please use "sonar.scm.provider" to define
      SCM of your project, or disable the SCM Sensor in the project settings.

解析対象を git リポジトリにしていなかったためです。解析自体は成功しますが、
SonarQube は git の blame 情報から「その行がいつ書かれたか」を判断して
New Code を決めます
。SCM 情報が無いと New Code の判定が正しく働かないので、
実プロジェクトでは必ず git 管理下でスキャンしてください
(CI では fetch-depth: 0 が必要なのも同じ理由です)。

余談:指摘の件数が合わないときは resolved=false

修正後に API で指摘を数えたら 18 件返ってきて「直ってない?」と焦りました。
/api/issues/search は resolved を指定しないと修正済み(FIXED / CLOSED)も返します。

# 未解決のみ
curl -s -u "admin:$PASS" "$SONAR_URL/api/issues/search?components=$KEY&resolved=false"

未解決だけに絞ったら 4 件で、ダッシュボードと一致しました。


(未検証)9. GitHub Actions 連携

SONAR_TOKEN と SONAR_HOST_URL を Secrets に入れて使います(先行記事と同じ)。
projectBaseDir を変えて 2 ジョブに分けます。

name: SonarQube

# Community Build はブランチ解析・PR デコレーションに非対応。
# PR ごとに解析を投げても結果が分離されず、同じプロジェクトを上書きしてしまう。
# そのため既定では main への push のみで動かす。
on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  backend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
        with:
          fetch-depth: 0     # SCM 情報を使うので浅いクローンにしない

      - uses: actions/setup-python@v6
        with:
          python-version: '3.13'

      - run: pip install -r backend/requirements.txt

      # カバレッジ生成は「スキャンより前」。逆にすると Coverage が 0% になる
      - name: テストとカバレッジ生成
        working-directory: backend
        run: |
          coverage run -m pytest
          coverage xml

      - uses: SonarSource/sonarqube-scan-action@v8
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
        with:
          projectBaseDir: backend

      - uses: sonarsource/sonarqube-quality-gate-action@master
        timeout-minutes: 10
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
        with:
          pollingTimeoutSec: 600

frontend 側は setup-node + npm ci + npm run test:coverage に置き換えるだけです。

注意点を整理します。

  • sonarqube-scan-action は v8 が最新(先行記事の頃より進んでいます)
  • Quality Gate で CI を落とすには sonarqube-quality-gate-action を併用。
    scan-action と組み合わせる場合 scanMetadataReportFile の指定は不要
  • セルフホストの SonarQube は GitHub Actions ランナーから到達できる必要があります。
    社内 LAN に置くなら self-hosted runner が必要です
  • Community Build で PR 単位の結果を見たいなら Developer Edition 以上が必要

10. SonarQube は「どこまで」見ているのか

「静的解析」と一括りにされますが、実際には深さに段階があります。ここを理解しておくと、
何を SonarQube に任せられて、何は別のツールが必要かの判断ができます。

解析の深さは 4 段階

深さ 見ているもの 今回の実例 Community Build
① 構文 コードの形 TODO コメント、except: pass の形 ✅
② 型 型チェッカーを動かして型を解決 下記参照 ✅
③ 関数内のフロー 制御フロー・データフロー S1763 到達不能コード、S1854 代入したが読まれない ✅
④ 関数/ファイルを越えた追跡 taint analysis (検出されなかった) ❌ Developer 以上

②については、スキャンログが証拠になります。

INFO  Found 1 tsconfig.json file(s): [/usr/src/frontend/tsconfig.json]
INFO  Creating TypeScript(6.0.3) program with configuration file .../tsconfig.json
INFO  Analyzing 16 file(s) from tsconfig ... (76 total files in program)

tsconfig.json を読んで TypeScript の型チェッカーを動かしています(76 total files は
node_modules の型定義を含む数)。

そのおかげで面白い挙動がありました。== をわざと書いたのに指摘されなかったのです。

if (todo.title == '') {   // 指摘なし

型情報から todo.title が string と分かるため、== でも === と同じ結果になると
判断して黙った
わけです。単純な構文マッチではこうなりません。

脆弱性は 3 種類に分けて考える

「SonarQube は脆弱性を見るのか」への答えは 「種類による」 です。

型 例 Community Build 補う手段
危険な API / 設定の誤用 MD5、DEBUG=True、verify=False、秘密鍵のハードコード ✅ 今回 8 件検出 —
インジェクション系 SQLi、XSS、コマンド注入、パストラバーサル ❌ Semgrep、bandit、eslint-plugin-security
依存ライブラリの既知脆弱性(CVE) requirements.txt の古いパッケージ ❌ Dependabot、pip-audit、npm audit、Trivy

1 つ目が検出できるのは「1 箇所を見れば判断できる」からです。hashlib.md5( と書いてあれば、
それだけで危険と分かります。

2 つ目は入力から出力までの経路を追う必要があるため、taint analysis が要ります。

3 つ目は特に見落としやすいので注意してください。スキャンログにこう出ます。

INFO  ------------- Gather SCA dependencies on project
INFO  Dependency analysis skipped        ← スキップされている

SCA(Software Composition Analysis)は Advanced Security アドオンで Enterprise Edition
以上
が必要です。Community Build では依存ライブラリの CVE を一切検出しません。

見ないもの

  • 実行時の動作 — 静的解析なのでコードは動かしません
  • テストが正しいか — テストは実行せず、カバレッジレポートを読むだけです
    (だから「アサーションの無いテスト」は構文から S2699 で指摘されました)
  • 性能 — 実測しないので遅いコードは分かりません

11. Community Build でどこまでできるか

実際に触って分かった線引きです。

できたこと

  • Python / TypeScript / Vue(SFC) / CSS / HTML の解析
  • カバレッジの取り込み(Cobertura XML / LCOV)
  • 重複コードの検出(コピペ関数を S4144 と Duplications 10.9% で検出)
  • 認知的複雑度の定量化(28 → 上限 15 という形で出る)
  • Quality Gate のカスタマイズと CI での判定
  • Web API による初期化・結果取得・誤検知処理の自動化

できなかったこと(Developer Edition 以上が必要)

  • ブランチ解析・PR デコレーション
  • モノレポとしての一元管理(2 プロジェクトに分けて回避)
  • taint analysis(SQL インジェクション、パストラバーサル等のデータフロー追跡)

できなかったこと(Enterprise Edition + Advanced Security アドオンが必要)

  • SCA(依存ライブラリの既知脆弱性・ライセンス違反の検出)
    … ログに Dependency analysis skipped と出て、requirements.txt /
    package.json は一切チェックされない

社内展開では、まず Community Build で「複雑度・重複・カバレッジの可視化」を回し、
PR 連携やインジェクション検出が必要になった段階で有償版を検討する、
という順序が現実的だと思います。

なお日本語化は、クレスコさんの SonarQube Japanese Pack を
extensions/plugins に置いて再起動する形です(今回は英語 UI のまま検証しました。
プラグインはバージョン対応の確認が必要です)。


まとめ

後編で押さえた要点です。

  1. 初回スキャンで Quality Gate は素通りする。 Sonar way の条件は 4 つ全部が
    New Code 側。既存コードを評価したいなら Overall Code の条件を足して再解析する

  2. sonar.projectVersion を固定すると New Code は永久に空のまま。
    区切りはスキャン回数ではなくバージョンが変わったかどうかで決まる。
    CI で注入するか、New Code の定義を Number of days /
    Specific analysis に変える。git 管理下でないと行レベルの精度も落ちる

  3. 反映のタイミングが操作によって違う

    操作 再解析が必要か
    Quality Gate の条件を変更 必要
    Quality Profile のルールを変更 必要
    指摘を False Positive にする 不要(即時)
  4. v-html や console.log は検出されない。 原因は「ルールが存在しない」と
    「存在するが無効」の 2 パターンで、後者は Quality Profile をコピーして有効化できる

  5. ESLint / ruff と併用する前提で設計する。 SonarQube の強みは、リンターが見ない
    認知的複雑度・重複・カバレッジの定量化と、推移の可視化

  6. 日本語コメントは S125 で誤検知される。コードを歪めて回避せず、
    理由を添えて False Positive で解決する

  7. 脆弱性は「設定・API の誤用」までしか見ない。 インジェクション系は
    Developer Edition 以上、依存ライブラリの CVE は Enterprise + Advanced Security が必要

社内に入れるときの現実的な順序

前後編を通して検証した結果、この順序を勧めます。

  1. まず Community Build で「可視化」だけ始める — Quality Gate は既定の Sonar way
    (New Code のみ)のままにして、既存の負債では落とさない
  2. 新規に書くコードだけきれいに保つ(Clean as You Code)。これが SonarQube の
    設計思想に沿った使い方で、チームの抵抗も少ない
  3. 既存コードの現状を把握したいときだけ Overall Code 条件を足した別ゲートを作り、
    レポート目的で使う
  4. 足りない部分は他ツールで埋める — v-html は ESLint、依存の CVE は DependabotやTrivy
  5. PR 連携やインジェクション検出が必要になった段階で有償版を検討する

検証環境一式

Docker Compose / Makefile / 自動化スクリプト / 指摘を仕込んだアプリは、
そのまま動く形でまとめてあります。make all だけで起動から解析結果の表示まで通ります。

cp .env.example .env
make all
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?