mirror of
https://github.com/ivuorinen/gibidify.git
synced 2026-01-26 03:24:05 +00:00
* build: update Go 1.25, CI workflows, and build tooling - Upgrade to Go 1.25 - Add benchmark targets to Makefile - Implement parallel gosec execution - Lock tool versions for reproducibility - Add shellcheck directives to scripts - Update CI workflows with improved caching * refactor: migrate from golangci-lint to revive - Replace golangci-lint with revive for linting - Configure comprehensive revive rules - Fix all EditorConfig violations - Add yamllint and yamlfmt support - Remove deprecated .golangci.yml * refactor: rename utils to shared and deduplicate code - Rename utils package to shared - Add shared constants package - Deduplicate constants across packages - Address CodeRabbit review feedback * fix: resolve SonarQube issues and add safety guards - Fix all 73 SonarQube OPEN issues - Add nil guards for resourceMonitor, backpressure, metricsCollector - Implement io.Closer for headerFileReader - Propagate errors from processing helpers - Add metrics and templates packages - Improve error handling across codebase * test: improve test infrastructure and coverage - Add benchmarks for cli, fileproc, metrics - Improve test coverage for cli, fileproc, config - Refactor tests with helper functions - Add shared test constants - Fix test function naming conventions - Reduce cognitive complexity in benchmark tests * docs: update documentation and configuration examples - Update CLAUDE.md with current project state - Refresh README with new features - Add usage and configuration examples - Add SonarQube project configuration - Consolidate config.example.yaml * fix: resolve shellcheck warnings in scripts - Use ./*.go instead of *.go to prevent dash-prefixed filenames from being interpreted as options (SC2035) - Remove unreachable return statement after exit (SC2317) - Remove obsolete gibidiutils/ directory reference * chore(deps): upgrade go dependencies * chore(lint): megalinter fixes * fix: improve test coverage and fix file descriptor leaks - Add defer r.Close() to fix pipe file descriptor leaks in benchmark tests - Refactor TestProcessorConfigureFileTypes with helper functions and assertions - Refactor TestProcessorLogFinalStats with output capture and keyword verification - Use shared constants instead of literal strings (TestFilePNG, FormatMarkdown, etc.) - Reduce cognitive complexity by extracting helper functions * fix: align test comments with function names Remove underscores from test comments to match actual function names: - benchmark/benchmark_test.go (2 fixes) - fileproc/filetypes_config_test.go (4 fixes) - fileproc/filetypes_registry_test.go (6 fixes) - fileproc/processor_test.go (6 fixes) - fileproc/resource_monitor_types_test.go (4 fixes) - fileproc/writer_test.go (3 fixes) * fix: various test improvements and bug fixes - Remove duplicate maxCacheSize check in filetypes_registry_test.go - Shorten long comment in processor_test.go to stay under 120 chars - Remove flaky time.Sleep in collector_test.go, use >= 0 assertion - Close pipe reader in benchmark_test.go to fix file descriptor leak - Use ContinueOnError in flags_test.go to match ResetFlags behavior - Add nil check for p.ui in processor_workers.go before UpdateProgress - Fix resource_monitor_validation_test.go by setting hardMemoryLimitBytes directly * chore(yaml): add missing document start markers Add --- document start to YAML files to satisfy yamllint: - .github/workflows/codeql.yml - .github/workflows/build-test-publish.yml - .github/workflows/security.yml - .github/actions/setup/action.yml * fix: guard nil resourceMonitor and fix test deadlock - Guard resourceMonitor before CreateFileProcessingContext call - Add ui.UpdateProgress on emergency stop and path error returns - Fix potential deadlock in TestProcessFile using wg.Go with defer close
361 lines
9.5 KiB
Bash
Executable File
361 lines
9.5 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
|
|
check_secrets() {
|
|
print_status "Scanning for potential secrets and sensitive data..."
|
|
|
|
local secrets_found=false
|
|
|
|
# Common secret patterns
|
|
local patterns=(
|
|
"password\s*[:=]\s*['\"][^'\"]{3,}['\"]"
|
|
"secret\s*[:=]\s*['\"][^'\"]{3,}['\"]"
|
|
"key\s*[:=]\s*['\"][^'\"]{8,}['\"]"
|
|
"token\s*[:=]\s*['\"][^'\"]{8,}['\"]"
|
|
"api_?key\s*[:=]\s*['\"][^'\"]{8,}['\"]"
|
|
"aws_?access_?key"
|
|
"aws_?secret"
|
|
"AKIA[0-9A-Z]{16}" # AWS Access Key pattern
|
|
"github_?token"
|
|
"private_?key"
|
|
)
|
|
|
|
for pattern in "${patterns[@]}"; do
|
|
if grep -r -i -E "$pattern" --include="*.go" . 2>/dev/null; then
|
|
print_warning "Potential secret pattern found: $pattern"
|
|
secrets_found=true
|
|
fi
|
|
done
|
|
|
|
# Check git history for secrets (last 10 commits)
|
|
if git log --oneline -10 | grep -i -E "(password|secret|key|token)" >/dev/null 2>&1; then
|
|
print_warning "Potential secrets mentioned in recent commit messages"
|
|
secrets_found=true
|
|
fi
|
|
|
|
if [[ "$secrets_found" = true ]]; then
|
|
print_warning "Potential secrets detected. Please review manually."
|
|
return 1
|
|
else
|
|
print_success "No obvious secrets detected"
|
|
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 yamllint -c .yamllint .; then
|
|
print_success "YAML files check passed"
|
|
else
|
|
print_error "YAML file issues detected!"
|
|
return 1
|
|
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)
|
|
- Custom 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
|
|
|
|
### 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 "- security-report.md"
|
|
fi
|
|
|
|
exit $exit_code
|
|
}
|
|
|
|
# Run main function
|
|
main "$@"
|