Skip to main content

GForge (Python)

Governance Forge — an engineering governance platform that helps teams forge consistent development standards through Git automation, quality gates, and developer tooling.

PyPI version Python versions platforms license

GForge brings engineering standards to the one place every change passes through: the commit. Its first governance capability is a secret firewall — a managed global Git hook that stops credentials from ever entering your history, on every repository, across your whole team.

This is the Python port of GForge. The idea, the product design, and the detection engine are the work of Gaurang Joshi, Shrey Tandel, and Dwij Acharya, who built the original together. See Credits and attribution.


Why GForge

A single leaked API key, database password, or private key in a commit can mean a production incident, a costly rotation, and a permanent entry in Git history. Per-project hooks drift, get skipped, or are never installed. GForge makes the guardrail global, automatic, and uniform for every developer and every repo — so the standard is enforced by default, not by discipline.

Features

  • Install once, protected everywhere. Configures Git's global core.hooksPath, so the firewall applies to every repository on the machine.
  • Deep, layered detection
    • .env cross-reference — blocks any staged file that hardcodes a real value from your git-ignored .env files (the classic "pasted a token out of .env").
    • Provider rules — 25+ credential shapes: AWS, GitHub/GitLab, Google, Slack, Stripe, Twilio, SendGrid, npm, PyPI, OpenAI/Anthropic, PEM private keys, JWTs, database URLs, and more.
    • Generic secrets — any credential keyword assigned to a hardcoded value (DB_PASSWORD=…, password: "…", api_key = "…").
    • Entropy — high-entropy strings that carry no recognizable name.
  • Low noise by design. References like os.environ["DB_PASSWORD"], f-string interpolation, placeholders, and env templates (.env.example) are not flagged, so correct code keeps flowing.
  • Never leaks the secret. Reports only file paths, line numbers, and rule names — the matched value is never printed.
  • Encoding-aware. Handles UTF‑8, UTF‑16, and BOM-prefixed files (e.g. those written by PowerShell) so nothing slips through as "binary".
  • gitleaks turbo (optional). If gitleaks is on PATH, GForge runs it too and merges the findings.
  • Cross-platform, zero runtime dependencies. Standard library only.

Requirements

  • Python 3.9 or newer
  • Git

Installation

pipx install gforge-python   # or: pip install --user gforge-python
gforge install

The PyPI project is gforge-python; the command it installs is gforge.

gforge install is the one-time setup step: it writes the managed hook and points your global core.hooksPath at it. From the next commit onward, changes are scanned for secrets on every repository. Confirm anytime with:

gforge verify

Why two steps, unlike the npm original? Python wheels have no postinstall hook — pip deliberately runs no package code at install time. Rather than smuggle setup into an import side effect, GForge asks for one explicit command. It is also the honest boundary: reconfiguring your global Git config is a decision, not a side effect of pip install.

Quick start

# See the current status of your workstation
gforge verify

# Try it — a hardcoded secret is blocked before it can be committed
echo 'DB_PASSWORD=S3cr3t-Value-123' > config.txt
git add config.txt
git commit -m "add config"
# → GForge blocks the commit and names config.txt (the value is never printed)

Commands

gforge <command> [--force]
Command Description
gforge install Upgrade to the latest version (if any) and install the global hooks.
gforge verify Read-only health check of the environment and installed hooks.
gforge update Upgrade to the latest version (if any) and refresh the hooks.
gforge uninstall Remove GForge-owned hooks and restore your previous Git config.
gforge version Print the installed version.
gforge help Print usage.

--force (with install/update) reinstalls the latest release even if you are already on it. GForge never downgrades below your installed version.

How detection works

The pre-commit hook scans only the files staged for the current commit — not the whole repository — and blocks the commit if any appear to contain a secret. It reports file paths, line numbers, and rule names, and never prints the matched value. Detection runs several layers in order:

  1. .env cross-reference — the highest-precision signal: values read (in memory only) from your git-ignored .env files, matched verbatim in staged code.
  2. Provider rules — fixed credential shapes for the major cloud and SaaS providers.
  3. Generic secrets — credential keywords assigned to a hardcoded value; smart enough to ignore os.environ[...], function calls, f-strings and ${VAR} interpolation, and obvious placeholders.
  4. Entropy — unnamed high-entropy strings, tuned to skip Git SHAs, UUIDs, lockfiles, and file paths (a path is scored per segment, so a long import path is not mistaken for a base64 blob).
  5. Secret files.env (and .env.* except templates), id_rsa, *.p12/*.pfx, keystores, .git-credentials, .netrc, and more.

Detection is best-effort and complements — not replaces — good secret hygiene.

Managing false positives

Maximum coverage occasionally flags something safe. Three escape hatches:

  • Inline: add a gforge:allow (or gitleaks:allow) comment on the line.

  • Per-repo: add a path or pattern to a .gforgeignore file at the repo root (a .gitleaksignore is also honored):

    # .gforgeignore
    tests/fixtures/
    ^docs/sample-config\.md$
    
  • One-off: bypass a single commit with git commit --no-verify.

Staying up to date

gforge update upgrades the package to the latest published release and refreshes the hook. GForge also keeps itself current on its own: at most once a day it checks PyPI in a detached background process (it never delays or blocks a commit), installs the update, and prints a one-line notice on commit:

gforge: v1.2.0 is available (you have v1.1.0). Run: gforge update

The background upgrade only runs when the hook's interpreter is the one GForge is installed into, so it can never install into the wrong environment.

Configuration

Behavior is controlled entirely through environment variables — there is no config file to manage.

Variable Effect
GFORGE_AUTO_UPDATE=0 Notify only; do not auto-install new versions (default: auto-install on).
GFORGE_NO_SELF_UPDATE=1 Skip the pip self-upgrade in install/update (CI / air-gapped).
GFORGE_PYTHON=/path/to/python Pin the Python runtime the hook uses.
NO_COLOR=1 Disable ANSI colour in all output.

If a repository or the system already defines its own core.hooksPath (e.g. Husky, lefthook, or pre-commit), that value shadows GForge in the affected repository; gforge verify warns when it detects this. Your previous global value is recorded at install time and restored by gforge uninstall.

Cross-platform support

Platform Shells
macOS Bash, Zsh
Linux Bash
Windows Git Bash, WSL, PowerShell (via Git for Windows)

The scanner runs on Python; the hook is a small POSIX shell shim that locates a Python interpreter robustly (including on Git for Windows) and fails closed if it cannot — a commit is never allowed through unscanned.

What GForge changes on your machine

GForge is transparent and fully reversible. It touches only your global Git config and a single directory in your home folder:

  • ~/.gforge/hooks/ — the managed hook and scanner (core.hooksPath points here).
  • ~/.gforge/state.json — records your previous core.hooksPath so uninstall can restore it.
  • ~/.gforge/update-check.json — the once-a-day version-check cache.

gforge uninstall removes GForge-owned files and restores your prior configuration.

Programmatic use

GForge is primarily a CLI, but both the command runner and the detection engine are importable:

import sys
from gforge import run_cli

result = run_cli(["verify"], sys.stdout, sys.stderr)
sys.exit(result.exit_code)
from gforge.scanner import scan_text

findings = scan_text("config.py", 'API_KEY = "s3cr3tValue123"')
for finding in findings:
    print(finding.file, finding.line, finding.rule_id)  # the value is never exposed

Development

python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -e ".[dev]"

pytest                             # run the test suite
ruff check . && ruff format --check .
mypy                               # strict type checking
python -m build                    # build the sdist and wheel

Differences from the Node original

The behaviour of the detection engine is intentionally identical; the differences are the ones Python's packaging model forces:

Node (npm i -g gforge) Python (this port)
Setup Automatic via postinstall Explicit gforge install
Self-upgrade npm install -g gforge@latest pip install --upgrade gforge-python
Version source package.json Installed distribution metadata
Package name gforge gforge-python on PyPI, gforge to import and run
Hook engine ~/.gforge/hooks/gforge-scan.mjs ~/.gforge/hooks/gforge_scan.py
Interpreter preference node from PATH, then baked path Baked path first, then PATH

The interpreter preference is inverted deliberately: any node runs the scanner equally well, but on Python the interpreter recorded at install time is the one GForge lives in, which keeps self-upgrade targeting the right environment.

Roadmap

The secret firewall is the first governance capability. Planned directions:

  • Additional commit-time quality gates (commit message and branch conventions, large-file and merge-conflict guards).
  • Shareable, versioned org policy packs.
  • Reporting and audit for governance coverage across a team.

Credits and attribution

GForge was created by Gaurang Joshi, Shrey Tandel, and Dwij Acharya, who contributed to it equally. The original Node.js implementation lives at github.com/psspl-gaurang/gforge and is the source of everything that makes this tool what it is: the idea, the product design, the command surface, the layered detection strategy, and the carefully tuned false-positive heuristics that the test suite here still encodes.

Gaurang Joshi Original author — @psspl-gaurang
Shrey Tandel Original author
Dwij Acharya Original author

This package is a Python translation of their work, published under the same Apache-2.0 licence, with the original NOTICE reproduced verbatim. It is not a fork that claims originality — if GForge is useful to you, the credit belongs upstream.

Thanks to everyone who has contributed to GForge:

GForge contributors

Contributing

Issues and pull requests are welcome. Please run the checks below before submitting, keep changes focused, and preserve the Apache-2.0 licence header and the NOTICE file.

pytest
ruff check .
mypy

Changes to the detection engine should stay behaviour-compatible with the upstream Node implementation wherever practical, so a fix in one can be carried to the other.

Security

To report a vulnerability, follow the process in SECURITY.md. Do not open a public issue for security reports, and never include real secrets in a report.

Licence

Licensed under the Apache License 2.0, the same licence as the upstream project. Please preserve the NOTICE file when redistributing.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gforge_python-0.1.0.tar.gz (60.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gforge_python-0.1.0-py3-none-any.whl (48.7 kB view details)

Uploaded Python 3

File details

Details for the file gforge_python-0.1.0.tar.gz.

File metadata

  • Download URL: gforge_python-0.1.0.tar.gz
  • Upload date:
  • Size: 60.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.10

File hashes

Hashes for gforge_python-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5ed20507ba3f5127026be046a85916725c78ce2fb546080d3b6e5d4418d36611
MD5 677e782c97ba5a35ff4e782f5d6c7633
BLAKE2b-256 97148f33b32e4cd0344e15c4bc80af0eac8f34a42bf5a70ec7880218cec7c8a0

See more details on using hashes here.

File details

Details for the file gforge_python-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: gforge_python-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 48.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.10

File hashes

Hashes for gforge_python-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fc12ad090d77fff0628402fef50cf51a81073dd503cc3227bd515f6daa30e15f
MD5 f7d4d62deb09eb9b9cecf235341d752d
BLAKE2b-256 9bd4d7adcaff8ed75f5bbe516cdfdf1418138b2dbc0c7d78f80fee55f7cc005a

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.2

2 files

0.1.1

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page