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.