# GoHoarder **A universal, security-first caching proxy for package managers with automated vulnerability scanning.** GoHoarder is a transparent pass-through cache proxy that supports npm, pip, and Go modules. It caches packages locally, scans them for vulnerabilities using multiple security scanners, and blocks packages that exceed your security thresholdsβ€”all without requiring changes to your existing workflows. [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Go Version](https://img.shields.io/badge/go-1.22+-blue.svg)](https://golang.org) --- ## ✨ Features ### πŸ”’ **Security-First** - **Automated vulnerability scanning** with multiple scanners (Trivy, OSV, Grype, npm-audit, pip-audit, GitHub Advisory Database, govulncheck) - **Configurable blocking thresholds** by severity (CRITICAL, HIGH, MODERATE, LOW) - **CVE bypass system** for managing false positives or accepted risks - **Real-time scanning** before package delivery - blocks vulnerable packages on **first download** - **403 Forbidden responses** for blocked packages (not 502 errors) - **No fallback mechanisms** - security is enforced across all package managers ### πŸš€ **Performance** - **Intelligent caching** reduces bandwidth and speeds up builds - **Scan-once, serve-many** - packages scanned once, results cached - **Background rescanning** keeps security assessments up-to-date - **Multi-backend storage** (filesystem, S3, SMB/CIFS) - **Connection pooling** and **rate limiting** for upstream registries - **Circuit breaker** pattern for resilience ### πŸ“Š **Observability** - **Web dashboard** with Vue 3 frontend for package management - **Detailed vulnerability reports** with CVE information and severity breakdown - **Download analytics** and usage statistics - **Health check endpoints** for monitoring - **Prometheus metrics** integration - **Structured JSON logging** with zerolog ### 🌐 **Universal Support** - **npm/pnpm/yarn** - Full npm registry protocol support - **pip** - PyPI Simple API (PEP 503) implementation - **Go modules** - GOPROXY protocol with sumdb support - **Transparent proxying** - Works with existing tools without modification --- ## πŸ“‹ Table of Contents - [Quick Start](#-quick-start) - [Installation](#-installation) - [Configuration](#-configuration) - [Package Manager Setup](#-package-manager-setup) - [Private Repository Support](#-private-repository-support) - [Kubernetes Deployment](#️-kubernetes-deployment) - [Security Scanning](#-security-scanning) - [Web Dashboard](#-web-dashboard) - [API Reference](#-api-reference) - [Architecture](#-architecture) - [Development](#-development) - [Troubleshooting](#-troubleshooting) - [Contributing](#-contributing) --- ## πŸš€ Quick Start ### 1. Install and Run ```bash # Clone the repository git clone https://github.com/lukaszraczylo/gohoarder.git cd gohoarder # Build make build # Run (starts both backend and frontend) make run ``` GoHoarder will start on **http://localhost:8080** ### 2. Configure Your Package Manager **npm/pnpm:** ```bash npm config set registry http://localhost:8080/npm ``` **pip:** ```bash pip install --index-url http://localhost:8080/pypi/simple/ \ --trusted-host localhost \ package-name ``` **Go:** ```bash # ⚠️ IMPORTANT: Do NOT use ",direct" fallback - it bypasses security! export GOPROXY="http://localhost:8080/go" ``` ### 3. Install Packages Normally ```bash # npm npm install axios # pip pip install requests # Go go get github.com/gin-gonic/gin ``` **Vulnerable packages are automatically blocked:** ``` npm install axios@0.21.1 ❌ ERROR: 403 Forbidden - Package has 3 HIGH vulnerabilities (threshold: 0) ``` --- ## πŸ“¦ Installation ### Prerequisites - **Go 1.22+** for building the backend - **Node.js 18+** and **pnpm** for building the frontend - **Security scanners** (optional, but recommended): - [Trivy](https://github.com/aquasecurity/trivy) - Container and package scanning - [Grype](https://github.com/anchore/grype) - Vulnerability scanner - [govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck) - Go-specific scanner ### Building from Source ```bash # Clone repository git clone https://github.com/lukaszraczylo/gohoarder.git cd gohoarder # Build backend only make build # Build backend + frontend make build-all # Run with frontend make run # Run backend only ./bin/gohoarder serve ``` ### Install Security Scanners **Trivy:** ```bash # macOS brew install aquasecurity/trivy/trivy # Linux wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add - echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list sudo apt-get update && sudo apt-get install trivy ``` **Grype:** ```bash # macOS brew tap anchore/grype brew install grype # Linux curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin ``` **govulncheck:** ```bash go install golang.org/x/vuln/cmd/govulncheck@latest ``` --- ## βš™οΈ Configuration ### Configuration File Create `config.yaml` in the project root: ```yaml server: port: 8080 host: "0.0.0.0" read_timeout: "5m" write_timeout: "5m" storage: backend: "filesystem" # Options: filesystem, s3, smb path: "./data/storage" metadata: backend: "sqlite" # Options: sqlite, postgresql path: "./data/gohoarder.db" security: enabled: true update_db_on_startup: true # Block packages based on vulnerability counts block_thresholds: critical: 0 # Block if ANY critical vulnerabilities high: 0 # Block if ANY high vulnerabilities medium: 5 # Block if MORE than 5 medium vulnerabilities low: -1 # -1 = don't block based on low severity # Or block based on highest severity present block_on_severity: "high" # Options: critical, high, moderate, low, none scanners: trivy: enabled: true osv: enabled: true grype: enabled: true govulncheck: enabled: true npm_audit: enabled: true pip_audit: enabled: true ghsa: enabled: true cache: default_ttl: 86400 # 24 hours in seconds logging: level: "info" # debug, info, warn, error format: "json" upstream: npm: "https://registry.npmjs.org" pypi: "https://pypi.org/simple" go: "https://proxy.golang.org" ``` ### Environment Variables All configuration values can be overridden with environment variables: ```bash # Server export GOHOARDER_SERVER_PORT=8080 export GOHOARDER_SERVER_HOST="0.0.0.0" # Storage export GOHOARDER_STORAGE_BACKEND="filesystem" export GOHOARDER_STORAGE_PATH="./data/storage" # Security export GOHOARDER_SECURITY_ENABLED=true export GOHOARDER_SECURITY_BLOCK_CRITICAL=0 export GOHOARDER_SECURITY_BLOCK_HIGH=0 # Logging export GOHOARDER_LOG_LEVEL="info" ``` --- ## πŸ”§ Package Manager Setup ### npm / pnpm / yarn #### ⚠️ Security Notice **All three package managers enforce security correctly - no fallback mechanisms.** #### Configuration **npm:** ```bash npm config set registry http://localhost:8080/npm ``` **pnpm:** ```bash pnpm config set registry http://localhost:8080/npm ``` **yarn (v4+):** ```yaml # .yarnrc.yml npmRegistryServer: "http://localhost:8080/npm" unsafeHttpWhitelist: - localhost ``` #### Usage ```bash # Install packages normally npm install express pnpm add react yarn add lodash # Vulnerable packages will fail with 403 Forbidden npm install axios@0.21.1 # ❌ ERROR: 403 Forbidden - Package has 3 HIGH vulnerabilities (threshold: 0) ``` #### Clear Cache ```bash npm cache clean --force pnpm store prune yarn cache clean --all ``` --- ### Python (pip) #### Configuration **Per-install:** ```bash pip install --index-url http://localhost:8080/pypi/simple/ \ --trusted-host localhost \ package-name ``` **Global configuration:** ```ini # ~/.pip/pip.conf (Linux/macOS) # %APPDATA%\pip\pip.ini (Windows) [global] index-url = http://localhost:8080/pypi/simple/ trusted-host = localhost ``` #### Usage ```bash # Install packages normally pip install requests # Vulnerable packages will fail pip install flask==0.12.0 # ❌ ERROR: HTTP error 403 while getting ... # ❌ ERROR: 403 Client Error: Forbidden ``` #### Clear Cache ```bash pip cache purge ``` --- ### Go Modules #### ⚠️ CRITICAL: No Fallback Configuration **The `,direct` fallback completely bypasses security scanning and must NEVER be used!** **❌ INSECURE (bypasses security):** ```bash export GOPROXY="http://localhost:8080/go,direct" # ^^^^^^^ NEVER USE THIS! ``` **βœ… SECURE (enforces scanning):** ```bash export GOPROXY="http://localhost:8080/go" ``` **Persistent configuration:** ```bash # Add to ~/.bashrc, ~/.zshrc, or ~/.profile echo 'export GOPROXY="http://localhost:8080/go"' >> ~/.bashrc source ~/.bashrc ``` #### Usage ```bash # Download packages normally go get github.com/gin-gonic/gin@v1.7.0 go mod download # Vulnerable packages will fail with 403 Forbidden # (if vulnerability databases detect issues) ``` #### Clear Cache ```bash go clean -modcache ``` ## πŸ” Private Repository Support GoHoarder supports private packages through **automatic credential forwarding** - no server-side configuration needed! Your existing authentication automatically works through the proxy. ### How It Works 1. **Client Authentication** β†’ Your package manager sends credentials to GoHoarder 2. **Credential Forwarding** β†’ GoHoarder forwards credentials to upstream registry 3. **Package Caching** β†’ Packages are cached with credential-aware keys 4. **Access Validation** β†’ For private packages, credentials are validated on every request (cached for 5 minutes) 5. **Multi-User Isolation** β†’ Different users with different credentials get separate cache entries ### Security Model - **Per-Request Validation**: Private packages verify credentials with upstream before serving - **Credential Isolation**: Each user's credentials create separate cache entries - **Validation Caching**: Validation results cached for 5 minutes to reduce upstream load - **Access Control**: 403 Forbidden if credentials are invalid or missing ### Setup #### npm Private Packages **GitHub Packages:** ```bash # Configure .npmrc for GitHub Packages echo "@yourorg:registry=https://npm.pkg.github.com" >> ~/.npmrc echo "//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN" >> ~/.npmrc # Use GoHoarder proxy npm config set registry http://localhost:8080/npm npm install @yourorg/private-package ``` **GitLab Packages:** ```bash # Configure .npmrc for GitLab echo "@yourgroup:registry=https://gitlab.com/api/v4/packages/npm/" >> ~/.npmrc echo "//gitlab.com/api/v4/packages/npm/:_authToken=YOUR_GITLAB_TOKEN" >> ~/.npmrc # Use GoHoarder proxy npm config set registry http://localhost:8080/npm ``` **Private Artifactory / Nexus:** ```bash # Configure .npmrc with Basic auth echo "//your-registry.com/:_auth=BASE64_CREDENTIALS" >> ~/.npmrc # Use GoHoarder proxy npm config set registry http://localhost:8080/npm ``` #### PyPI Private Packages **Private PyPI Index:** ```bash # Configure pip with credentials in URL pip config set global.index-url http://localhost:8080/pypi/simple # Install with credentials in request (pip handles auth) pip install --index-url http://username:password@localhost:8080/pypi/simple private-package //trufflehog:ignore ``` **AWS CodeArtifact:** ```bash # Get CodeArtifact token export CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token --domain your-domain --query authorizationToken --output text) # Use with pip pip install --index-url http://aws:$CODEARTIFACT_AUTH_TOKEN@localhost:8080/pypi/simple private-package ``` **GitHub Packages (PyPI):** ```bash # Configure pip to use GitHub Packages through GoHoarder pip install --index-url http://USERNAME:GITHUB_TOKEN@localhost:8080/pypi/simple your-private-package //trufflehog:ignore ``` #### Go Private Modules **GitHub Private Repositories:** ```bash # Configure .netrc with GitHub credentials cat >> ~/.netrc <> ~/.netrc <