Add Gitea Actions workflows, CI config, and docs
This commit is contained in:
211
.gitea/workflows/security.yml
Normal file
211
.gitea/workflows/security.yml
Normal file
@@ -0,0 +1,211 @@
|
||||
# =============================================================================
|
||||
# Security Workflow — Secret Scanning & Vulnerability Detection
|
||||
# =============================================================================
|
||||
#
|
||||
# DISABLED BY DEFAULT (ENABLE_SECURITY=false in .ci/config.env).
|
||||
#
|
||||
# When enabled, this workflow runs:
|
||||
# 1. gitleaks — scans for hardcoded secrets in the repo
|
||||
# 2. osv-scanner — checks dependencies for known vulnerabilities
|
||||
# 3. trivy — scans Docker images for CVEs (if a built image exists)
|
||||
#
|
||||
# STRICT_SECURITY=true → any finding fails the workflow
|
||||
# STRICT_SECURITY=false → findings are logged as warnings (default)
|
||||
#
|
||||
# This is "best effort" — tools that aren't available are skipped.
|
||||
# See docs/SECURITY.md for full details.
|
||||
# =============================================================================
|
||||
|
||||
name: Security
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
security:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# -----------------------------------------------------------------------
|
||||
# Step 1: Checkout
|
||||
# -----------------------------------------------------------------------
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Step 2: Load configuration
|
||||
# -----------------------------------------------------------------------
|
||||
- name: Load config
|
||||
run: |
|
||||
if [ -f .ci/config.env ]; then
|
||||
set -a
|
||||
source .ci/config.env
|
||||
set +a
|
||||
fi
|
||||
|
||||
echo "ENABLE_SECURITY=${ENABLE_SECURITY:-false}" >> "$GITHUB_ENV"
|
||||
echo "STRICT_SECURITY=${STRICT_SECURITY:-false}" >> "$GITHUB_ENV"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Step 3: Check if security scanning is enabled
|
||||
# -----------------------------------------------------------------------
|
||||
- name: Check if enabled
|
||||
run: |
|
||||
if [ "$ENABLE_SECURITY" != "true" ]; then
|
||||
echo "Security scanning is disabled (ENABLE_SECURITY=$ENABLE_SECURITY)."
|
||||
echo "To enable, set ENABLE_SECURITY=true in .ci/config.env"
|
||||
echo "SKIP_SECURITY=true" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Step 4: Gitleaks — Secret scanning
|
||||
#
|
||||
# Scans the git history for accidentally committed secrets
|
||||
# (API keys, passwords, tokens, etc.)
|
||||
# -----------------------------------------------------------------------
|
||||
- name: Run gitleaks
|
||||
if: env.SKIP_SECURITY != 'true'
|
||||
run: |
|
||||
FINDINGS=0
|
||||
|
||||
# Install gitleaks
|
||||
echo "Installing gitleaks..."
|
||||
GITLEAKS_VERSION="8.18.4"
|
||||
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" | \
|
||||
tar xz -C /usr/local/bin gitleaks || {
|
||||
echo "WARNING: Failed to install gitleaks, skipping secret scan."
|
||||
exit 0
|
||||
}
|
||||
|
||||
echo ">>> gitleaks detect"
|
||||
if ! gitleaks detect --source . --verbose; then
|
||||
FINDINGS=1
|
||||
echo "gitleaks found potential secrets!"
|
||||
fi
|
||||
|
||||
if [ "$FINDINGS" -ne 0 ]; then
|
||||
if [ "$STRICT_SECURITY" = "true" ]; then
|
||||
echo "ERROR: Secret scan found issues (STRICT_SECURITY=true)"
|
||||
exit 1
|
||||
else
|
||||
echo "WARNING: Secret scan found issues (STRICT_SECURITY=false, continuing)"
|
||||
fi
|
||||
else
|
||||
echo "gitleaks: no secrets found."
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Step 5: OSV-Scanner — Dependency vulnerability scanning
|
||||
#
|
||||
# Checks lockfiles (requirements.txt, package-lock.json, etc.) against
|
||||
# the OSV database for known vulnerabilities.
|
||||
# -----------------------------------------------------------------------
|
||||
- name: Run osv-scanner
|
||||
if: env.SKIP_SECURITY != 'true'
|
||||
run: |
|
||||
FINDINGS=0
|
||||
|
||||
# Check if there's anything to scan
|
||||
HAS_DEPS=false
|
||||
for f in requirements.txt package-lock.json yarn.lock pnpm-lock.yaml go.sum Cargo.lock; do
|
||||
if [ -f "$f" ]; then
|
||||
HAS_DEPS=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$HAS_DEPS" = "false" ]; then
|
||||
echo "SKIP: No dependency lockfiles found for osv-scanner."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Install osv-scanner
|
||||
echo "Installing osv-scanner..."
|
||||
OSV_VERSION="1.8.3"
|
||||
curl -sSfL "https://github.com/google/osv-scanner/releases/download/v${OSV_VERSION}/osv-scanner_linux_amd64" \
|
||||
-o /usr/local/bin/osv-scanner && chmod +x /usr/local/bin/osv-scanner || {
|
||||
echo "WARNING: Failed to install osv-scanner, skipping."
|
||||
exit 0
|
||||
}
|
||||
|
||||
echo ">>> osv-scanner --recursive ."
|
||||
if ! osv-scanner --recursive .; then
|
||||
FINDINGS=1
|
||||
echo "osv-scanner found vulnerabilities!"
|
||||
fi
|
||||
|
||||
if [ "$FINDINGS" -ne 0 ]; then
|
||||
if [ "$STRICT_SECURITY" = "true" ]; then
|
||||
echo "ERROR: Dependency scan found issues (STRICT_SECURITY=true)"
|
||||
exit 1
|
||||
else
|
||||
echo "WARNING: Dependency scan found issues (STRICT_SECURITY=false, continuing)"
|
||||
fi
|
||||
else
|
||||
echo "osv-scanner: no vulnerabilities found."
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Step 6: Trivy — Container image scanning
|
||||
#
|
||||
# Scans a Docker image for OS and library CVEs.
|
||||
# Only runs if a Dockerfile exists (assumes image was built).
|
||||
# -----------------------------------------------------------------------
|
||||
- name: Run trivy
|
||||
if: env.SKIP_SECURITY != 'true'
|
||||
run: |
|
||||
if [ ! -f Dockerfile ]; then
|
||||
echo "SKIP: No Dockerfile found, skipping Trivy image scan."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
FINDINGS=0
|
||||
|
||||
# Install trivy
|
||||
echo "Installing trivy..."
|
||||
curl -sSfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | \
|
||||
sh -s -- -b /usr/local/bin || {
|
||||
echo "WARNING: Failed to install trivy, skipping."
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Build the image first so Trivy can scan it
|
||||
IMAGE_TAG="security-scan:local"
|
||||
echo ">>> docker build -t ${IMAGE_TAG} ."
|
||||
docker build -t "${IMAGE_TAG}" . || {
|
||||
echo "WARNING: Docker build failed, skipping Trivy scan."
|
||||
exit 0
|
||||
}
|
||||
|
||||
echo ">>> trivy image ${IMAGE_TAG}"
|
||||
if ! trivy image --exit-code 1 --severity HIGH,CRITICAL "${IMAGE_TAG}"; then
|
||||
FINDINGS=1
|
||||
echo "Trivy found vulnerabilities in the Docker image!"
|
||||
fi
|
||||
|
||||
if [ "$FINDINGS" -ne 0 ]; then
|
||||
if [ "$STRICT_SECURITY" = "true" ]; then
|
||||
echo "ERROR: Image scan found issues (STRICT_SECURITY=true)"
|
||||
exit 1
|
||||
else
|
||||
echo "WARNING: Image scan found issues (STRICT_SECURITY=false, continuing)"
|
||||
fi
|
||||
else
|
||||
echo "trivy: no HIGH/CRITICAL vulnerabilities found."
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Step 7: Summary
|
||||
# -----------------------------------------------------------------------
|
||||
- name: Security Summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "=============================="
|
||||
echo " Security Workflow Complete"
|
||||
echo " Enabled: ${ENABLE_SECURITY:-false}"
|
||||
echo " Strict: ${STRICT_SECURITY:-false}"
|
||||
echo "=============================="
|
||||
Reference in New Issue
Block a user