One reusable workflow. Point it at any GitHub repo. Get a full security report β by email, in the Security tab, and as downloadable artifacts.
TID-SecureCI is a reusable GitHub Actions security pipeline. It lives in one repository and scans other repositories β your own apps or a third party's β by running six independent scanners in parallel and consolidating everything into a single, branded report. It is tuned for broad coverage instead of one scanner pretending to catch everything.
- App teams that want continuous scanning on every push and PR without wiring up six separate tools in every repo.
- Security & platform owners who want one place to maintain scanning policy and keep a copy of every report.
- Anyone vetting a third-party app before adopting it β scan any public repo on demand and read the report first.
| Scanner | Looks for |
|---|---|
| Semgrep | Insecure code patterns (SAST) + custom AI/ML guardrails |
| Gitleaks | Secrets committed to git history |
| OSV-Scanner | Known-vulnerable dependencies in manifests / lockfiles |
| Trivy | Filesystem, dependency, secret, license, IaC, and optional image vulns |
| Checkov | Infrastructure-as-Code misconfiguration |
| Syft (SBOM) | A full software inventory (SPDX + CycloneDX) |
| Dependency review | Risky dependency changes on pull requests |
- π§ an emailed report β branded HTML + Markdown with a Detailed Findings table (every issue, with a link to review it in context) and the raw scanner output attached;
- π¬ code-scanning alerts in the repo's Security tab (for repos you own);
- π¦ workflow artifacts with the raw SARIF and SBOM files;
- π an at-a-glance findings table on the run's summary page.
-
Add a caller workflow to your app repo at
.github/workflows/scan.yml(copy examples/github/scan.yml and setreport_recipientto your email):permissions: contents: read security-events: write pull-requests: write actions: read jobs: secureci: uses: TIDHQ-NETWORK/TID-SecureCI/.github/workflows/tid-secureci.yml@master secrets: inherit with: enforce: false report_recipient: you@example.com
-
Configure email once (org or repo secrets) so reports can be sent β see docs/EMAIL-SETUP.md.
-
Push, open a PR, or run it manually. When the scan finishes you get an emailed report, code-scanning alerts in Security, and downloadable artifacts.
Vetting someone else's repo? Use examples/github/scan-external.yml β an on-demand workflow that scans any public
owner/repoyou type in and emails you the report.
Point the hosted scanner at any public repo and have the report emailed to you:
gh workflow run scan-external.yml \
-R TIDHQ-NETWORK/TID-SecureCI \
-f target_repository=OWNER/REPO \
-f report_recipient=you@example.comNo CLI? Run it from Actions β Scan External Repo β Run workflow. The full test-drive guide β including how to let other people run their own scans and get reports β is in docs/TRY-IT.md.
New to this? The full walkthrough is in docs/SCANNING-GUIDE.md β scanning your other repos, vetting third-party apps, reading the report, and understanding severity.
Store this repository as private, then in the repository that hosts TID-SecureCI go to:
Settings -> Actions -> General -> Access
Allow other private repositories in your account or organization to use this workflow.
For each app repository you want to scan, also enable these GitHub-native features in the app repo:
- CodeQL default setup
- Dependabot alerts
- Dependabot security updates
- Secret scanning and push protection
Those settings live at the repository level, so they complement this reusable workflow instead of replacing it.
Add a caller workflow like examples/github/scan.yml to the app repository:
name: Secure Scan
on:
pull_request:
push:
branches: [main]
schedule:
- cron: "21 4 * * *"
permissions:
contents: read
security-events: write
pull-requests: write # dependency-review job (PR events) needs this
actions: read # sbom job needs this
jobs:
secureci:
uses: YOUR-ORG/TID-SecureCI/.github/workflows/tid-secureci.yml@master
secrets: inherit
with:
enforce: false
fail_severity: HIGH,CRITICAL
image_ref: ghcr.io/YOUR-ORG/YOUR-APP:${{ github.sha }}- Start with
enforce: falseso you can tune noise before making the workflow blocking. - Pin the reusable workflow to a branch or tag that actually exists in the SecureCI repo. The current default branch here is
master. - If you scan a different private repository than the caller, pass
target_repository,target_ref, and acheckout_token. - If your app does not build a container, leave
image_refempty.
| Input | Default | Purpose |
|---|---|---|
target_repository |
caller repo | Repo to scan |
target_ref |
caller SHA | Branch, tag, or SHA to scan |
image_ref |
empty | Optional image to scan with Trivy |
fail_severity |
HIGH,CRITICAL |
Blocking threshold for Trivy |
enforce |
false |
Whether findings should fail the workflow |
enable_semgrep |
true |
Enable Semgrep SAST |
enable_gitleaks |
true |
Enable secret scanning |
enable_osv |
true |
Enable dependency vulnerability scanning |
enable_checkov |
true |
Enable IaC scanning |
enable_trivy |
true |
Enable filesystem and image scanning |
enable_sbom |
true |
Generate SPDX and CycloneDX SBOMs |
upload_artifacts |
true |
Upload raw reports as workflow artifacts |
report_recipient |
owner address | Email address for this scan's report |
report_name |
Application Security Scan Report |
Cover-page title |
You will get:
- SARIF alerts in the GitHub Security tab (
Security -> Code scanning alerts) - workflow artifacts for raw scanner output (
Actions -> the run -> Artifacts) - the rendered HTML/Markdown summary report in the
tid-secureci-reportartifact - a findings table written to the run summary page
- SPDX and CycloneDX SBOM artifacts
- dependency review feedback on pull requests
- an optional emailed report (see below)
On every run the summary job builds a branded report β a TIDHQ.NETWORK cover
page, a preface, and numbered sections β then emails the HTML body with
report.html, report.md, and the raw SARIF/SBOM files attached. The email is
sent only when SMTP is configured; otherwise the step is skipped and everything
else runs unchanged.
- Each scan emails its report to the caller's
report_recipientinput. - If a caller does not set
report_recipient, the report goes to the TIDHQ owner address (report_ownersecret). - The TIDHQ owner address is BCC'd on every report from other callers, so you keep a copy of all scans for your records.
Set these on the SecureCI repo (or pass them through secrets: inherit):
| Secret | Required | Purpose |
|---|---|---|
smtp_server |
yes | SMTP host β enables email when set. Proton: smtp.protonmail.ch |
report_owner |
yes | TIDHQ owner address β default recipient + BCC. Enables email when set |
smtp_username |
yes | SMTP user. Proton: your full Proton address |
smtp_password |
yes | SMTP password. Proton: the SMTP submission token |
smtp_port |
no | SMTP port, defaults to 587 (STARTTLS) |
mail_from |
no | From address, defaults to smtp_username. Proton: must match the token's address |
Email is sent only when both smtp_server and report_owner are present.
| Input | Default | Purpose |
|---|---|---|
report_recipient |
owner address | Address this scan's report is sent to |
report_name |
Application Security Scan Report |
Title on the cover page |
Full step-by-step instructions live in docs/EMAIL-SETUP.md.
Proton Bridge does not work in CI. You must use Proton's SMTP submission, available on paid Proton Mail / Business plans:
- In Proton, go to
Settings -> Mail -> IMAP/SMTPand create an SMTP submission token. - Set the secrets:
smtp_server=smtp.protonmail.ch,smtp_port=587,smtp_username=<your Proton address>,smtp_password=<the token>,mail_from=<your Proton address>,report_owner=<your Proton address>. - All mail is sent from your Proton address regardless of recipient, which is correct: TIDHQ delivers each report to the user who ran the scan.
The repo also includes local helper scripts:
- scripts/clone_target_repo.sh
- scripts/generate_sbom.sh
- scripts/install_gitleaks.sh
- scripts/install_osv_scanner.sh
Example:
bash scripts/clone_target_repo.sh https://github.com/your-org/your-app.git main ./target
bash scripts/install_gitleaks.sh
bash scripts/install_osv_scanner.sh
bash scripts/generate_sbom.sh ./target ./sbom- Put TID-SecureCI in a private repo.
- Grant workflow access to your private app repos.
- Add the caller workflow to one app repo.
- Run with
enforce: falsefor a few cycles. - Fix false positives and real issues.
- Turn on
enforce: true. - Add branch protection and require both
Secure Scan / secureciandValidatebefore merge.
- Reusable workflow β a GitHub Actions workflow other repos call with
uses:. TID-SecureCI is one. - Caller workflow β the small
scan.ymlin your app repo that invokes the reusable workflow. - SAST β Static Application Security Testing: scanning source code for flaws without running it (Semgrep).
- SARIF β the standard JSON format scanners emit so findings show up in the GitHub Security tab.
- SBOM β Software Bill of Materials: a full inventory of components in a build (SPDX + CycloneDX here).
- CVE β a public identifier for a specific known vulnerability (e.g.
CVE-2024-12345). - Severity β graded impact/exploitability of a finding: CRITICAL, HIGH, MEDIUM, LOW.
- Secret β a committed credential (API key, token, password, private key) that should never be in git.
- IaC β Infrastructure as Code (Terraform, Kubernetes, Dockerfiles); scanned by Checkov and Trivy.
- Enforce mode β whether findings fail the workflow (
enforce: true) or are report-only (enforce: false). - Severity gate (
fail_severity) β which severities count as blocking when enforce is on. - SMTP submission token β the Proton-issued password used to send report email from CI.
A fuller glossary and a complete how-to live in docs/SCANNING-GUIDE.md.