mrkeyoor.com_
Sat 08 Aug 17:40 UTC
PyPISecurityupdated 08 Aug 2026

semgrep

Semgrep is a static-analysis CLI that matches source code by syntax and meaning instead of treating it as plain text. Its YAML rules can find insecure calls, bug patterns, policy violations, and migration targets across more than 30 languages, and some rules can propose or apply fixes. The open-source Community Edition runs locally and works well for focused searches, but Semgrep's own README says serious security scanning benefits from paid platform features such as cross-file analysis, supply-chain scanning, secrets scanning, and managed rules.

Verdict

Install Semgrep when you have concrete patterns your existing linters cannot express, especially across several languages. Do not mistake the open-source CLI for the full commercial security platform; Semgrep's own README draws that boundary plainly.

API stability4/5The YAML rule format and core scan command are established, but the CLI ships frequent 1.x releases and product-facing commands can evolve without a major-version boundary.
Docs5/5The README is unusually frank about Community Edition limits, and semgrep.dev documents rule syntax, supported languages, CLI flags, metrics, CI, and many worked examples.
Maintenance5/5Version 1.172.0 is current on PyPI, the repository was pushed yesterday, and development is backed by a company with regular releases.
Ecosystem5/5The public Registry, editor integrations, pre-commit support, CI recipes, more than 30 language parsers, and a large collection of community rules make it much broader than a language-specific linter.

Use it if

  • You want project-specific security or correctness checks expressed as code-shaped patterns that developers can review
  • You need one local scanner across a polyglot repository and want it in pre-commit hooks or CI
  • You are auditing a codebase for a dangerous API, deprecated call, or bug variant and regex would produce too much noise
  • You want a large public rule registry but still need the option to keep source code on your own machine
Skip it if

Setup reality

Use pipx or uv tool install rather than dropping Semgrep's large dependency set into an application environment. A first scan is easy, but useful CI needs pinned rule configuration, paths and generated files excluded, exit-code policy, baseline handling, and a decision about Registry metrics. Login is optional for local Community Edition scans, while Semgrep CI and the platform features require an account token.

Patterns

Install Semgrep as an isolated CLIinstall-cli

pipx install semgrep
semgrep --version

Semgrep requires Python 3.10 or newer and has many dependencies; pipx keeps them out of your application's environment.

Scan with a Registry rulesetscan-registry-config

semgrep scan --config p/default src/

Registry configurations are remote. Pin rules locally for reproducible CI, and review the metrics policy before using them.

Run a one-off structural searchsearch-inline-pattern

semgrep -e '$X == $X' --lang py path/to/src

Shell quotes are required around metavariables such as $X so the shell does not expand them.

Write a local rulewrite-basic-rule

rules:
  - id: no-python-eval
    languages: [python]
    message: Avoid eval on untrusted input
    severity: ERROR
    pattern: eval($X)

A rule needs an id, languages, message, severity, and at least one pattern operator.

Require several conditionscombine-patterns

rules:
  - id: flask-debug-enabled
    languages: [python]
    message: Do not enable Flask debug mode
    severity: WARNING
    patterns:
      - pattern: $APP.run(...)
      - pattern-inside: |
          $APP = Flask(...)
          ...
      - pattern: $APP.run(..., debug=True, ...)

All entries under patterns must match; ellipses allow intervening arguments or statements.

Exclude an allowed formexclude-safe-case

rules:
  - id: require-timeout
    languages: [python]
    message: HTTP requests need a timeout
    severity: WARNING
    patterns:
      - pattern: requests.get(...)
      - pattern-not: requests.get(..., timeout=$T, ...)

Negative patterns are applied to the positive match range; test the rule against both allowed and rejected examples.

Attach a simple automatic fixadd-autofix

rules:
  - id: replace-debug-print
    languages: [python]
    message: Use the logger
    severity: INFO
    pattern: print($X)
    fix: logger.info($X)

A textual fix can change behavior when formatting or argument semantics differ; review changes before running with --autofix.

Run checked-in rules without Registry metricsscan-local-rules

semgrep scan --config .semgrep/rules.yml --metrics off src/ tests/

Local rules keep configuration reproducible; --metrics off also prevents Registry rule metrics from being sent.

Produce machine-readable findingsemit-json

semgrep scan --config .semgrep/rules.yml --json --output semgrep-results.json src/

Keep human terminal output and JSON artifact handling separate in CI so logs do not corrupt the result file.

Run platform-managed CI scanningrun-ci-mode

export SEMGREP_APP_TOKEN='replace-with-ci-secret'
semgrep ci

semgrep ci is platform-oriented and needs an authenticated token; plain semgrep scan is the account-free local path.

Alternatives

PackageRegistryPick it when
banditPyPIPython-only security checks where a focused, familiar rule set is enough
ruffPyPIPython lint, correctness, and modernization checks where speed and low setup matter more than custom semantic rules
detect-secretsPyPIYou only need secret detection with a reviewable baseline, not general static analysis