Skip to content

ci: pilot Psalm security scan, release-please, and PR title lint - #6

Merged
dconlan merged 3 commits into
mainfrom
ci-tooling-pilot
Sep 3, 2026
Merged

ci: pilot Psalm security scan, release-please, and PR title lint#6
dconlan merged 3 commits into
mainfrom
ci-tooling-pilot

Conversation

@dconlan

@dconlan dconlan commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Pilot of the CI tooling discussed for the ontology-provider modules, on this repo first since it's under active review (see #5).

What this adds

  • security-scan.yml — runs Psalm's taint analysis (--taint-analysis) on every PR, scoped to mirror the REDCap consortium's stated security-scan categories (SQL, XSS, cookies, headers, path traversal, shell, LDAP, curl/SSRF) rather than general code quality. Findings are also uploaded as SARIF to the Security tab via github/codeql-action/upload-sarif, making them eligible for Copilot Autofix assignment.
  • stubs/redcap-em-framework.phpstub — minimal method/function signatures (no implementation) for the EM framework surface this module calls, with @psalm-taint-sink/@psalm-taint-escape annotations, so Psalm can do useful taint tracking without needing REDCap core itself in a public CI runner. Sourced from REDCap's published EM Framework docs, not REDCap source.
  • release-please.yml — dormant until this branch reaches main (it only triggers on pushes there). Uses release-type: simple since config.json has no version field to bump; release-please owns its own manifest.
  • pr-title-lint.yml — enforces Conventional Commits on PR titles via pull_request_target (safe here — only reads the title, never checks out fork code), so release-please has something reliable to parse.
  • .github/dependabot.yml — weekly version-update PRs for composer (Psalm itself) and github-actions (the pinned action versions here).

Verified before opening this PR

  • Ran Psalm against the actual module code (clean) and against a deliberately tainted throwaway file (correctly flagged TaintedSql via the stubbed query() sink and TaintedHtml/TaintedTextWithQuotes via echo), to confirm the scan detects real taint rather than silently passing everything.
  • Confirmed --report=psalm-results.sarif produces valid SARIF (schema 2.1.0) alongside the normal console output, not instead of it.

Known limitation

Psalm only analyzes PHP. The module's actual JS lives embedded in PHP heredoc strings, which no mainstream JS static analyzer (ESLint, CodeQL) can see — that's a separate piece of follow-up work (extracting embedded <script> blocks into real .js files), deliberately not part of this PR.

Still open

  • Repo merge-strategy restriction to squash-only (needed for release-please to read a clean one-commit-per-PR history) — pending, not part of this PR.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

dconlan and others added 2 commits September 3, 2026 09:50
Piloting the release-workflow tooling discussed for the three ontology
provider modules, on this repo first since it's under active review.

- security-scan.yml runs Psalm's taint analysis (--taint-analysis) on
  every PR and push to main/develop. errorLevel is deliberately very
  permissive (8) since this mirrors the REDCap consortium's stated
  security scan scope (SQL, XSS, cookies, headers, path traversal,
  shell, LDAP, curl/SSRF), not general code quality - only the Tainted*
  issue handlers are pinned to always report.
- stubs/redcap-em-framework.phpstub gives Psalm just enough of the EM
  framework's public method signatures (with @psalm-taint-sink /
  @psalm-taint-escape annotations) to do useful taint tracking without
  needing REDCap core itself in a public CI runner - REDCap core is
  proprietary and was never going to be checked out here. Signatures
  only, no implementation, sourced from REDCap's published EM Framework
  docs.
- Verified against a throwaway deliberately-tainted file before
  committing (SQL via the stubbed query() sink, HTML via echo) to
  confirm the config actually detects taint rather than silently
  passing everything. Confirmed clean on the real module code.
- release-please.yml uses release-type: simple since config.json has
  no version field to bump - release-please owns its own manifest.
  Dormant until this branch reaches main (it only triggers on pushes to
  main), which is when we'd want it to start operating anyway.
- pr-title-lint.yml enforces Conventional Commits on PR titles via
  pull_request_target (safe here - the action only reads the title,
  never checks out fork code) so release-please has something reliable
  to parse regardless of what merge strategy is used.

Note: this repo's merge strategy (squash/merge-commit/rebase all
currently allowed) hasn't been restricted to squash-only yet - that's
a repo-settings change still pending confirmation, needed for
release-please to read a clean one-commit-per-PR history reliably.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- dependabot.yml: weekly version-update PRs for composer (psalm itself)
  and github-actions (pinned action versions in the workflows added in
  the previous commit). Security alerts and automated security fixes
  were already enabled at the repo level; this adds the separate,
  opt-in scheduled version-update checks.
- security-scan.yml now writes Psalm's taint-analysis output as SARIF
  and uploads it via github/codeql-action/upload-sarif, so findings
  show up in the repo's Security tab like any other code-scanning
  alert - including third-party ones, which Copilot Autofix can now be
  assigned to (public preview as of mid-2026). continue-on-error keeps
  the upload happening even when Psalm finds something; a separate
  step still fails the job afterward so PR checks reflect it.

Verified against the same deliberately-tainted smoke-test file as the
previous commit: --report=psalm-results.sarif produces valid SARIF
(schema 2.1.0, one run) alongside the normal console output, not
instead of it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

- continue-on-error on the SARIF upload step: GITHUB_TOKEN is forced
  read-only on pull_request runs triggered from forks regardless of the
  security-events: write permission declared in this workflow, so the
  upload always failed on external contributions (this repo has them -
  see PR #5). That failure was indistinguishable from a real Psalm
  finding in the job's status. The final step already gates correctly
  on steps.psalm.outcome alone, so this doesn't lose any signal.
- Drop 'develop' from the push trigger - this repo no longer has a
  permanent develop branch.

Found by /code-review on PR #6.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@dconlan
dconlan merged commit db4ef7f into main Sep 3, 2026
3 checks passed
@dconlan
dconlan deleted the ci-tooling-pilot branch September 3, 2026 00:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants