docs: add README with usage, settings, and threat model
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
128
README.md
Normal file
128
README.md
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
# git-harden.sh
|
||||||
|
|
||||||
|
Audit and harden your global git configuration with security-focused defaults.
|
||||||
|
|
||||||
|
Protects against history rewriting, supply chain attacks, credential theft, and malicious repository exploitation. Runs on macOS and Linux.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download and run
|
||||||
|
curl -O https://raw.githubusercontent.com/<you>/git-hardening/main/git-harden.sh
|
||||||
|
chmod +x git-harden.sh
|
||||||
|
|
||||||
|
# Audit your current config (no changes)
|
||||||
|
./git-harden.sh --audit
|
||||||
|
|
||||||
|
# Interactive mode — review and approve each change
|
||||||
|
./git-harden.sh
|
||||||
|
|
||||||
|
# Apply all recommended defaults without prompting
|
||||||
|
./git-harden.sh -y
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
The script runs in two phases:
|
||||||
|
|
||||||
|
1. **Audit** — scans your current `git config --global` and `~/.ssh/config`, prints a color-coded report:
|
||||||
|
- `[OK]` already set to the recommended value
|
||||||
|
- `[WARN]` set to a non-recommended value
|
||||||
|
- `[MISS]` not configured
|
||||||
|
2. **Apply** — for each non-OK setting, shows what it does and prompts you to accept or skip (or auto-applies with `-y`)
|
||||||
|
|
||||||
|
### Settings Applied
|
||||||
|
|
||||||
|
| Category | What it does |
|
||||||
|
|---|---|
|
||||||
|
| **Object integrity** | Validates all objects on fetch/push/receive (`transfer.fsckObjects`, etc.) |
|
||||||
|
| **Protocol restrictions** | Default-deny policy: only HTTPS and SSH allowed. Blocks `git://` (unencrypted) and `ext://` (arbitrary command execution) |
|
||||||
|
| **Filesystem protection** | Enables `core.protectNTFS`, `core.protectHFS`, disables `core.fsmonitor` |
|
||||||
|
| **Hook control** | Redirects `core.hooksPath` to `~/.config/git/hooks` so repo-local hooks can't execute |
|
||||||
|
| **Repository safety** | `safe.bareRepository=explicit`, `submodule.recurse=false` |
|
||||||
|
| **Pull/merge hardening** | `pull.ff=only`, `merge.ff=only` — refuses non-fast-forward merges, surfacing rewritten history |
|
||||||
|
| **Transport security** | Rewrites `http://` to `https://`, enforces `http.sslVerify=true` |
|
||||||
|
| **Credential storage** | Platform-detected secure helper (`osxkeychain` on macOS, `libsecret` on Linux). Warns if using plaintext `store` |
|
||||||
|
| **Commit signing** | SSH-based signing with interactive key setup wizard (software or FIDO2 hardware key) |
|
||||||
|
| **SSH hardening** | `StrictHostKeyChecking=accept-new`, `HashKnownHosts=yes`, `IdentitiesOnly=yes`, modern algorithm restrictions |
|
||||||
|
| **Visibility** | `log.showSignature=true` |
|
||||||
|
|
||||||
|
A config backup is saved to `~/.config/git/pre-harden-backup-<timestamp>.txt` before any changes.
|
||||||
|
|
||||||
|
### Signing Setup
|
||||||
|
|
||||||
|
The script includes an interactive wizard that:
|
||||||
|
|
||||||
|
1. Detects existing SSH keys (including custom-named keys from `~/.ssh/config`)
|
||||||
|
2. Detects FIDO2 hardware (YubiKey, etc.)
|
||||||
|
3. Offers two tiers:
|
||||||
|
- **Software SSH key** — use existing `ed25519` or generate one
|
||||||
|
- **FIDO2 hardware key** — generate `ed25519-sk` with touch-to-sign (if hardware detected)
|
||||||
|
4. Configures `user.signingkey`, `commit.gpgsign`, `tag.gpgsign`
|
||||||
|
5. Sets up `~/.config/git/allowed_signers` for local signature verification
|
||||||
|
|
||||||
|
With `-y`, the script auto-detects the best available key. If no key exists, signing config is prepared but not enabled (to avoid breaking commits).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
git-harden.sh [OPTIONS]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--audit Audit only, no changes (exit code 2 if issues found)
|
||||||
|
-y, --yes Auto-apply all recommended defaults
|
||||||
|
--help, -h Show help
|
||||||
|
--version Show version
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exit Codes
|
||||||
|
|
||||||
|
| Code | Meaning |
|
||||||
|
|------|---------|
|
||||||
|
| 0 | All OK, or changes applied successfully |
|
||||||
|
| 1 | Error (missing dependencies, etc.) |
|
||||||
|
| 2 | Audit found issues (`--audit` mode) |
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- `git` >= 2.34.0 (required for SSH signing)
|
||||||
|
- `ssh-keygen`
|
||||||
|
- Bash 3.2+ (compatible with macOS default bash)
|
||||||
|
|
||||||
|
Optional:
|
||||||
|
- `ykman` or `fido2-token` for FIDO2 hardware key detection
|
||||||
|
|
||||||
|
## Threat Model
|
||||||
|
|
||||||
|
### What this protects against
|
||||||
|
|
||||||
|
- **History rewriting** — `pull.ff=only` and `merge.ff=only` refuse non-fast-forward operations, making force-pushed changes visible
|
||||||
|
- **Object injection** — `fsckObjects` validates every object transferred, catching corruption or malicious payloads
|
||||||
|
- **Protocol downgrade** — blocks plaintext `git://` and dangerous `ext://` protocol
|
||||||
|
- **Hook-based RCE** — redirects hook execution away from repo-local `.git/hooks/`
|
||||||
|
- **Submodule attacks** — disables auto-recursion; submodules must be explicitly initialized
|
||||||
|
- **Credential theft** — ensures secure credential storage, warns about plaintext `store`
|
||||||
|
- **Commit impersonation** — SSH signing proves key possession (anyone can fake `user.name`/`user.email`)
|
||||||
|
- **Filesystem tricks** — blocks NTFS/HFS+ path manipulation attacks
|
||||||
|
|
||||||
|
### What this does NOT protect against
|
||||||
|
|
||||||
|
- A compromised machine (malware can use cached keys)
|
||||||
|
- Malicious code from an authorized signer
|
||||||
|
- Historical unsigned commits (signing is not retroactive)
|
||||||
|
- Server-side misconfigurations (see admin recommendations printed by the script)
|
||||||
|
|
||||||
|
## Admin Recommendations
|
||||||
|
|
||||||
|
The script prints (but does not apply) server/org-level recommendations:
|
||||||
|
|
||||||
|
- Enable "require signed commits" on protected branches
|
||||||
|
- Enable GitHub/GitLab vigilant mode
|
||||||
|
- Restrict force-pushes server-side
|
||||||
|
- Use fine-grained, short-lived tokens in CI/CD
|
||||||
|
- Maintain an allowed signers file in repos
|
||||||
|
- Clone untrusted repos with `--no-recurse-submodules`
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
Reference in New Issue
Block a user