diff --git a/.github/workflows/gitleaks.yml b/.github/workflows/gitleaks.yml new file mode 100644 index 0000000..8e57a0e --- /dev/null +++ b/.github/workflows/gitleaks.yml @@ -0,0 +1,36 @@ +name: Secret Scanning with Gitleaks + +on: + push: + branches: + - main + - develop + pull_request: + branches: + - main + - develop + +jobs: + gitleaks: + name: Scan for Secrets + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for all branches and tags + + - name: Run Gitleaks + uses: gitleaks/gitleaks-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} # Optional: for Gitleaks Pro + + - name: Upload Gitleaks Report + if: failure() + uses: actions/upload-artifact@v4 + with: + name: gitleaks-report + path: gitleaks-report.json + retention-days: 30 diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 0000000..f0ae263 --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,71 @@ +title = "VacciChain Gitleaks Configuration" + +[extend] +# Use default gitleaks rules as base +useDefault = true + +# Custom rules for VacciChain-specific secrets +[[rules]] +id = "stellar-secret-key" +description = "Stellar Secret Key" +regex = '''S[A-Z0-9]{55}''' +tags = ["stellar", "secret", "key"] + +[[rules]] +id = "stellar-private-key" +description = "Stellar Private Key (alternative format)" +regex = '''(?i)(stellar[_-]?secret|stellar[_-]?private)[_-]?key["\s:=]+[A-Z0-9]{56}''' +tags = ["stellar", "secret", "key"] + +[[rules]] +id = "jwt-secret" +description = "JWT Secret" +regex = '''(?i)(jwt[_-]?secret|jwt[_-]?key)["\s:=]+[A-Za-z0-9+/=]{32,}''' +tags = ["jwt", "secret"] + +[[rules]] +id = "soroban-secret" +description = "Soroban Secret Key" +regex = '''(?i)(soroban[_-]?secret|soroban[_-]?key)["\s:=]+[A-Za-z0-9+/=]{32,}''' +tags = ["soroban", "secret"] + +[[rules]] +id = "api-key-generic" +description = "Generic API Key" +regex = '''(?i)(api[_-]?key|apikey)["\s:=]+[A-Za-z0-9_\-]{20,}''' +tags = ["api", "key"] + +# Allowlist for false positives +[allowlist] +description = "Allowlist for known false positives" +paths = [ + '''\.env\.example$''', + '''env\.example$''', + '''\.md$''', + '''test_.*\.js$''', + '''.*\.test\.js$''', + '''.*\.spec\.js$''', + '''__mocks__/.*''', +] + +# Allowlist specific patterns that are not real secrets +regexes = [ + '''EXAMPLE_.*''', + '''TEST_.*''', + '''DEMO_.*''', + '''your-.*-here''', + '''replace-with-.*''', + '''<.*>''', + '''SXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX''', +] + +# Stop words that indicate example/placeholder values +stopwords = [ + "example", + "sample", + "test", + "demo", + "placeholder", + "your-secret-here", + "replace-me", +] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..6c0cf5e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,10 @@ +repos: + - repo: https://github.com/gitleaks/gitleaks + rev: v8.18.4 + hooks: + - id: gitleaks + name: Detect hardcoded secrets + description: Detect hardcoded secrets using Gitleaks + entry: gitleaks protect --verbose --redact --staged + language: golang + pass_filenames: false diff --git a/PR_DESCRIPTION.md b/PR_DESCRIPTION.md new file mode 100644 index 0000000..1721a9e --- /dev/null +++ b/PR_DESCRIPTION.md @@ -0,0 +1,147 @@ +# Add Secret Scanning Protection with Gitleaks + +## Summary +Implements comprehensive secret scanning protection to prevent accidental commits of sensitive credentials (Stellar secret keys, JWT secrets, API tokens, etc.) to the repository. + +## Problem Statement +Previously, no automated protection existed against accidentally committing sensitive credentials like: +- Stellar secret keys (S...) +- JWT secrets +- Private keys +- API tokens +- Soroban secrets + +This posed a significant security risk as leaked credentials could compromise the entire VacciChain system. + +## Solution +Implemented multi-layered secret scanning using Gitleaks: + +### 1. **GitHub Actions CI/CD** (`.github/workflows/gitleaks.yml`) +- Runs on every push to main/develop branches +- Runs on every pull request to main/develop +- Blocks PRs if secrets are detected +- Uploads detailed reports as artifacts for investigation + +### 2. **Pre-commit Hooks** (`.pre-commit-config.yaml`) +- Scans staged files before commit +- Blocks commits containing secrets locally +- Provides immediate feedback to developers +- Prevents secrets from ever reaching the repository + +### 3. **Custom Configuration** (`.gitleaks.toml`) +- VacciChain-specific secret patterns: + - Stellar secret keys: `S[A-Z0-9]{55}` + - JWT secrets + - Soroban secrets + - Generic API keys +- Allowlist for false positives (example files, tests, documentation) +- Optimized for minimal false positives + +### 4. **Setup Scripts** +- `scripts/setup-git-hooks.sh` - For Linux/macOS users +- `scripts/setup-git-hooks.ps1` - For Windows users +- Automated installation of gitleaks and pre-commit +- One-command setup for new developers + +### 5. **Documentation** (`docs/secret-scanning-setup.md`) +- Complete setup guide +- Usage instructions +- Troubleshooting tips +- Best practices + +## Changes Made + +### New Files +- `.gitleaks.toml` - Gitleaks configuration with custom rules +- `.github/workflows/gitleaks.yml` - GitHub Actions workflow +- `.pre-commit-config.yaml` - Pre-commit hook configuration +- `scripts/setup-git-hooks.sh` - Linux/macOS setup script +- `scripts/setup-git-hooks.ps1` - Windows setup script +- `docs/secret-scanning-setup.md` - Complete documentation + +## Testing + +### Local Testing +```bash +# Test the setup script +./scripts/setup-git-hooks.sh + +# Test manual scanning +gitleaks detect --source . --verbose --redact + +# Test pre-commit hook +git add . +git commit -m "test" +``` + +### CI/CD Testing +- GitHub Actions workflow will run automatically on this PR +- Verify workflow passes successfully +- Check that gitleaks scans complete without errors + +## Acceptance Criteria Met + +✅ **Gitleaks runs on every PR and push to main** +- Implemented in `.github/workflows/gitleaks.yml` +- Configured for main and develop branches + +✅ **Pre-commit hook configured to block secret commits locally** +- Implemented in `.pre-commit-config.yaml` +- Setup scripts provided for easy installation + +✅ **Scan covers required secret types** +- Stellar secret keys (S...) +- JWT secrets +- Private keys +- API tokens +- Custom Soroban patterns + +✅ **Historical commit scan capability** +- Command provided in documentation +- Can be run manually: `gitleaks detect --source . --log-opts="--all"` + +## Deployment Steps + +1. **Merge this PR** +2. **All developers run setup script**: + - Linux/macOS: `./scripts/setup-git-hooks.sh` + - Windows: `.\scripts\setup-git-hooks.ps1` +3. **Run historical scan** (one-time): + ```bash + gitleaks detect --source . --log-opts="--all" --verbose + ``` +4. **Rotate any found secrets** immediately + +## Security Impact +- **High**: Prevents credential leaks before they happen +- **Proactive**: Catches secrets at commit time, not after push +- **Comprehensive**: Multiple layers of protection (local + CI/CD) + +## Performance Impact +- Pre-commit hook adds ~1-3 seconds per commit +- GitHub Actions adds ~30-60 seconds to CI/CD pipeline +- Minimal impact, significant security benefit + +## Breaking Changes +None. This is purely additive security enhancement. + +## Documentation +- Complete setup guide in `docs/secret-scanning-setup.md` +- Inline comments in configuration files +- Setup scripts with helpful output messages + +## Follow-up Tasks +- [ ] Run historical scan on entire repository +- [ ] Rotate any secrets found in historical scan +- [ ] Add secret scanning badge to README +- [ ] Schedule periodic security audits +- [ ] Consider adding additional secret patterns as needed + +## Related Issues +Closes #[issue-number] - Add secret scanning protection + +--- + +**Priority**: High +**Effort**: Small +**Security Impact**: Critical diff --git a/README.md b/README.md index e3bc4af..44fbd71 100644 --- a/README.md +++ b/README.md @@ -259,7 +259,19 @@ cp .env.example .env # Fill in your Stellar keys and contract IDs ``` -### 2. Deploy the contract +### 2. Setup secret scanning protection + +```bash +# Linux/macOS +./scripts/setup-git-hooks.sh + +# Windows +.\scripts\setup-git-hooks.ps1 +``` + +This installs [Gitleaks](https://github.com/gitleaks/gitleaks) pre-commit hooks to prevent accidental commits of Stellar secret keys, JWT secrets, and other credentials. See [docs/secret-scanning-setup.md](docs/secret-scanning-setup.md) for details. + +### 3. Deploy the contract ```bash cd contracts @@ -268,13 +280,13 @@ make deploy # deploy to testnet, outputs CONTRACT_ID make test # run contract unit tests ``` -### 3. Run with Docker +### 4. Run with Docker ```bash docker compose up --build ``` -### 4. Run locally (without Docker) +### 5. Run locally (without Docker) ```bash # Backend diff --git a/docs/secret-scanning-setup.md b/docs/secret-scanning-setup.md new file mode 100644 index 0000000..d072ed8 --- /dev/null +++ b/docs/secret-scanning-setup.md @@ -0,0 +1,151 @@ +# Secret Scanning Setup Guide + +## Overview + +VacciChain uses [Gitleaks](https://github.com/gitleaks/gitleaks) to prevent accidental commits of sensitive credentials including: +- Stellar secret keys (S...) +- JWT secrets +- Private keys +- API tokens +- Soroban secrets + +## Protection Layers + +### 1. Pre-commit Hook (Local) +Blocks commits containing secrets before they reach the repository. + +### 2. GitHub Actions (CI/CD) +Scans every push and pull request to main/develop branches. + +## Setup Instructions + +### For Linux/macOS Users + +```bash +# Run the setup script +chmod +x scripts/setup-git-hooks.sh +./scripts/setup-git-hooks.sh +``` + +### For Windows Users + +```powershell +# Run the PowerShell script +.\scripts\setup-git-hooks.ps1 +``` + +### Manual Setup + +If the automated scripts don't work: + +1. **Install Gitleaks** + - **macOS**: `brew install gitleaks` + - **Linux**: Download from [releases](https://github.com/gitleaks/gitleaks/releases) + - **Windows**: `winget install gitleaks` or download from releases + +2. **Install pre-commit** + ```bash + pip install pre-commit + ``` + +3. **Install hooks** + ```bash + pre-commit install + ``` + +## Usage + +### Manual Scanning + +Scan entire repository: +```bash +gitleaks detect --source . --verbose +``` + +Scan staged files only: +```bash +gitleaks protect --staged +``` + +Scan with redacted output: +```bash +gitleaks detect --source . --verbose --redact +``` + +### Historical Scan + +To scan all historical commits: +```bash +gitleaks detect --source . --log-opts="--all" --verbose +``` + +## Configuration + +The `.gitleaks.toml` file contains: +- Custom rules for VacciChain-specific secrets +- Allowlist for false positives (example files, tests) +- Patterns for Stellar keys, JWT secrets, API keys + +## Handling False Positives + +If gitleaks flags a false positive: + +1. **Verify it's not a real secret** +2. **Add to allowlist** in `.gitleaks.toml`: + ```toml + [allowlist] + paths = [ + '''path/to/file\.ext$''' + ] + ``` + +## Bypassing (Emergency Only) + +⚠️ **Not recommended** - Only use in emergencies: + +```bash +# Skip pre-commit hooks (NOT RECOMMENDED) +git commit --no-verify -m "message" +``` + +## CI/CD Integration + +GitHub Actions workflow (`.github/workflows/gitleaks.yml`) runs on: +- Every push to main/develop +- Every pull request to main/develop + +Failed scans will: +- Block the PR from merging +- Upload a detailed report as an artifact + +## Troubleshooting + +### Pre-commit hook not running +```bash +pre-commit install +``` + +### Gitleaks not found +Ensure gitleaks is in your PATH: +```bash +which gitleaks # Linux/macOS +where gitleaks # Windows +``` + +### False positive in CI +Update `.gitleaks.toml` and push the changes. + +## Best Practices + +1. **Never commit real secrets** - Use environment variables +2. **Use `.env.example`** for template files +3. **Rotate secrets** if accidentally committed +4. **Run manual scans** periodically +5. **Keep gitleaks updated** for latest detection rules + +## Support + +For issues or questions: +- Check [Gitleaks documentation](https://github.com/gitleaks/gitleaks) +- Review `.gitleaks.toml` configuration +- Contact the security team diff --git a/scripts/setup-git-hooks.ps1 b/scripts/setup-git-hooks.ps1 new file mode 100644 index 0000000..9e1cb1d --- /dev/null +++ b/scripts/setup-git-hooks.ps1 @@ -0,0 +1,77 @@ +# PowerShell script for Windows users to setup Git hooks and secret scanning + +Write-Host "🔒 Setting up secret scanning protection for VacciChain..." -ForegroundColor Cyan + +# Check if gitleaks is installed +$gitleaksInstalled = Get-Command gitleaks -ErrorAction SilentlyContinue + +if (-not $gitleaksInstalled) { + Write-Host "📦 Installing gitleaks..." -ForegroundColor Yellow + + # Check if winget is available + $wingetInstalled = Get-Command winget -ErrorAction SilentlyContinue + + if ($wingetInstalled) { + Write-Host "Installing via winget..." -ForegroundColor Gray + winget install gitleaks + } else { + Write-Host "❌ winget not found. Please install gitleaks manually:" -ForegroundColor Red + Write-Host " 1. Download from: https://github.com/gitleaks/gitleaks/releases" -ForegroundColor Yellow + Write-Host " 2. Extract gitleaks.exe to a folder in your PATH" -ForegroundColor Yellow + Write-Host " Or install winget and run this script again" -ForegroundColor Yellow + exit 1 + } + + Write-Host "✅ Gitleaks installed successfully" -ForegroundColor Green +} else { + Write-Host "✅ Gitleaks is already installed" -ForegroundColor Green + gitleaks version +} + +# Check if pre-commit is installed +$precommitInstalled = Get-Command pre-commit -ErrorAction SilentlyContinue + +if (-not $precommitInstalled) { + Write-Host "📦 Installing pre-commit..." -ForegroundColor Yellow + + # Check if pip is available + $pipInstalled = Get-Command pip -ErrorAction SilentlyContinue + + if ($pipInstalled) { + pip install pre-commit + } else { + Write-Host "❌ pip not found. Please install Python and pip first." -ForegroundColor Red + Write-Host " Download from: https://www.python.org/downloads/" -ForegroundColor Yellow + exit 1 + } + + Write-Host "✅ Pre-commit installed successfully" -ForegroundColor Green +} else { + Write-Host "✅ Pre-commit is already installed" -ForegroundColor Green +} + +# Install pre-commit hooks +Write-Host "🔧 Installing pre-commit hooks..." -ForegroundColor Cyan +pre-commit install + +# Run initial scan +Write-Host "🔍 Running initial gitleaks scan..." -ForegroundColor Cyan +$scanResult = gitleaks detect --source . --verbose --redact + +if ($LASTEXITCODE -eq 0) { + Write-Host "✅ No secrets detected in repository" -ForegroundColor Green +} else { + Write-Host "⚠️ Secrets detected! Please review and remove them before committing." -ForegroundColor Yellow + Write-Host " Run 'gitleaks detect --source . --verbose' for details" -ForegroundColor Yellow +} + +Write-Host "" +Write-Host "✅ Setup complete!" -ForegroundColor Green +Write-Host "" +Write-Host "📝 Next steps:" -ForegroundColor Cyan +Write-Host " 1. The pre-commit hook will now scan for secrets before each commit" +Write-Host " 2. To manually scan: gitleaks detect --source . --verbose" +Write-Host " 3. To scan specific files: gitleaks protect --staged" +Write-Host " 4. GitHub Actions will scan on every push and PR" +Write-Host "" +Write-Host "🔒 Your repository is now protected against accidental secret commits!" -ForegroundColor Green diff --git a/scripts/setup-git-hooks.sh b/scripts/setup-git-hooks.sh new file mode 100644 index 0000000..72e0094 --- /dev/null +++ b/scripts/setup-git-hooks.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +# Setup script for Git hooks and secret scanning +# This script installs gitleaks and configures pre-commit hooks + +set -e + +echo "🔒 Setting up secret scanning protection for VacciChain..." + +# Check if gitleaks is installed +if ! command -v gitleaks &> /dev/null; then + echo "📦 Installing gitleaks..." + + # Detect OS and install accordingly + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + # Linux + wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.4/gitleaks_8.18.4_linux_x64.tar.gz + tar -xzf gitleaks_8.18.4_linux_x64.tar.gz + sudo mv gitleaks /usr/local/bin/ + rm gitleaks_8.18.4_linux_x64.tar.gz + elif [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + if command -v brew &> /dev/null; then + brew install gitleaks + else + echo "❌ Homebrew not found. Please install Homebrew or manually install gitleaks." + exit 1 + fi + elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then + # Windows (Git Bash) + echo "⚠️ On Windows, please install gitleaks manually:" + echo " 1. Download from: https://github.com/gitleaks/gitleaks/releases" + echo " 2. Extract and add to PATH" + echo " Or use: winget install gitleaks" + exit 1 + else + echo "❌ Unsupported OS. Please install gitleaks manually from:" + echo " https://github.com/gitleaks/gitleaks/releases" + exit 1 + fi + + echo "✅ Gitleaks installed successfully" +else + echo "✅ Gitleaks is already installed" + gitleaks version +fi + +# Check if pre-commit is installed +if ! command -v pre-commit &> /dev/null; then + echo "📦 Installing pre-commit..." + + if command -v pip3 &> /dev/null; then + pip3 install pre-commit + elif command -v pip &> /dev/null; then + pip install pre-commit + else + echo "❌ pip not found. Please install Python and pip first." + exit 1 + fi + + echo "✅ Pre-commit installed successfully" +else + echo "✅ Pre-commit is already installed" +fi + +# Install pre-commit hooks +echo "🔧 Installing pre-commit hooks..." +pre-commit install + +# Run initial scan on staged files +echo "🔍 Running initial gitleaks scan..." +if gitleaks detect --source . --verbose --redact; then + echo "✅ No secrets detected in repository" +else + echo "⚠️ Secrets detected! Please review and remove them before committing." + echo " Run 'gitleaks detect --source . --verbose' for details" +fi + +echo "" +echo "✅ Setup complete!" +echo "" +echo "📝 Next steps:" +echo " 1. The pre-commit hook will now scan for secrets before each commit" +echo " 2. To manually scan: gitleaks detect --source . --verbose" +echo " 3. To scan specific files: gitleaks protect --staged" +echo " 4. GitHub Actions will scan on every push and PR" +echo "" +echo "🔒 Your repository is now protected against accidental secret commits!"