Skip to content

Repository files navigation

CI

Gate

Gate is an experimental local CLI for finding secret-like patterns in source files and git history. It can install a repository-local pre-commit hook, emit JSON or SARIF, optionally ask supported providers whether a detected credential is accepted, and attempt bounded source-to-environment rewrites.

Gate is a pattern scanner, not proof that a repository is secret-free. Findings require review, rules can produce false positives, and credentials can be missed. A clean result should be one layer in a wider review and secret-management process.

Documentation: penumbraforge.com/gate/wiki

A demonstration of Gate finding a secret pattern and attempting a local rewrite

Quick start

Requires Node.js 22 or later and npm 10 or later.

npm install -g @penumbraforge/gate
gate init
gate scan --all
gate fix --dry-run

gate init can create .gateignore, update .gitignore, and install a pre-commit hook in the current repository. Review every generated file before committing it.

You can also run a one-off scan without a global install:

npx @penumbraforge/gate scan --all

What Gate actually does

Pattern scanning

  • Scans explicit paths, staged files, changed files, all tracked files, or a bounded number of commits.
  • Uses regular-expression and entropy-based rules. These are heuristics, not semantic analysis.
  • Emits text, JSON, or SARIF and exits non-zero when findings or scan errors remain.
  • Respects .gaterc and .gateignore; exclusions reduce coverage and should be reviewed.

111 unique detection rules (80 built-in + 68 FORTRESS pack, deduplicated).

By severity: critical 54 · high 43 · medium 11 · low 3

Category Rules
SaaS Tokens 27
Cloud Credentials 24
Authentication Tokens 10
AI/ML Keys 7
Database Credentials 7
Generic Secrets 7
Private Keys 7
API Keys 6
Infrastructure 5
Registry Tokens 3
PII 2
AI Keys 1
Code Injection 1
Encoding 1
Entropy Detection 1
Misconfiguration 1
Secrets Management 1

Rule count is not the same as measured recall. Gate does not currently publish a comparative recall benchmark against other scanners.

Optional provider verification

gate verify and gate scan --verify make network requests for rule IDs with a supported verifier. The detected credential is sent to that credential's provider API, usually in an authorization header; GCP verification currently places the token in a provider URL query. Unsupported rules, partial credentials, timeouts, and unexpected responses return an unknown or incomplete status.

Verification is off for a normal scan unless enabled by CLI/config. Set GATE_OFFLINE=1 to disable verification requests. A hashed verification cache is stored under ~/.gate, but provider and network logs are outside Gate's control.

The current generated hook exports GATE_HOOK_TYPE, while the CLI's hook-specific verification/re-staging branch checks GATE_PRE_COMMIT. As a result, enabling verification in .gaterc can unexpectedly make provider requests from a generated hook, and hook-specific re-staging behavior may not activate. Keep verification disabled in hook configuration (or set GATE_OFFLINE=1) until that mismatch is fixed.

Treat live, inactive, and unknown as advisory observations. Provider behavior can change, and an inactive response does not prove that a value was never valid or that exposure caused no harm.

Bounded remediation

gate fix can extract recognized values into a plaintext .env, update .gitignore, create .env.example, and rewrite some quoted source assignments to environment-variable references. Adapters exist for several common file types, but not every finding, syntax shape, framework, or language is safely rewritable.

Important limits:

  • Always run gate fix --dry-run first and review the diff, tests, and application behavior afterward.
  • Moving a value does not rotate or revoke it. Rotate an exposed credential at its provider.
  • JSON cannot reference environment variables directly; the current JSON path extracts a value but requires manual source/config migration.
  • Multiple secrets that derive the same variable name and existing .env conflicts require special review.
  • Generated imports and source substitutions are syntactic heuristics, not an AST-aware refactor.
  • Undo snapshots are local recovery aids, not transactional rollback across every file or external system.

.env, remediation snapshots, purge replacement files, and Gate's local audit data should all be treated as sensitive. In the current audit implementation, the displayed match field is masked before persistence, but another internal finding field can still contain the raw secret.

Hooks and CI

gate install adds a pre-commit hook to the current repository. The hook scans staged files, but it is a local convenience boundary: hooks can be skipped, removed, or absent on another clone, and a pre-commit scan does not cover untracked/unstaged content or remote history. Because of the environment-variable mismatch described above, review hook behavior in a disposable commit before relying on interactive remediation or automatic re-staging.

The GitHub Action defaults to mode: report, which warns rather than blocks. Use mode: enforce or failure-mode: block when a non-zero policy decision is required. The Action installs the current published npm package on the runner when gate is not already available, so pin the Action to an immutable commit and review the package/version boundary for high-assurance use.

name: Gate
on: [pull_request, push]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: penumbraforge/gate@v2
        with:
          mode: enforce
          failure-mode: block
          fail-on: high
          verify: false
          format: sarif

Enabling verify: true sends supported candidate credentials to their provider APIs from the GitHub runner. SARIF upload and PR comments send finding metadata to GitHub. Slack notifications send finding counts/repository context to the configured Slack webhook.

Incident and report artifacts

gate incident prints provider-specific rotation and audit guidance, creates a local incident record, and writes a history-purge script plus a plaintext replacement file for manual review. It does not rotate a credential, inspect provider audit logs, execute the purge, force-push rewritten history, notify collaborators, or confirm that those actions were completed.

gate report maps recorded findings to selected OWASP, NIST, CIS, and SOC 2 references. The output is a scanner report, not an audit, certification, control assessment, or evidence that a system complies with those frameworks.

Commands

gate scan [files...]       Scan explicit files; without files, scan staged files
gate scan --all            Scan all tracked files
gate scan --changed        Scan files changed from the upstream branch
gate scan --history <N>    Scan the last N commits
gate verify [files...]     Scan and attempt supported-provider verification
gate fix [files...]        Attempt bounded remediation (all tracked by default)
gate fix --dry-run         Preview remediation without writing
gate fix --undo            Restore the latest local remediation snapshot where safe
gate incident [files...]   Generate incident guidance/artifacts for pushed findings
gate report                Generate a report from local audit data
gate purge                 Generate a manual git-filter-repo purge script
gate install               Install the current repository's pre-commit hook
gate uninstall             Remove Gate's managed pre-commit hook block
gate audit                 Inspect the local audit log
gate status                Show local installation/configuration status
gate help                  Show the complete CLI help

Run gate <command> --help for the implemented options. The longer technical reference is in GUIDE.md.

Data and network boundary

Normal local scans do not require an account or send findings to a Penumbra Forge service. Network activity can still occur when you deliberately use provider verification or update checks, run the GitHub Action/integrations, or use npm to install the package. Gate has one external runtime npm dependency (js-yaml), so "local" does not mean "no supply-chain risk."

Development

npm test
npm run docs
node bin/gate.js scan --all

Generated rule-count blocks in this README and GUIDE.md come from scripts/gen-docs.js.

License

Apache-2.0. See LICENSE and NOTICE.

Corrections and reproducible bug reports are welcome in the issue tracker.

About

Experimental local secret-pattern scanner for staged changes, with bounded remediation and optional provider verification. Expect false positives and misses.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages