Skip to content

scan — Secret & PII Scanning

Recursively scans every file in the current directory for hardcoded secrets, credentials, and PII using 26 built-in regex patterns. Respects .gitignore automatically.

For JavaScript, TypeScript, Python, and Go files the scanner automatically runs an AST-based SAST pass using tree-sitter. This eliminates false positives from comments and string non-literals, and additionally flags dangerous API patterns (XSS sinks, eval, command injection, unsafe deserialization).

Usage

greengate scan [OPTIONS]

Options:
  --format <FORMAT>    Output format: text (default), json, sarif, junit, gitlab
  --staged             Only scan git-staged files (git diff --cached)
  --since <COMMIT>     Only scan files changed since the given commit
  --history            Scan the entire git commit history (slow on large repos)
  --annotate           Post findings as a GitHub Check Run with per-line
                       annotations and a rich PR summary comment. Requires
                       GITHUB_TOKEN, GITHUB_REPOSITORY, and GITHUB_SHA env vars.
  --update-baseline    Save current findings as the baseline (.greengate-baseline.json)
  --since-baseline     Only fail on findings not present in the saved baseline
  --blame              Enrich each finding with git blame info (author + commit)
  -h, --help           Print help

Examples

bash
# Full scan — human-readable output
greengate scan

# Only scan what you're about to commit (fast, ideal for pre-commit)
greengate scan --staged

# Only scan files changed since the last commit
greengate scan --since HEAD~1

# Output SARIF for GitHub Advanced Security PR annotations
greengate scan --format sarif > results.sarif

# Output JSON for custom tooling
greengate scan --format json | jq '.findings[].rule'

# JUnit XML for Jenkins / Azure DevOps
greengate scan --format junit > results.xml

# GitLab SAST Security Scanner JSON
greengate scan --format gitlab > gl-sast-report.json

# Enrich findings with git blame (author + commit hash)
greengate scan --blame

# Post findings directly to the GitHub Checks tab + PR summary comment
GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \
GITHUB_REPOSITORY=owner/repo \
GITHUB_SHA=${{ github.sha }} \
greengate scan --annotate

AST-Based SAST for JS/TS/Python/Go

When scanning .js, .jsx, .ts, .tsx, .py, or .go files, greengate uses tree-sitter to parse each file into a real AST. This provides:

1. String-literal scoping — secret patterns only fire inside string and template literals, not comments or JSX text:

ts
// AKIAIOSFODNN7EXAMPLE123       ← comment: NOT flagged
const key = "AKIAIOSFODNN7EXAMPLE123";  // ← string literal: flagged
tsx
<p>contact@example.com</p>               // ← JSX text: NOT flagged
<Input placeholder="name@example.com" /> // ← string attribute: flagged

2. Dangerous pattern detection — structural rules that catch XSS, eval, command injection, unsafe deserialization, and more regardless of whether arguments are literals. See SAST Rules for the full list.

3. Code smell rules — flags long functions, too many parameters, and deep nesting (JS/TS only). See SAST Rules.

Baseline mode

If your repository already has existing findings you can't fix immediately, the baseline workflow lets you suppress known findings and only fail on new ones introduced by a PR.

Step 1: Save a baseline (typically on your main branch)

bash
greengate scan --update-baseline
# Writes .greengate-baseline.json — commit this file

Step 2: Gate on new findings only (in CI, on every PR)

bash
greengate scan --since-baseline
# Only fails if new findings are introduced vs the baseline

The baseline file stores (file, rule, line) fingerprints. If a secret moves to a different line, it appears as a new finding and is re-reviewed.

yaml
# GitHub Actions example
- name: Save baseline (main branch only)
  if: github.ref == 'refs/heads/main'
  run: greengate scan --update-baseline && git add .greengate-baseline.json

- name: Gate on new secrets only (PRs)
  if: github.event_name == 'pull_request'
  run: greengate scan --since-baseline

Suppressing findings

Add // greengate: ignore on the same line to suppress a specific finding:

ts
const legacyKey = "AKIAIOSFODNN7EXAMPLE123"; // greengate: ignore
el.innerHTML = sanitizedHtml;                 // greengate: ignore

Sample output

ℹ️  Starting secret and PII scan...
ℹ️  Running SAST checks...
ℹ️  SAST: scanning 14 file(s)...
⚠️  Found 3 potential issue(s):
  - [CRITICAL] [AWS Access Key] src/config.ts:14
  - [CRITICAL] [SAST/EvalUsage] src/utils/parser.js:42
  - [HIGH] [SAST/InnerHTMLAssignment] src/components/Widget.tsx:88
Error: Scan failed: 3 secret(s)/PII found.

With --blame:

  - [CRITICAL] [AWS Access Key] src/config.ts:14
    blame: Alice Smith <alice@example.com> (abc12345)

Released under the MIT License.