All integrations

PHP Security Audit v2 Integration with DefectDojo

PHP Security Audit v2 Integration with DefectDojo

PHP Security Audit (phpcs-security-audit) is an open source set of PHP_CodeSniffer rules that looks for security weaknesses in PHP source code. It was started by Jonathan Marcil with backing from Pheromone, later renamed Floe Design + Technologies, and its 2.x line is the current tagged release. The rules flag patterns such as user input reaching output or dangerous functions, weak type comparisons, risky file and system calls, and framework-specific issues for Drupal 7. Because it runs inside phpcs, it can write results in any phpcs report format, including the JSON report that DefectDojo imports.

PHP Security Audit v2 Integration with DefectDojo

We run PHP Security Audit v2 because it plugs into the phpcs setup our PHP teams already use for style checks, so adding security rules costs almost nothing. The catch is volume. A first scan of a legacy codebase can return hundreds of warnings, and a phpcs report in a CI log is not a place anyone triages. DefectDojo turns each warning into a Finding tied to the file and line, lets us mark noisy patterns as false positives once, and tracks the rest against SLAs. Later imports show whether the count is going down.

Why PHP Security Audit v2 Matters

PHP still runs a large share of web applications, including many older codebases that predate modern frameworks and their built-in protections.

  • It catches common PHP weakness patterns early, before code reaches a test environment.
  • It runs anywhere phpcs runs, including developer machines, pre-commit hooks, and CI, with no server or account.
  • The ParanoiaMode setting lets teams choose between broader coverage and fewer false positives.
  • Rule names are descriptive (for example Security.BadFunctions.EasyXSS.EasyXSSwarn), so engineers can see the class of issue at a glance.
  • The tool reports pattern matches, not confirmed vulnerabilities. Without triage and tracking, the useful findings get lost among the noise.

Advantages of This Integration

What we gain by sending PHP Security Audit v2 results through DefectDojo:

  • Line-level Findings. Each message becomes a Finding with the file path and line number, so a developer can go straight to the code.
  • Triage that sticks. Marking a pattern as a false positive or risk-accepting it in DefectDojo keeps that decision across later imports, instead of relying on inline phpcs ignore comments.
  • Reimport lifecycle. Reimporting into the same Test mitigates warnings that were fixed, adds new ones, and reactivates any that return.
  • Severity normalized to the DefectDojo scale. phpcs uses a 1 to 10 severity, which the parser converts to Low through Critical so SLA rules apply.
  • PHP alongside other results. Findings sit on the same Asset as SCA results for Composer dependencies and DAST results for the running site, so reports reflect the whole application.

How This Integration Works

DefectDojo imports these results with the PHP Security Audit v2 scan type.

1. Produce a JSON report. Run phpcs with the security ruleset and the JSON report writer:

phpcs --extensions=php,inc,lib,module,info \
  --standard=./vendor/pheromone/phpcs-security-audit/example_base_ruleset.xml \
  --report=json --report-file=phpcs-security.json \
  --basepath=. src/

--basepath strips the local path prefix from file names, which keeps paths consistent between machines. The parser expects the phpcs JSON layout, with a files object keyed by file path and a messages list per file.

2. Import it. In the UI, open the Engagement, choose Import Scan Results, select PHP Security Audit v2, and upload the file. For automation, use the API, available in Community Edition and DefectDojo Pro:

curl "https://YOUR_INSTANCE/api/v2/import-scan/" \
  -H "Authorization: Token $DD_API_TOKEN" \
  -F "scan_type=PHP Security Audit v2" \
  -F "file=@phpcs-security.json" \
  -F "product_name=storefront" \
  -F "engagement_name=CI" \
  -F "auto_create_context=true"

DefectDojo Pro users can run the same import with Universal Importer:

universal-importer import \
  --defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/" \
  --scan-type "PHP Security Audit v2" \
  --report-path "./phpcs-security.json" \
  --product-name "storefront" \
  --engagement-name "CI" \
  --auto-create-context

3. Reimport on each build. Send later reports to /api/v2/reimport-scan/ against the same Test so the open list tracks the current code.

Data Granularity: What Gets Imported

The parser reads every file with at least one error or warning and creates one Finding per message.

DefectDojo Field Source in phpcs JSON Notes
Title Message source The sniff name, for example Security.Misc.TypeJuggle.TypeJuggle
Severity Message severity (1 to 10) Halved and rounded up: 9 to 10 Critical, 7 to 8 High, 5 to 6 Medium, 4 or less Low
Description File, line, column, rule source, message Assembled as labeled lines
File Path Key of the files object As phpcs wrote it, so absolute paths stay absolute
Line Message line Line of the match
Finding type Static All findings are static
Deduplication Legacy algorithm No per-scanner config; hash falls back to title, CWE, line, file path, description

The parser doesn't set CWE, mitigation, or references, and ignores phpcs's type (ERROR or WARNING) and fixable flags. If the same rule fires twice at the same file, line, and column, only one Finding is kept.

Use Cases

In pull requests: The PHP pipeline runs phpcs with the security ruleset and reimports into a Test per repository. Reviewers check DefectDojo for new Findings introduced by the branch rather than reading the raw phpcs output.

When adopting the tool on legacy code: A team runs the first scan of a ten-year-old application and imports several hundred warnings. They spend a session marking known-safe patterns as false positives, risk-accept a few with expiration dates, and assign the rest by directory. Each later reimport shows progress against that baseline.

For Drupal 7 sites: Teams still maintaining Drupal 7 code run the Drupal ruleset and keep its Findings on the site's Asset next to DAST results for the live site.

For security reviews: Before a release, AppSec filters the Asset's Findings to High and Critical PHP Security Audit v2 results and reviews each against the code, using the file and line in the Finding.

Operational Tips

  • Most rules report at phpcs's default severity of 5, which maps to Medium. If everything looks Medium, that is why. Adjust severities in your ruleset if you want the tool to separate high-risk sniffs.
  • Run phpcs with --basepath or from a consistent working directory. File path is part of the fallback hash, so different absolute paths on different CI agents can break matching.
  • Set ParanoiaMode to 0 if the first import is too noisy, then raise it later when the team has capacity for broader coverage.
  • Because the description includes the column, reformatting a line can make a warning look new. Reimport into the same Test, which matches on title and severity for this scan type, to reduce churn.
  • Use false positive marking in DefectDojo rather than suppressing whole sniffs in phpcs, so the decision is recorded and reviewable.
  • Pair this scan with an SCA tool for Composer dependencies, since phpcs-security-audit looks at your code, not third-party packages.