Satisfies: U4 (false positive documentation), O4 (developer security guide)
This document describes the security scanning tools and practices for Manifold.
Manifold uses a defense-in-depth strategy for secret detection:
┌─────────────────────────────────────────────────────────────────────┐
│ Security Layers │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Developer Workstation CI/CD Pipeline Historical │
│ ───────────────────── ───────────── ─────────── │
│ │
│ ┌─────────────────┐ ┌─────────────────────┐ ┌───────────┐ │
│ │ Pre-commit │ │ Gitleaks (SARIF) │ │TruffleHog │ │
│ │ (gitleaks) │────▶│ Semgrep (SARIF) │ │ (audit) │ │
│ │ │ │ │ │ │ │
│ │ Catches │ │ Catches leaked │ │ Catches │ │
│ │ secrets │ │ secrets in PRs │ │ secrets │ │
│ │ BEFORE │ │ BEFORE merge │ │ in git │ │
│ │ commit │ │ │ │ history │ │
│ └─────────────────┘ └─────────────────────┘ └───────────┘ │
│ │
│ Fastest feedback PR gate + SARIF Deep scan │
│ integration │
└─────────────────────────────────────────────────────────────────────┘
| Layer | Tool | When | Purpose |
|---|---|---|---|
| Local | Gitleaks | Pre-commit hook | Prevent secrets from entering history |
| CI | Gitleaks + Semgrep | PR/Push | Gate merges, SARIF integration |
| Historical | TruffleHog | On-demand/weekly | Scan git history for past leaks |
Choose your preferred installation method:
macOS (Homebrew)
brew install gitleaksWindows (Scoop)
scoop install gitleaksGo Install
go install github.com/gitleaks/gitleaks/v8@latestLinux/macOS (curl)
# Check https://github.com/gitleaks/gitleaks/releases for latest version
curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.18.0/gitleaks_8.18.0_linux_x64.tar.gz | tar xz
sudo mv gitleaks /usr/local/bin/gitleaks version
# Should output: gitleaks version 8.x.xThe pre-commit hook is configured via .husky/pre-commit. Verify it works:
# Create a test file with a fake secret
echo 'AWS_SECRET_KEY="AKIAIOSFODNN7EXAMPLE"' > test-secret.txt
# Attempt to commit (should fail)
git add test-secret.txt
git commit -m "test: should fail"
# Expected: Gitleaks blocks the commit
# Clean up
rm test-secret.txt
git reset HEADDO NOT COMMIT. Follow these steps immediately:
-
Remove the secret from your code
# Remove the offending line git checkout -- <file-with-secret>
-
Use environment variables instead
// WRONG: Hardcoded secret const apiKey = "sk-1234567890abcdef"; // CORRECT: Environment variable const apiKey = process.env.API_KEY;
-
If the secret was already committed (even locally):
- Rotate the secret immediately - assume it's compromised
- Contact the relevant service provider (AWS, GitHub, etc.)
- Use
git filter-branchor BFG Repo Cleaner to remove from history - Force push to overwrite history (coordinate with team)
-
Add to
.env.example(without real values):# .env.example API_KEY=your-api-key-here DATABASE_URL=postgres://user:password@localhost:5432/db
Gitleaks may flag strings that look like secrets but aren't (e.g., test fixtures, example values, hashes).
-
Verify it's actually a false positive
- Is it a real credential? If unsure, treat it as real.
- Is it an example/placeholder that can't be used?
- Is it a test fixture with no production access?
-
Add to
.gitleaks.tomlallowlistCreate or edit
.gitleaks.tomlin the project root:# .gitleaks.toml title = "Manifold Gitleaks Configuration" [allowlist] description = "Allowlisted patterns and paths" # Allowlist specific files paths = [ '''tests/fixtures/.*''', '''docs/examples/.*''', ] # Allowlist specific patterns (use with caution) regexes = [ '''EXAMPLE_.*''', '''test-api-key-.*''', ] # Allowlist specific commits (for historical issues) commits = [ '''abc123def456...''', ]
-
Document the rationale
Always include a comment explaining WHY something is allowlisted:
# Allowlist test fixtures - these are fake credentials # used only in unit tests and have no production access # Added: 2024-01-15 by @developer paths = [ '''tests/fixtures/mock-credentials\.json''', ]
-
Get PR approval - allowlist changes should be reviewed
In rare cases, you may need to bypass the pre-commit hook:
# DANGER: Bypasses ALL pre-commit hooks
git commit --no-verify -m "emergency: fix production outage"When this is acceptable:
- Active production incident where the secret check is blocking a critical fix
- The change contains NO actual secrets (you've verified manually)
- You immediately follow up with a proper commit
When this is NOT acceptable:
- "It's just a test credential" - add to allowlist instead
- "I'm in a hurry" - security is never optional
- "I'll fix it later" - you won't
The GitHub Actions security workflow runs automatically.
| Event | When | Purpose |
|---|---|---|
| Pull Request | PR to main | Gate before merge |
| Push | Push to main | Verify after merge |
| Weekly | Sunday 2am UTC | Historical scan |
| Manual | workflow_dispatch |
On-demand scan |
Scan results are uploaded to GitHub Security tab via SARIF format:
- Navigate to Security > Code scanning alerts
- View detected secrets with file locations
- Track remediation status
To run a security scan on-demand:
# Via GitHub CLI
gh workflow run security.yml
# Or via GitHub UI
# Actions > Security Scan > Run workflowGitleaks detects 100+ secret patterns including:
| Category | Examples |
|---|---|
| Cloud Providers | AWS keys, GCP service accounts, Azure credentials |
| Version Control | GitHub tokens, GitLab tokens, Bitbucket credentials |
| Databases | PostgreSQL URLs, MongoDB connection strings, Redis passwords |
| Payment | Stripe keys, Square tokens, PayPal credentials |
| Communication | Slack tokens, Discord webhooks, Twilio credentials |
| Authentication | JWT secrets, OAuth client secrets, API keys |
| Infrastructure | Terraform state, Kubernetes secrets, Docker registry |
| Private Keys | RSA keys, SSH keys, PGP keys |
| File | Purpose | Location |
|---|---|---|
.gitleaks.toml |
Gitleaks configuration and allowlists | Project root |
.github/workflows/security.yml |
CI security workflow | .github/workflows/ |
.husky/pre-commit |
Pre-commit hook configuration | .husky/ |
title = "Manifold Gitleaks Configuration"
# Extend the default rules
[extend]
useDefault = true
[allowlist]
description = "Manifold-specific allowlist"
# Paths that are safe to ignore
paths = [
# Test fixtures with fake credentials
'''tests/fixtures/.*''',
# Documentation examples
'''docs/examples/.*''',
# Lock files
'''bun\.lockb''',
'''package-lock\.json''',
]
# Specific regex patterns to ignore
regexes = [
# Example placeholders
'''EXAMPLE_.*''',
'''your-.*-here''',
# Test identifiers
'''test-[a-z]+-[0-9]+''',
]#!/usr/bin/env sh
# Husky pre-commit hook
# Satisfies: O4 (secret detection before commit)
# Run gitleaks on staged files
gitleaks protect --staged --verbose
# If gitleaks fails, the commit is blockedIf you discover a security vulnerability in Manifold itself:
- DO NOT create a public GitHub issue
- DO NOT discuss in public channels (Slack, Discord, etc.)
- Email: security@manifold.dev (or create a private security advisory on GitHub)
- Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
If you discover leaked credentials in the repository:
- Rotate immediately - assume the credential is compromised
- Notify the team via secure channel
- Remove from history using git filter-branch or BFG Repo Cleaner
- Document the incident for post-mortem
| Severity | Response Time | Resolution Time |
|---|---|---|
| Critical (active exploit) | 1 hour | 24 hours |
| High (exposed credentials) | 4 hours | 48 hours |
| Medium (potential exposure) | 24 hours | 1 week |
| Low (hardening) | 1 week | 1 month |
# Scan current directory
gitleaks detect --verbose
# Scan staged files only
gitleaks protect --staged --verbose
# Scan with custom config
gitleaks detect --config .gitleaks.toml --verbose
# Scan git history
gitleaks detect --log-opts="--all" --verbose
# Generate SARIF report
gitleaks detect --report-format sarif --report-path results.sarif| Problem | Solution |
|---|---|
| Hook not running | Run bun install to set up Husky |
| False positive blocking commit | Add to .gitleaks.toml allowlist |
| gitleaks command not found | Install gitleaks (see Setup section) |
| CI scan failing | Check GitHub Security tab for details |