以下の内容はhttps://kazuhira-r.hatenablog.com/entry/2025/11/03/181527より取得しました。


SASTツール、Semgrep Community Editionを試す

これは、なにをしたくて書いたもの?

SemgrepというSASTツールをちょっと試してみようかなということで。

Semgrep

SemgrepはSASTツールの一種です。Webサイトはこちら。

Semgrep App Security Platform | AI-assisted SAST, SCA and Secrets Detection

Semgrepにはプロダクト、サービス等いくつかの製品があります。

SASTだったりSCAだったり、シークレットをスキャンするものだったりといくつか製品があるのですが、SaaS(プラットフォーム)としても
利用できます。

今回は、SASTのCommunity EditionであるSemgrep Community Editionを使います。

ドキュメントはこちら。

Docs home | Semgrep

対応している言語は以下になります。

Supported languages | Semgrep

Python 3.9以上が必要です。OSはLinuxmacOSを想定していて、WindowsはBeta対応みたいですね。

Prerequisites | Semgrep

Semgrepの商用版とCommunity Editionの違いはこちらに書かれています。

Semgrep AppSec Platform versus Community Edition | Semgrep

ここでは商用版としてSemgrep AppSec Platformを挙げています。こちらに含まれるのはSemgrep Code(SAST)、Semgrep Supply Chain(SCA)、
Semgrep Secrets(シークレットスキャン)です。

Semgrep Community Editionからの視点では、Semgrep Codeに含まれている「Pro Rules」というルールが含まれていることが大きな差に
なります。ここにはフレームワーク固有のルールなどが多数含まれています。
またSemgrep Community Editionのスキャンは単一ファイル内に限定されますが、Semgrep Codeではファイル間の解析も行えます。

以下の図がSemgrep Community EditionとSemgrep AppSec Platformの差ですが、パッと見が見ているようで中でやっていることが大きく異なる
ことがわかります。

つまり、より広く・精度良く、解析したければ商用版を使ってねということですね(それはそうでしょう)。

実行はSemgrep Community EditionはローカルマシンでのCLIでの利用となっています。Semgrep AppSec PlatformではCI環境、マネージドスキャン
(Web)、CLIIDE、pre-commitと選択肢が広がります。

商用版でサポートされているSCMはこちら。

Supported source code managers | Semgrep

Semgrep Community EditionをCI環境で使えないわけではないですが、単純に自分でSemgrepのCLIをCIのジョブに組み込むことになります。

Semgrep Community EditionのGitHubリポジトリーはこちら。

GitHub - semgrep/semgrep: Lightweight static analysis for many languages. Find bug variants with patterns that look like source code.

こちらを見るとSemgrepは文字列のパターンマッチであるgrepと異なり、コードに対する意味的なgrepを行うということがわかります。

Semgrep is semantic grep for code. While running grep "2" would only match the exact string 2, Semgrep would match x = 1; y = x + 1 when searching for 2. Semgrep rules look like the code you already write; no abstract syntax trees, regex wrestling, or painful DSLs.

ちなみにOCamlで実装されているようです。

そしてルールはこちらです。

GitHub - semgrep/semgrep-rules: Semgrep Community Edition rules, maintained by Semgrep and the community. Free to use under the Semgrep Rules License.

そこそこあるように見えるのですが、Semgrep Registryでルールを探す時にCommuty EditionのみとProのみでそれぞれ絞り込むと数がまったく
違うことがわかったりします。

Semgrep Registry

基本的にSemgrep AppSec Platformを随所で勧めてくるのですが、ひとまずSemgrep Community Editionを使ってみたいのです。

なのですが、ドキュメントを見ていてもSemgrep Community Editionの使い方がなかなかわからなかったので、1度使ってみようと思ったのが
今回のエントリーを書いた動機です。

それでは少し試してみましょう。

OpengrepとGlobstar

少し余談です。Semgrepは、2024年12月にライセンスの変更をしています。今のSemgrep Community EditionはSemgrep OSSと呼ばれていたものが
名を変えたものみたいです。

Important updates to Semgrep OSS | Semgrep

ライセンスの変更はルールに対するものが大きく、Semgrepの競合製品やSaaS製品でルールを管理しているベンダーに対して制限
(というか廃止)を要求するものになっています。Semgrep OSSそのもののライセンスは変わっていないみたいです(名前が変わっただけ)。

結果、OpengrepというSemgrep OSSのフォークが生まれました。

Opengrep - The open-source code security engine

GitHub - opengrep/opengrep: 🔎 Static code analysis engine to find security issues in code.

GitHub - opengrep/opengrep-rules

ライセンス変更後にルールセットを自由化するため、OpengrepがSemgrepをフォーク - InfoQ

Semgrepのドキュメント内にOpengrepとの比較まであります。

Compare Semgrep to Opengrep | Semgrep

またDeepSourceからはGlobstarというものがリリースされています。

GitHub - DeepSourceCorp/globstar: Globstar is a fast, feature-rich, and open-source static analysis toolkit for writing and running code checkers. Based on tree-sitter.

GitHub - DeepSourceCorp/globstar: Globstar is a fast, feature-rich, and open-source static analysis toolkit for writing and running code checkers. Based on tree-sitter.

Open-Source Alternatives Amid Semgrep Licensing Controversy – Unite.AI

個人的にはGlobstarはちょっと気になるものの、まずはSemgrepからかなと思います。

環境

今回の環境はこちら。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04.3 LTS
Release:        24.04
Codename:       noble


$ uname -srvmpio
Linux 6.8.0-86-generic #87-Ubuntu SMP PREEMPT_DYNAMIC Mon Sep 22 18:03:36 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

Semgrepのインストールにはpipが必要になります。

$ python3 --version
Python 3.12.3


$ pip3 --version
pip 24.0 from /usr/lib/python3/dist-packages/pip (python 3.12)

Semgrepをインストールする

まずはSemgrepをインストールしましょう。なお、ここからはSemgrep Community Editionのことを単純に「Semgrep」と書くことにします。

インストールはpipで行うようです。

Quickstart | Semgrep

Semgrep / Getting started / Option 2: Getting started from the CLI

実行(全体に入れるので--break-system-packagesを付与)。

$ pip3 install --break-system-packages semgrep

けっこうな数のパッケージがついてくるみたいです。

Successfully installed annotated-types-0.7.0 anyio-4.11.0 boltons-21.0.0 bracex-2.6 click-8.1.8 click-option-group-0.5.9 exceptiongroup-1.2.2 face-24.0.0 glom-22.1.0 googleapis-common-protos-1.71.0 h11-0.16.0 httpcore-1.0.9 httpx-0.28.1 httpx-sse-0.4.3 importlib-metadata-8.7.0 jsonschema-4.25.1 jsonschema-specifications-2025.9.1 mcp-1.16.0 opentelemetry-api-1.37.0 opentelemetry-exporter-otlp-proto-common-1.37.0 opentelemetry-exporter-otlp-proto-http-1.37.0 opentelemetry-instrumentation-0.58b0 opentelemetry-instrumentation-requests-0.58b0 opentelemetry-proto-1.37.0 opentelemetry-sdk-1.37.0 opentelemetry-semantic-conventions-0.58b0 opentelemetry-util-http-0.58b0 peewee-3.18.2 protobuf-6.33.0 pydantic-2.12.3 pydantic-core-2.41.4 pydantic-settings-2.11.0 python-dotenv-1.2.1 python-multipart-0.0.20 referencing-0.37.0 rich-13.5.3 rpds-py-0.28.0 ruamel.yaml-0.18.16 ruamel.yaml.clib-0.2.14 semgrep-1.142.0 sniffio-1.3.1 sse-starlette-3.0.3 starlette-0.50.0 tomli-2.0.2 typing-extensions-4.15.0 typing-inspection-0.4.2 uvicorn-0.38.0 wcmatch-8.5.2 wrapt-1.17.3 zipp-3.23.0

ちょっと通常使っているOSにこのインストール方法を取るのは気が引けますね…。

$ pip3 list
Package                                  Version
---------------------------------------- --------------
annotated-types                          0.7.0
anyio                                    4.11.0
attrs                                    23.2.0
Automat                                  22.10.0
Babel                                    2.10.3
bcc                                      0.29.1
bcrypt                                   3.2.2
blinker                                  1.7.0
boltons                                  21.0.0
boto3                                    1.34.46
botocore                                 1.34.46
bracex                                   2.6
certifi                                  2023.11.17
chardet                                  5.2.0
click                                    8.1.8
click-option-group                       0.5.9
cloud-init                               25.2
colorama                                 0.4.6
command-not-found                        0.3
configobj                                5.0.8
constantly                               23.10.4
cryptography                             41.0.7
dbus-python                              1.3.2
distro                                   1.9.0
distro-info                              1.7+build1
exceptiongroup                           1.2.2
face                                     24.0.0
glom                                     22.1.0
googleapis-common-protos                 1.71.0
h11                                      0.16.0
httpcore                                 1.0.9
httplib2                                 0.20.4
httpx                                    0.28.1
httpx-sse                                0.4.3
hyperlink                                21.0.0
idna                                     3.6
importlib_metadata                       8.7.0
incremental                              22.10.0
Jinja2                                   3.1.2
jmespath                                 1.0.1
jsonpatch                                1.32
jsonpointer                              2.0
jsonschema                               4.25.1
jsonschema-specifications                2025.9.1
launchpadlib                             1.11.0
lazr.restfulclient                       0.14.6
lazr.uri                                 1.0.6
markdown-it-py                           3.0.0
MarkupSafe                               2.1.5
mcp                                      1.16.0
mdurl                                    0.1.2
netaddr                                  0.8.0
netifaces                                0.11.0
oauthlib                                 3.2.2
opentelemetry-api                        1.37.0
opentelemetry-exporter-otlp-proto-common 1.37.0
opentelemetry-exporter-otlp-proto-http   1.37.0
opentelemetry-instrumentation            0.58b0
opentelemetry-instrumentation-requests   0.58b0
opentelemetry-proto                      1.37.0
opentelemetry-sdk                        1.37.0
opentelemetry-semantic-conventions       0.58b0
opentelemetry-util-http                  0.58b0
packaging                                24.0
peewee                                   3.18.2
pexpect                                  4.9.0
pip                                      24.0
protobuf                                 6.33.0
ptyprocess                               0.7.0
pyasn1                                   0.4.8
pyasn1-modules                           0.2.8
pydantic                                 2.12.3
pydantic_core                            2.41.4
pydantic-settings                        2.11.0
Pygments                                 2.17.2
PyGObject                                3.48.2
PyHamcrest                               2.1.0
PyJWT                                    2.7.0
pyOpenSSL                                23.2.0
pyparsing                                3.1.1
pyrsistent                               0.20.0
pyserial                                 3.5
python-apt                               2.7.7+ubuntu5
python-dateutil                          2.8.2
python-debian                            0.1.49+ubuntu2
python-dotenv                            1.2.1
python-magic                             0.4.27
python-multipart                         0.0.20
pytz                                     2024.1
PyYAML                                   6.0.1
referencing                              0.37.0
requests                                 2.31.0
rich                                     13.5.3
rpds-py                                  0.28.0
ruamel.yaml                              0.18.16
ruamel.yaml.clib                         0.2.14
s3transfer                               0.10.1
semgrep                                  1.142.0
service-identity                         24.1.0
setuptools                               68.1.2
six                                      1.16.0
sniffio                                  1.3.1
sos                                      4.9.2
sse-starlette                            3.0.3
ssh-import-id                            5.11
starlette                                0.50.0
systemd-python                           235
tomli                                    2.0.2
Twisted                                  24.3.0
typing_extensions                        4.15.0
typing-inspection                        0.4.2
ubuntu-pro-client                        8001
ufw                                      0.36.2
unattended-upgrades                      0.1
urllib3                                  2.0.7
uvicorn                                  0.38.0
wadllib                                  1.3.6
wcmatch                                  8.5.2
wheel                                    0.42.0
wrapt                                    1.17.3
zipp                                     3.23.0
zope.interface                           6.1

インストール先は$HOME/.local/binです。

$ which semgrep
$HOME/.local/bin/semgrep

バージョン。

$ semgrep --version
1.142.0

ヘルプ。

$ semgrep --help
Usage: semgrep [OPTIONS] COMMAND [ARGS]...

  To get started quickly, run `semgrep scan --config auto`

  Run `semgrep SUBCOMMAND --help` for more information on each subcommand

  If no subcommand is passed, will run `scan` subcommand by default

Options:
  -h, --help  Show this message and exit.

Commands:
  ci                   Run Semgrep on a git diff (for use in CI)
  install-semgrep-pro  Install the Semgrep Pro Engine
  login                Obtain and save credentials for semgrep.dev
  logout               Remove locally stored credentials to semgrep.dev
  lsp                  Start the Semgrep LSP server (useful for IDEs)
  publish              Upload rule to semgrep.dev
  scan                 Run Semgrep rules on local folders or files
  show                 Show various types of information
  test                 Test the rules (EXPERIMENTAL improvements over scan --test)
  validate             Validate the rules (EXPERIMENTAL improvements over scan --validate)
  mcp                  Start the Semgrep MCP server

単純に実行するにはsemgrep scan --config autoがよさそうです。

またsemgrepコマンドだけを入力しても使い方がわかります。

$ semgrep

┌──── ○○○ ────┐
│ Semgrep CLI │
└─────────────┘
Semgrep CLI scans your code for bugs, security and dependency vulnerabilities.

For more information about Semgrep, visit https://semgrep.dev

Get Started:
  Run `semgrep login && semgrep ci` to enable Pro rules, Semgrep Supply Chain,
  and secrets scanning. Without logging in, Semgrep CLI will only run the free
  open-source rules available at https://semgrep.dev/r.

Commands:
  semgrep login                Enable Pro rules, Supply Chain, and secrets scanning
  semgrep ci                   Run Semgrep on a git diff (for use in CI)
  semgrep scan                 Run Semgrep rules on local folders or files

Help:
  semgrep COMMAND --help       For more information on each command

For the CLI docs visit https://semgrep.dev/docs/cli-reference

ここで気づきますが、Semgrep Community Editionを使う場合はローカルファイルのスキャンになるのでsemgrep scanを使うことになります。

Semgrepを試してみる

まずはチュートリアル的なことをやってみます。ここまでやってきて、Semgrep Community Edition用のドキュメントも少しだけあることに
気づきました(笑)。

Get started | Semgrep

すごく目立たないところにあります…。

サポートしている言語についても少し違った表現で書かれていますね。

Supported languages | Semgrep

semgrepコマンドはCommunity Editionでも商用版でも変わらないようなので、このまま進めます。ログインすると商用版の機能が使えるように
なるようなので。

チュートリアルに習ってこんなPythonスクリプトを作成。

app.py

# app.py
import os

user_input = input("Enter a Directory: ")
os.system("ls " + user_input)

Get started with Semgrep Community Edition / Create a test file for use with Semgrep CE

実行。

$ python3 app.py
Enter a Directory: .
app.py

このスクリプトは、利用者から受け取った文字列をそのまま外部コマンド(ls)の引数として渡します。

よってOSコマンドインジェクションが可能です。

$ python3 app.py
Enter a Directory: .; cat /etc/passwd
app.py
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin

〜以降省略〜

では、semgrepを実行してみましょう。

$ semgrep scan

どうもルールはレジストリーから取得するようです。

┌──── ○○○ ────┐
│ Semgrep CLI │
└─────────────┘

⠏ Loading rules from registry...

結果。


┌──── ○○○ ────┐
│ Semgrep CLI │
└─────────────┘


Scanning 1 file (only git-tracked) with:

✔ Semgrep OSS
  ✔ Basic security coverage for first-party code vulnerabilities.

✘ Semgrep Code (SAST)
  ✘ Find and fix vulnerabilities in the code you write with advanced scanning and expert security rules.

✘ Semgrep Supply Chain (SCA)
  ✘ Find and fix the reachable vulnerabilities in your OSS dependencies.

💎 Get started with all Semgrep products via `semgrep login`.
✨ Learn more at https://sg.run/cloud.

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00


┌──────────────┐
│ Scan Summary │
└──────────────┘
✅ Scan completed successfully.
 • Findings: 0 (0 blocking)
 • Rules run: 291
 • Targets scanned: 1
 • Parsed lines: ~100.0%
 • No ignore information available
Ran 291 rules on 1 file: 0 findings.
💎 Missed out on 1390 pro rules since you aren't logged in!
⚡ Supercharge Semgrep OSS when you create a free account at https://sg.run/rules.
(need more rules? `semgrep login` for additional free Semgrep Registry rules)


✨ If Semgrep missed a finding, please send us feedback to let us know!
   See https://semgrep.dev/docs/reporting-false-negatives/

0件でしたが…。

 • Findings: 0 (0 blocking)

--config autoを付けて実行してみます。

$ semgrep --config auto

結果およびルール数が変わらないので、省略しても同じみたいですね。

✅ Scan completed successfully.
 • Findings: 0 (0 blocking)
 • Rules run: 291
 • Targets scanned: 1
 • Parsed lines: ~100.0%
 • No ignore information available
Ran 291 rules on 1 file: 0 findings.

チュートリアルに従って、適用するルールを変更してみましょう。

$ semgrep --config 'p/python-command-injection'

すると、結果がだいぶ変わりました。

┌──── ○○○ ────┐
│ Semgrep CLI │
└─────────────┘


Scanning 1 file (only git-tracked) with 24 Code rules:

  CODE RULES
  Scanning 1 file with 24 python rules.

  SUPPLY CHAIN RULES

  💎 Sign in with `semgrep login` and run
     `semgrep ci` to find dependency vulnerabilities and
     advanced cross-file findings.


  PROGRESS

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00


┌────────────────┐
│ 1 Code Finding │
└────────────────┘

    app.py
   ❯❯❱ python.lang.security.audit.dangerous-system-call-audit.dangerous-system-call-audit
          Found dynamic content used in a system call. This is dangerous if external data can reach this
          function call because it allows a malicious actor to execute commands. Use the 'subprocess' module
          instead, which is easier to use without accidentally exposing a command injection vulnerability.
          Details: https://sg.run/2WL0

            5┆ os.system("ls " + user_input)



┌──────────────┐
│ Scan Summary │
└──────────────┘
✅ Scan completed successfully.
 • Findings: 1 (1 blocking)
 • Rules run: 24
 • Targets scanned: 1
 • Parsed lines: ~100.0%
 • No ignore information available
Ran 24 rules on 1 file: 1 finding.

どうなっているんでしょうね…。

p/で指定しているのは、ルールをまとめたルールセットのようです。

ルールはSemgrep Registryで確認できます。

Semgrep Registry / Explore

ルールセットはルールをまとめたものです。

たとえばPython用のルールセット。

https://semgrep.dev/p/python

なのですが、p/python-command-injectionというルールセットはこのExploreから見つけられません。

URLを直接指定すれば見つけられますけどね。どうなっているんでしょう…。

https://semgrep.dev/p/python-command-injection

このあたりでやってもダメでした。

$ semgrep --config 'p/default'
$ semgrep --config 'p/python'

こうなると、ルールセットの一覧が見たくなるのですがそれはできなさそうです。

どうなっているんでしょうね?

ちなみに--debugオプションを付けてみると

$ semgrep --config auto --debug

以下のように一時的に出力されるJSONファイルを読めばどういうルールで実行されているかはわかりそうです。

[00.05][INFO]: Parsing rules in /tmp/tmp_ja8xkz7.json
[00.23][DEBUG](default): read targets from file: /tmp/tmpwh0sugb5
[00.23][DEBUG](default): Core_scan.scan_exn { Core_scan_config.rule_source = Rule_file (/tmp/tmp_ja8xkz7.json);

まあ、autoはいろんな言語入りでとっかかりで使うもののようなので

p/auto

デフォルトを使った方がよいのかもしれませんね。

Cheat Sheets | Semgrep

たとえば、app.pyチートシートの例に直して

app.py

import subprocess
import sys

# Vulnerable
user_input = "foo && cat /etc/passwd" # value supplied by user
subprocess.call("grep -R {} .".format(user_input), shell=True)

# Vulnerable
user_input = "cat /etc/passwd" # value supplied by user
subprocess.run(["bash", "-c", user_input], shell=True)

# Not vulnerable
user_input = "cat /etc/passwd" # value supplied by user
subprocess.Popen(['ls', '-l', user_input])

# Not vulnerable
subprocess.check_output('ls -l dir/')

Command Injection in Python | Semgrep

ルールセットをp/defaultで実行するとOSコマンドインジェクションが検出されるようになります。

$ semgrep scan --config p/default

┌──── ○○○ ────┐
│ Semgrep CLI │
└─────────────┘


Scanning 1 file (only git-tracked) with 1062 Code rules:

  CODE RULES

  Language      Rules   Files          Origin      Rules
 ─────────────────────────────        ───────────────────
  python          243       1          Community    1062
  <multilang>      48       1


  SUPPLY CHAIN RULES

  💎 Sign in with `semgrep login` and run
     `semgrep ci` to find dependency vulnerabilities and
     advanced cross-file findings.


  PROGRESS

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00


┌─────────────────┐
│ 2 Code Findings │
└─────────────────┘

    app.py
   ❯❯❱ python.lang.security.audit.subprocess-shell-true.subprocess-shell-true
          Found 'subprocess' function 'call' with 'shell=True'. This is dangerous because this call will spawn
          the command using a shell process. Doing so propagates current shell settings and variables, which
          makes it much easier for a malicious actor to execute commands. Use 'shell=False' instead.
          Details: https://sg.run/J92w

           ▶▶┆ Autofix ▶ False
            6┆ subprocess.call("grep -R {} .".format(user_input), shell=True)
            ⋮┆----------------------------------------
   ❯❯❱ python.lang.security.audit.subprocess-shell-true.subprocess-shell-true
          Found 'subprocess' function 'run' with 'shell=True'. This is dangerous because this call will spawn
          the command using a shell process. Doing so propagates current shell settings and variables, which
          makes it much easier for a malicious actor to execute commands. Use 'shell=False' instead.
          Details: https://sg.run/J92w

           ▶▶┆ Autofix ▶ False
           10┆ subprocess.run(["bash", "-c", user_input], shell=True)



┌──────────────┐
│ Scan Summary │
└──────────────┘
✅ Scan completed successfully.
 • Findings: 2 (2 blocking)
 • Rules run: 291
 • Targets scanned: 1
 • Parsed lines: ~100.0%
 • No ignore information available
Ran 291 rules on 1 file: 2 findings.
💎 Missed out on 1390 pro rules since you aren't logged in!
⚡ Supercharge Semgrep OSS when you create a free account at https://sg.run/rules.

p/default

ただ、このコードの場合はautoでも検出されるんですけどね。本当によくわかりません…。

$ semgrep scan --config auto

┌──── ○○○ ────┐
│ Semgrep CLI │
└─────────────┘


Scanning 1 file (only git-tracked) with:

✔ Semgrep OSS
  ✔ Basic security coverage for first-party code vulnerabilities.

✘ Semgrep Code (SAST)
  ✘ Find and fix vulnerabilities in the code you write with advanced scanning and expert security rules.

✘ Semgrep Supply Chain (SCA)
  ✘ Find and fix the reachable vulnerabilities in your OSS dependencies.

💎 Get started with all Semgrep products via `semgrep login`.
✨ Learn more at https://sg.run/cloud.

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00


┌─────────────────┐
│ 2 Code Findings │
└─────────────────┘

    app.py
   ❯❯❱ python.lang.security.audit.subprocess-shell-true.subprocess-shell-true
          Found 'subprocess' function 'call' with 'shell=True'. This is dangerous because this call will spawn
          the command using a shell process. Doing so propagates current shell settings and variables, which
          makes it much easier for a malicious actor to execute commands. Use 'shell=False' instead.
          Details: https://sg.run/J92w

           ▶▶┆ Autofix ▶ False
            6┆ subprocess.call("grep -R {} .".format(user_input), shell=True)
            ⋮┆----------------------------------------
   ❯❯❱ python.lang.security.audit.subprocess-shell-true.subprocess-shell-true
          Found 'subprocess' function 'run' with 'shell=True'. This is dangerous because this call will spawn
          the command using a shell process. Doing so propagates current shell settings and variables, which
          makes it much easier for a malicious actor to execute commands. Use 'shell=False' instead.
          Details: https://sg.run/J92w

           ▶▶┆ Autofix ▶ False
           10┆ subprocess.run(["bash", "-c", user_input], shell=True)



┌──────────────┐
│ Scan Summary │
└──────────────┘
✅ Scan completed successfully.
 • Findings: 2 (2 blocking)
 • Rules run: 291
 • Targets scanned: 1
 • Parsed lines: ~100.0%
 • No ignore information available
Ran 291 rules on 1 file: 2 findings.
💎 Missed out on 1390 pro rules since you aren't logged in!
⚡ Supercharge Semgrep OSS when you create a free account at https://sg.run/rules.

ちなみに、ルールは複数指定できるようです。

$ semgrep scan --config p/default --config p/python

SemgrepでWebGoatをスキャンする

脆弱性込みのアプリケーションといえば、WebGoatです。こちらにSemgrepを実行してみましょう。

OWASP WebGoat | OWASP Foundation

GitHub - WebGoat/WebGoat: WebGoat is a deliberately insecure application

WebGoatをclone。

$ git clone https://github.com/WebGoat/WebGoat
$ cd WebGoat
$ git checkout v2025.3

Semgrepを実行してみます。

$ semgrep scan --config p/default


## 以下のようにしても適用されるルールはあまり変わりませんでした
## defaultにけっこう含まれているようです
$ semgrep scan --config p/default --config p/java --config p/javascript`

ファイルごとのルール。

  CODE RULES

  Language      Rules   Files          Origin      Rules
 ─────────────────────────────        ───────────────────
  <multilang>      62     964          Community    1062
  java            118     296
  js              156      83
  html              1      69
  yaml             31       8
  json              4       5
  bash              4       3
  dockerfile        6       1

結果。

┌──────────────┐
│ Scan Summary │
└──────────────┘
✅ Scan completed successfully.
 • Findings: 176 (176 blocking)
 • Rules run: 377
 • Targets scanned: 964
 • Parsed lines: ~99.9%
 • Scan skipped:
   ◦ Files larger than  files 1.0 MB: 2
   ◦ Files matching .semgrepignore patterns: 89
 • Scan was limited to files tracked by git
 • For a detailed list of skipped files and lines, run semgrep with the --verbose flag
Ran 377 rules on 964 files: 176 findings.
💎 Missed out on 1390 pro rules since you aren't logged in!
⚡ Supercharge Semgrep OSS when you create a free account at https://sg.run/rules.

📢 Too many findings? Try Semgrep Pro for more powerful queries and less noise.
   See https://sg.run/false-positives.

176件見つかりました。内容は数が多いので載せません…。

実行時間が気になったので、--timeオプション付きで実行。

$ semgrep scan --config p/default --time

結果。全体としては30秒ちょっとかかっています。

  ============================[ summary ]============================
  Total time: 34.9547s Config time: 1.6682s Core time: 33.2831s

  Semgrep-core time:
  Total CPU time: 29.5352s  File parse time: 4.4990s  Rule parse time: 1.0926s  Match time: 28.6517s
  Slowest 5/964 files
  ...n/resources/lessons/challenges/js/challenge8.js (  1KB): 0.015s (0.006s to parse)
  src/main/resources/lessons/xxe/js/xxe.js           (  2KB): 0.026s (0.005s to parse)
  ...at/webwolf/requests/WebWolfTraceRepository.java (  2KB): 0.021s (0.003s to parse)
  src/main/resources/lessons/xss/js/assignment3.js   (  1KB): 0.019s (0.003s to parse)
  ...g/owasp/webgoat/container/LessonDataSource.java (  2KB): 0.015s (0.002s to parse)
  Slowest 5 rules to match
  ...ct-non-literal-regexp.detect-non-literal-regexp:         3.302s
  ...y.audit.unsafe-formatstring.unsafe-formatstring:         2.799s
  ...xpress.security.audit.express-ssrf.express-ssrf:         2.147s
  ...urity.injection.raw-html-format.raw-html-format:         1.645s
  ...xss.direct-response-write.direct-response-write:         1.624s
  Analyzed: 6 bash files (  2KB in 0.003 seconds)
            3 dockerfile files (  4KB in 0.003 seconds)
            991 generic files ( 19MB in 1.114 seconds)
            207 html files (898KB in 0.662 seconds)
            888 java files (  1MB in 5.413 seconds)
            249 js files (  5MB in 68.273 seconds)
            15 json files ( 29KB in 0.012 seconds)
            10 xml files (112KB in 0.020 seconds)
            24 yaml files ( 24KB in 0.036 seconds)
  Errors:   6 files with errors, see output before the results for details or run with --strict
            PartialParsing (2 files)
            Timeout (1 files)


参考までに、sccで規模を見ておきましょう。

$ scc
───────────────────────────────────────────────────────────────────────────────
Language            Files       Lines    Blanks  Comments       Code Complexity
───────────────────────────────────────────────────────────────────────────────
Java                  371      24,508     3,031     2,797     18,680        777
AsciiDoc              238       5,165     1,482         0      3,683          0
JavaScript             94      55,559     5,291     3,100     47,168      8,122
HTML                   69       6,548       657       254      5,637          0
Properties File        45         901       152        11        738          0
CSS                    30      10,069     1,197       176      8,696          0
SQL                    13         228        13        16        199          0
Plain Text             11         245        42         0        203          0
SVG                    11       1,386         0         2      1,384          0
Markdown               10         837       232         0        605          0
YAML                    8         274        27         4        243          0
XML                     6       1,459        23        26      1,410          0
JSON                    5         187         0         0        187          0
Shell                   3         330        28        56        246         34
Batch                   1         182        35         0        147         30
Docker ignore           1           4         1         0          3          0
Dockerfile              1          40         8         1         31          3
Document Type …         1           4         0         0          4          0
───────────────────────────────────────────────────────────────────────────────
Total                 918     107,926    12,219     6,443     89,264      8,966
───────────────────────────────────────────────────────────────────────────────
Estimated Cost to Develop (organic) $3,018,599
Estimated Schedule Effort (organic) 20.93 months
Estimated People Required (organic) 12.81
───────────────────────────────────────────────────────────────────────────────
Processed 5063869 bytes, 5.064 megabytes (SI)
───────────────────────────────────────────────────────────────────────────────

ひとまず使い方の雰囲気はわかってきたので、1度ここで切りましょう。

おわりに

SASTツール、Semgrep Community Editionを試してみました。

とっかかりはちょっとわかりにくかったのですが、慣れるとルールの扱いもなんとかなりそうです。

このエントリーにもう少し詰め込もうと思ったのですが、長くなったので別エントリーにしたいと思います。




以上の内容はhttps://kazuhira-r.hatenablog.com/entry/2025/11/03/181527より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14