mirror of
https://github.com/ivuorinen/gibidify.git
synced 2026-02-07 19:47:05 +00:00
* fix(tests): remove unused test constants and helpers Delete dead test code that caused 41 staticcheck U1000 violations: - cli/test_constants.go (25 unused constants) - cli/terminal_test_helpers.go (unused type, method, 7 variables) - fileproc/test_constants.go (5 unused constants) - fileproc/processor_test.go (2 unused helper functions) * fix(security): replace custom secret detection with gitleaks The hand-rolled check_secrets regex patterns produced false positives on configKey test values, causing make security-full to fail. Replace with gitleaks via go run for proper secret detection with built-in rules and allowlist support for generated report files. * chore(deps): update dependencies and fix install-tools Update Go module dependencies to latest versions. Fix checkmake install path and remove yamllint go install (yamllint is a Python tool, not installable via go install). * docs: add design document for gitleaks integration * feat: update go to 1.25.6
347 lines
9.2 KiB
Bash
Executable File
347 lines
9.2 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Security Scanning Script for gibidify
|
|
# This script runs comprehensive security checks locally and in CI
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
cd "$PROJECT_ROOT" || {
|
|
echo "Failed to change directory to $PROJECT_ROOT"
|
|
exit 1
|
|
}
|
|
|
|
# shellcheck source=scripts/install-tools.sh
|
|
source "$SCRIPT_DIR/install-tools.sh"
|
|
|
|
echo "🔒 Starting comprehensive security scan for gibidify..."
|
|
|
|
check_dependencies
|
|
|
|
# Run gosec security scanner
|
|
run_gosec() {
|
|
print_status "Running gosec security scanner..."
|
|
|
|
if gosec -fmt=json -out=gosec-report.json -stdout -verbose=text ./...; then
|
|
print_success "gosec scan completed successfully"
|
|
else
|
|
print_error "gosec found security issues!"
|
|
if [[ -f "gosec-report.json" ]]; then
|
|
echo "Detailed report saved to gosec-report.json"
|
|
fi
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Run vulnerability check
|
|
run_govulncheck() {
|
|
print_status "Running govulncheck for dependency vulnerabilities..."
|
|
|
|
if govulncheck -json ./... >govulncheck-report.json 2>&1; then
|
|
print_success "No known vulnerabilities found in dependencies"
|
|
else
|
|
if grep -q '"finding"' govulncheck-report.json 2>/dev/null; then
|
|
print_error "Vulnerabilities found in dependencies!"
|
|
echo "Detailed report saved to govulncheck-report.json"
|
|
return 1
|
|
else
|
|
print_success "No vulnerabilities found"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Run revive with comprehensive linting
|
|
run_security_lint() {
|
|
print_status "Running comprehensive code quality linting with revive..."
|
|
|
|
if revive -config revive.toml -set_exit_status ./...; then
|
|
print_success "Revive linting passed"
|
|
else
|
|
print_error "Revive linting found issues!"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Check for potential secrets using gitleaks
|
|
check_secrets() {
|
|
print_status "Scanning for potential secrets and sensitive data with gitleaks..."
|
|
|
|
local gitleaks_report="gitleaks-report.json"
|
|
if go run github.com/zricethezav/gitleaks/v8@latest dir \
|
|
--config .gitleaks.toml \
|
|
--report-format json \
|
|
--report-path "$gitleaks_report" \
|
|
--no-banner \
|
|
.; then
|
|
print_success "No secrets detected by gitleaks"
|
|
rm -f "$gitleaks_report"
|
|
else
|
|
print_error "Secrets detected by gitleaks!"
|
|
if [[ -f "$gitleaks_report" ]]; then
|
|
echo "Detailed report saved to $gitleaks_report"
|
|
fi
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Check for hardcoded network addresses
|
|
check_hardcoded_addresses() {
|
|
print_status "Checking for hardcoded network addresses..."
|
|
|
|
local addresses_found=false
|
|
|
|
# Look for IP addresses (excluding common safe ones)
|
|
if grep -r -E "([0-9]{1,3}\.){3}[0-9]{1,3}" --include="*.go" . |
|
|
grep -v -E "(127\.0\.0\.1|0\.0\.0\.0|255\.255\.255\.255|localhost)" >/dev/null 2>&1; then
|
|
print_warning "Hardcoded IP addresses found:"
|
|
grep -r -E "([0-9]{1,3}\.){3}[0-9]{1,3}" --include="*.go" . |
|
|
grep -v -E "(127\.0\.0\.1|0\.0\.0\.0|255\.255\.255\.255|localhost)" || true
|
|
addresses_found=true
|
|
fi
|
|
|
|
# Look for URLs (excluding documentation examples)
|
|
if grep -r -E "https?://[^/\s]+" --include="*.go" . |
|
|
grep -v -E "(example\.com|no-color\.org|localhost|127\.0\.0\.1|\$\{)" >/dev/null 2>&1; then
|
|
print_warning "Hardcoded URLs found:"
|
|
grep -r -E "https?://[^/\s]+" --include="*.go" . |
|
|
grep -v -E "(example\.com|localhost|127\.0\.0\.1|\$\{)" || true
|
|
addresses_found=true
|
|
fi
|
|
|
|
if [[ "$addresses_found" = true ]]; then
|
|
print_warning "Hardcoded network addresses detected. Please review."
|
|
return 1
|
|
else
|
|
print_success "No hardcoded network addresses found"
|
|
fi
|
|
}
|
|
|
|
# Check Docker security (if Dockerfile exists)
|
|
check_docker_security() {
|
|
if [[ -f "Dockerfile" ]]; then
|
|
print_status "Checking Docker security..."
|
|
|
|
# Basic Dockerfile security checks
|
|
local docker_issues=false
|
|
|
|
if grep -q "^USER root" Dockerfile; then
|
|
print_warning "Dockerfile runs as root user"
|
|
docker_issues=true
|
|
fi
|
|
|
|
if ! grep -q "^USER " Dockerfile; then
|
|
print_warning "Dockerfile doesn't specify a non-root user"
|
|
docker_issues=true
|
|
fi
|
|
|
|
if grep -q "RUN.*wget\|RUN.*curl" Dockerfile && ! grep -q "rm.*wget\|rm.*curl" Dockerfile; then
|
|
print_warning "Dockerfile may leave curl/wget installed"
|
|
docker_issues=true
|
|
fi
|
|
|
|
if [[ "$docker_issues" = true ]]; then
|
|
print_warning "Docker security issues detected"
|
|
return 1
|
|
else
|
|
print_success "Docker security check passed"
|
|
fi
|
|
else
|
|
print_status "No Dockerfile found, skipping Docker security check"
|
|
fi
|
|
}
|
|
|
|
# Check file permissions
|
|
check_file_permissions() {
|
|
print_status "Checking file permissions..."
|
|
|
|
local perm_issues=false
|
|
|
|
# Check for overly permissive files
|
|
if find . -type f -perm +002 -not -path "./.git/*" | grep -q .; then
|
|
print_warning "World-writable files found:"
|
|
find . -type f -perm +002 -not -path "./.git/*" || true
|
|
perm_issues=true
|
|
fi
|
|
|
|
# Check for executable files that shouldn't be
|
|
if find . -type f -name "*.go" -perm +111 | grep -q .; then
|
|
print_warning "Executable Go files found (should not be executable):"
|
|
find . -type f -name "*.go" -perm +111 || true
|
|
perm_issues=true
|
|
fi
|
|
|
|
if [[ "$perm_issues" = true ]]; then
|
|
print_warning "File permission issues detected"
|
|
return 1
|
|
else
|
|
print_success "File permissions check passed"
|
|
fi
|
|
}
|
|
|
|
# Check Makefile with checkmake
|
|
check_makefile() {
|
|
if [[ -f "Makefile" ]]; then
|
|
print_status "Checking Makefile with checkmake..."
|
|
|
|
if checkmake --config=.checkmake Makefile; then
|
|
print_success "Makefile check passed"
|
|
else
|
|
print_error "Makefile issues detected!"
|
|
return 1
|
|
fi
|
|
else
|
|
print_status "No Makefile found, skipping checkmake"
|
|
fi
|
|
}
|
|
|
|
# Check shell scripts with shfmt
|
|
check_shell_scripts() {
|
|
print_status "Checking shell script formatting..."
|
|
|
|
if find . -name "*.sh" -type f | head -1 | grep -q .; then
|
|
if shfmt -d .; then
|
|
print_success "Shell script formatting check passed"
|
|
else
|
|
print_error "Shell script formatting issues detected!"
|
|
return 1
|
|
fi
|
|
else
|
|
print_status "No shell scripts found, skipping shfmt check"
|
|
fi
|
|
}
|
|
|
|
# Check YAML files
|
|
check_yaml_files() {
|
|
print_status "Checking YAML files..."
|
|
|
|
if find . -name "*.yml" -o -name "*.yaml" -type f | head -1 | grep -q .; then
|
|
if command -v yamllint >/dev/null 2>&1; then
|
|
if ! yamllint -c .yamllint .; then
|
|
print_error "YAML file issues detected!"
|
|
return 1
|
|
fi
|
|
print_success "YAML files check passed"
|
|
else
|
|
print_warning "yamllint not found, skipping YAML file check"
|
|
fi
|
|
else
|
|
print_status "No YAML files found, skipping yamllint check"
|
|
fi
|
|
}
|
|
|
|
# Generate security report
|
|
generate_report() {
|
|
print_status "Generating security scan report..."
|
|
|
|
local report_file="security-report.md"
|
|
|
|
cat >"$report_file" <<EOF
|
|
# Security Scan Report
|
|
|
|
**Generated:** $(date)
|
|
**Project:** gibidify
|
|
**Scan Type:** Comprehensive Security Analysis
|
|
|
|
## Scan Results
|
|
|
|
### Security Tools Used
|
|
- gosec (Go security analyzer)
|
|
- govulncheck (Vulnerability database checker)
|
|
- revive (Code quality and linting)
|
|
- checkmake (Makefile linting)
|
|
- shfmt (Shell script formatting)
|
|
- yamllint (YAML file validation)
|
|
- gitleaks (Secret detection)
|
|
- Custom network address detection
|
|
- Docker security checks
|
|
- File permission checks
|
|
|
|
### Files Generated
|
|
- \`gosec-report.json\` - Detailed gosec security findings
|
|
- \`govulncheck-report.json\` - Dependency vulnerability report
|
|
- \`gitleaks-report.json\` - Secret detection findings (if any)
|
|
|
|
### Recommendations
|
|
1. Review all security findings in the generated reports
|
|
2. Address any HIGH or MEDIUM severity issues immediately
|
|
3. Consider implementing additional security measures for LOW severity issues
|
|
4. Regularly update dependencies to patch known vulnerabilities
|
|
5. Run security scans before each release
|
|
|
|
### Next Steps
|
|
- Fix any identified vulnerabilities
|
|
- Update security scanning in CI/CD pipeline
|
|
- Consider adding security testing to the test suite
|
|
- Review and update security documentation
|
|
|
|
---
|
|
*This report was generated automatically by the gibidify security scanning script.*
|
|
EOF
|
|
|
|
print_success "Security report generated: $report_file"
|
|
return 0
|
|
}
|
|
|
|
# Main execution
|
|
main() {
|
|
echo "🔒 gibidify Security Scanner"
|
|
echo "=========================="
|
|
echo
|
|
|
|
local exit_code=0
|
|
|
|
check_dependencies
|
|
echo
|
|
|
|
# Run all security checks
|
|
run_gosec || exit_code=1
|
|
echo
|
|
|
|
run_govulncheck || exit_code=1
|
|
echo
|
|
|
|
run_security_lint || exit_code=1
|
|
echo
|
|
|
|
check_secrets || exit_code=1
|
|
echo
|
|
|
|
check_hardcoded_addresses || exit_code=1
|
|
echo
|
|
|
|
check_docker_security || exit_code=1
|
|
echo
|
|
|
|
check_file_permissions || exit_code=1
|
|
echo
|
|
|
|
check_makefile || exit_code=1
|
|
echo
|
|
|
|
check_shell_scripts || exit_code=1
|
|
echo
|
|
|
|
check_yaml_files || exit_code=1
|
|
echo
|
|
|
|
generate_report
|
|
echo
|
|
|
|
if [[ $exit_code -eq 0 ]]; then
|
|
print_success "🎉 All security checks passed!"
|
|
else
|
|
print_error "❌ Security issues detected. Please review the reports and fix identified issues."
|
|
print_status "Generated reports:"
|
|
print_status "- gosec-report.json (if exists)"
|
|
print_status "- govulncheck-report.json (if exists)"
|
|
print_status "- gitleaks-report.json (if exists)"
|
|
print_status "- security-report.md"
|
|
fi
|
|
|
|
exit $exit_code
|
|
}
|
|
|
|
# Run main function
|
|
main "$@"
|