From fcf72e1242b9a0fa1cf343f63f0d9309a2012c62 Mon Sep 17 00:00:00 2001 From: Aditya Pratap Singh Date: Sat, 12 Jul 2025 14:17:12 +0200 Subject: [PATCH] Add security audits to CI --- .github/workflows/go.yml | 89 +++++++++++++++++++- .gitignore | 34 +++++++- .gosec.json | 175 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 295 insertions(+), 3 deletions(-) create mode 100644 .gosec.json diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index ce16198..6a54b20 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -244,9 +244,62 @@ jobs: with: go-version: '1.21' + - name: Cache Go modules + uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-1.21-${{ hashFiles('**/go.sum') }} + + - name: Download dependencies + run: go mod download + - name: Run go vet run: go vet ./... + - name: Install gosec + run: | + go install github.com/securego/gosec/v2/cmd/gosec@latest + gosec --version + + - name: Run gosec security scan + run: | + # Run gosec with configuration file and multiple output formats + gosec -conf .gosec.json -fmt sarif -out gosec-results.sarif ./... + gosec -conf .gosec.json -fmt json -out gosec-results.json ./... + gosec -conf .gosec.json -fmt text -out gosec-results.txt ./... + + # Display results in CI log + echo "=== GOSEC SECURITY SCAN RESULTS ===" + gosec -conf .gosec.json ./... + + # Check if any HIGH or MEDIUM severity issues found + if gosec -conf .gosec.json -fmt json ./... | jq -r '.Issues[]? | select(.severity == "HIGH" or .severity == "MEDIUM") | .severity' | grep -q "HIGH\|MEDIUM"; then + echo "WARNING: HIGH or MEDIUM severity security issues found!" + echo "Please review the gosec results." + else + echo "✅ No HIGH or MEDIUM severity security issues found" + fi + continue-on-error: true + + - name: Upload gosec SARIF results + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: gosec-results.sarif + category: gosec + continue-on-error: true + + - name: Upload gosec security artifacts + uses: actions/upload-artifact@v4 + with: + name: gosec-security-results + path: | + gosec-results.sarif + gosec-results.json + gosec-results.txt + continue-on-error: true + # Coverage aggregation job coverage: name: Coverage Report @@ -359,7 +412,7 @@ jobs: test-reports: name: Test Reports runs-on: ubuntu-latest - needs: [unit-tests, n-node-tests, benchmark-tests] + needs: [unit-tests, n-node-tests, benchmark-tests, security] steps: - name: Checkout code @@ -371,6 +424,12 @@ jobs: pattern: "*test*" merge-multiple: true + - name: Download security scan results + uses: actions/download-artifact@v4 + with: + name: gosec-security-results + continue-on-error: true + - name: Generate test report run: | echo "# Pickbox Test Report - $(date)" > test-report.md @@ -378,10 +437,23 @@ jobs: echo "- Unit Tests: ✅ Completed" >> test-report.md echo "- N-Node Tests: ✅ Completed (3 categories)" >> test-report.md echo "- Benchmark Tests: ✅ Completed" >> test-report.md + echo "- Security Scan: ✅ Completed" >> test-report.md echo "" >> test-report.md echo "## Coverage Reports" >> test-report.md echo "Coverage reports available in artifacts" >> test-report.md echo "" >> test-report.md + echo "## Security Scan Results" >> test-report.md + if [ -f "gosec-results.txt" ]; then + echo "### Gosec Security Scan" >> test-report.md + echo '```' >> test-report.md + head -50 gosec-results.txt >> test-report.md + echo '```' >> test-report.md + echo "" >> test-report.md + echo "Full security scan results available in artifacts" >> test-report.md + else + echo "Security scan results not available" >> test-report.md + fi + echo "" >> test-report.md echo "## Benchmark Results" >> test-report.md if [ -f "package-bench-results.txt" ]; then echo "### Package Benchmarks" >> test-report.md @@ -431,6 +503,12 @@ jobs: with: name: test-report + - name: Download security scan results + uses: actions/download-artifact@v4 + with: + name: gosec-security-results + continue-on-error: true + - name: Get version from git tag id: version run: | @@ -448,6 +526,8 @@ jobs: bin/* coverage.html test-report.md + gosec-results.txt + gosec-results.json body: | ## Pickbox Distributed Storage System ${{ steps.version.outputs.version }} @@ -462,7 +542,12 @@ jobs: - ✅ Unit Tests: All package tests passed - ✅ N-Node Tests: 3 test categories completed - ✅ Benchmark Tests: Performance benchmarks completed - - ✅ Security Scan: No critical issues found + - ✅ Security Scan: Gosec security analysis completed + + ### Security + - Static analysis with gosec (Go Security Checker) + - SARIF results uploaded to GitHub Security tab + - Comprehensive security scan results available in artifacts ### Downloads - **Linux AMD64**: `multi_replication-linux-amd64` diff --git a/.gitignore b/.gitignore index cb83d63..0812d03 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,36 @@ /bin coverage.out coverage.html -gosec.sarif \ No newline at end of file +gosec.sarif +gosec-results.* + +# Security and secrets +.env +.env.* +!.env.example +*.pem +*.key +*.p12 +*.pfx +secrets.yml +secrets.yaml +credentials.json +config.json +.aws/ +.gcp/ +.azure/ + +# IDE and editor files +.idea/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db \ No newline at end of file diff --git a/.gosec.json b/.gosec.json new file mode 100644 index 0000000..68f158a --- /dev/null +++ b/.gosec.json @@ -0,0 +1,175 @@ +{ + "global": { + "nosec": "enabled", + "audit": "enabled", + "confidence": "low", + "severity": "low", + "quiet": false, + "verbose": "text", + "output": "stdout", + "log": "stderr", + "format": "text", + "color": true + }, + "rules": { + "G101": { + "mode": "enabled", + "level": "error", + "description": "Look for hard coded credentials" + }, + "G102": { + "mode": "enabled", + "level": "error", + "description": "Bind to all interfaces" + }, + "G103": { + "mode": "enabled", + "level": "error", + "description": "Audit the use of unsafe block" + }, + "G104": { + "mode": "enabled", + "level": "warning", + "description": "Audit errors not checked" + }, + "G105": { + "mode": "enabled", + "level": "error", + "description": "Audit the use of big.Exp function" + }, + "G106": { + "mode": "enabled", + "level": "error", + "description": "Audit the use of ssh.InsecureIgnoreHostKey" + }, + "G107": { + "mode": "enabled", + "level": "error", + "description": "Url provided to HTTP request as taint input" + }, + "G108": { + "mode": "enabled", + "level": "error", + "description": "Profiling endpoint automatically exposed on /debug/pprof" + }, + "G109": { + "mode": "enabled", + "level": "error", + "description": "Potential integer overflow when converting to string" + }, + "G110": { + "mode": "enabled", + "level": "error", + "description": "Potential DoS vulnerability via decompression bomb" + }, + "G201": { + "mode": "enabled", + "level": "error", + "description": "SQL query construction using format string" + }, + "G202": { + "mode": "enabled", + "level": "error", + "description": "SQL query construction using string concatenation" + }, + "G203": { + "mode": "enabled", + "level": "error", + "description": "Use of unescaped data in HTML templates" + }, + "G204": { + "mode": "enabled", + "level": "error", + "description": "Audit use of command execution" + }, + "G301": { + "mode": "enabled", + "level": "warning", + "description": "Poor file permissions used when creating a directory" + }, + "G302": { + "mode": "enabled", + "level": "warning", + "description": "Poor file permissions used when creation file or using chmod" + }, + "G303": { + "mode": "enabled", + "level": "warning", + "description": "Creating tempfile using a predictable path" + }, + "G304": { + "mode": "enabled", + "level": "error", + "description": "File path provided as taint input" + }, + "G305": { + "mode": "enabled", + "level": "error", + "description": "File traversal when extracting zip archive" + }, + "G306": { + "mode": "enabled", + "level": "warning", + "description": "Poor file permissions used when writing to a file" + }, + "G307": { + "mode": "enabled", + "level": "error", + "description": "Deferring a method which returns an error" + }, + "G401": { + "mode": "enabled", + "level": "error", + "description": "Detect the usage of DES, RC4, MD5 or SHA1" + }, + "G402": { + "mode": "enabled", + "level": "error", + "description": "Look for bad TLS connection settings" + }, + "G403": { + "mode": "enabled", + "level": "error", + "description": "Ensure minimum RSA key length of 2048 bits" + }, + "G404": { + "mode": "enabled", + "level": "error", + "description": "Insecure random number source (rand)" + }, + "G501": { + "mode": "enabled", + "level": "error", + "description": "Import blacklist: crypto/md5" + }, + "G502": { + "mode": "enabled", + "level": "error", + "description": "Import blacklist: crypto/des" + }, + "G503": { + "mode": "enabled", + "level": "error", + "description": "Import blacklist: crypto/rc4" + }, + "G504": { + "mode": "enabled", + "level": "error", + "description": "Import blacklist: net/http/cgi" + }, + "G505": { + "mode": "enabled", + "level": "error", + "description": "Import blacklist: crypto/sha1" + }, + "G601": { + "mode": "enabled", + "level": "error", + "description": "Implicit memory aliasing of items from a range statement" + } + }, + "exclude": [ + "test/*.go", + "*_test.go" + ] +} \ No newline at end of file