Secret Scan action
Last updated: Apr 24, 2026
The SS action detects hardcoded secrets and credentials (API keys, passwords, tokens, and similar sensitive data) in your repository. It is free and open source — no account, API key, or registration is required.
Marketplace: fluidattacks/secrets-scan
Scan modes
The action prefers differential scanning whenever a base commit is available,
falling back to a full scan only when there is nothing to compare against.
The default branch is detected automatically by running git remote show origin,
so any branch name (main, master, trunk, develop, etc.) works without configuration.
| Trigger | Mode | Base for comparison |
|---|---|---|
| Push to any branch | Differential scan | Commit before the push (github.event.before) |
| Pull request | Differential scan | PR base branch |
| Scheduled / manual trigger | Full scan | — |
Both differential modes compare against a known base commit, not just the previous commit, so all changes in a multi-commit push are analyzed. This keeps CI fast while ensuring nothing slips through.
Note: In differential mode, if no files changed, the scan is skipped and no output file is produced. This is expected behavior, not an error.
Setup
1. Create the workflow
Add .github/workflows/secret-scan.yml to your repository:
name: SECRET_SCAN
on:
push:
pull_request:
types: [opened, synchronize, reopened]
schedule:
- cron: "0 8 * * 1" # optional: weekly full scan every Monday at 8am
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # required: full history enables differential scanning
- uses: fluidattacks/ss-action@<version> # Use latest released version
id: scan
# Optional: upload findings to the GitHub Security tab
- name: Upload results to GitHub Security tab
if: always()
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: ${{ steps.scan.outputs.sarif_file }}Replace
<version>with the latest release tag. Find it on the Marketplace page.
fetch-depth: 0downloads the full git history, which is necessary for the differential scan to resolve the base commit and to detect the default branch viagit remote show origin. You can omit it only if you forcescanner_mode: full.upload-sarifis optional. When included, run it withif: always()so results are uploaded even when secrets are found.- The optional
scheduletrigger adds a weekly full scan to catch secrets that were already present before you added this workflow.
Restriction: Uploading to the Security tab requires GitHub Advanced Security, which is available on all public repositories and on private repositories under a GitHub Advanced Security license. On private repositories without that license, the upload step will fail.
Without a configuration file, the action scans the entire repository and writes results
to .fluidattacks-secret-scan-results.sarif.
2. (Optional) Add a configuration file
To customize scan paths or output format,
create a YAML configuration file anywhere in your repository
and pass its path to the action via scan_config_path:
- uses: fluidattacks/ss-action@<version>
id: scan
with:
scan_config_path: .github/secret-scan-config.yamlThe path is relative to the repository root. The job fails immediately if the file does not exist at the given path.
3. Push and run
Commit the workflow file and push. The scan runs automatically.
Configuration
When scan_config_path is provided, the action uses that file exclusively.
When omitted, the action runs with built-in defaults:
scans the entire repository and writes results to .fluidattacks-secret-scan-results.sarif.
Only the ss and output keys are used by this action.
ss:
include:
- . # paths to scan (default: entire repo)
exclude:
- tests/ # paths to skip
output:
file_path: .fluidattacks-secret-scan-results.sarif
format: SARIFss.include
A list of paths (files or directories) to scan.
- Full scan: uses this list, defaulting to
.(entire repository) if not set. - Differential scan: always uses the list of changed files, regardless of this setting.
ss.exclude
A list of paths to exclude from the scan. Applied in both full and differential modes.
output
| Field | Default | Description |
|---|---|---|
file_path | .fluidattacks-secret-scan-results.sarif | Path to the results file |
format | SARIF | Output format (SARIF or CSV) |
Action inputs
| Input | Required | Default | Description |
|---|---|---|---|
scan_config_path | No | — | Path to the YAML configuration file, relative to the repository root. When omitted, built-in defaults are used. The job fails if the file does not exist. |
scanner_mode | No | (auto) | Override the scan mode. full forces a full repository scan; diff forces a differential scan. If omitted, the mode is set automatically. |
Forcing a full scan
Use scanner_mode: full to scan the entire repository on every run regardless of the trigger.
This is useful for scheduled audits:
- uses: fluidattacks/ss-action@main
id: scan
with:
scanner_mode: fullAction outputs
| Output | Description |
|---|---|
sarif_file | Path to the SARIF results file (only set when output.format is SARIF) |
vulnerabilities_found | true if any secrets were detected, false otherwise |
You can use these outputs in subsequent workflow steps:
- name: Comment on PR
if: steps.scan.outputs.vulnerabilities_found == 'true'
run: echo "Secrets detected — check the Security tab."Viewing results
After the workflow runs, findings appear in two places:
- GitHub Security tab — Go to your repository → Security → Code scanning alerts. Each finding shows severity, file location, and the exact line where the secret was detected.
- Pull request annotations — On pull requests, findings appear as inline annotations directly in the code diff.
Common scenarios
Scan only specific folders (monorepo)
ss:
include:
- services/api/
- services/web/
exclude:
- services/legacy/Export results as CSV
output:
file_path: results.csv
format: CSVTroubleshooting
No results appear in the Security tab:
Make sure the "Upload SARIF" step uses if: always()
so it runs even when the scan finds secrets.
Differential scan analyzes all files instead of just changes:
Verify that fetch-depth: 0 is set in the actions/checkout step.
Without full git history, the action cannot resolve the base commit.
The action doesn't detect my default branch:
The action runs git remote show origin to detect the default branch.
This requires fetch-depth: 0 in the checkout step so remote metadata is available.
If detection fails, verify that the origin remote is correctly configured.
The job fails with "not found in repository":
The path provided to scan_config_path does not exist in the repository.
Verify the path is correct and relative to the repository root.
Prerequisites
- A GitHub repository (public or private).
- GitHub Actions enabled on the repository.
- A Linux runner (
ubuntu-latestor equivalent) — the action requires Docker, which is only available on Linux-hosted runners.
SCA action
Run the Fluid Attacks SCA GitHub Action to find known CVEs in your third-party dependencies on every push and pull request.
CI Gate action
Run the Fluid Attacks CI Gate GitHub Action to enforce a security gate in your CI/CD pipeline based on vulnerabilities reported on the Fluid Attacks platform.