ci: add Argus security scanning workflow #5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Security Scan | |
| on: | |
| push: | |
| branches: [main, master] | |
| pull_request: | |
| schedule: | |
| - cron: '0 2 * * *' # Daily at 2 AM UTC | |
| repository_dispatch: | |
| types: [cve-update] # Optional: external CVE trigger | |
| workflow_dispatch: # Manual trigger | |
| permissions: | |
| contents: read | |
| security-events: write | |
| pull-requests: write | |
| env: | |
| ARGUS_VERSION: '0.6.8' # Pin version here for easy updates | |
| jobs: | |
| detect: | |
| name: Detect Stack | |
| runs-on: ubuntu-latest | |
| outputs: | |
| languages: ${{ steps.detect.outputs.languages }} | |
| has_container: ${{ steps.detect.outputs.has_container }} | |
| container_buildable: ${{ steps.detect.outputs.container_buildable }} | |
| has_iac: ${{ steps.detect.outputs.has_iac }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Detect repository stack | |
| id: detect | |
| run: | | |
| LANGUAGES="" | |
| # Detect languages | |
| if find . -name '*.rb' -o -name 'Gemfile' 2>/dev/null | grep -q .; then | |
| LANGUAGES="${LANGUAGES}ruby," | |
| fi | |
| if find . -name '*.py' -o -name 'requirements.txt' -o -name 'pyproject.toml' 2>/dev/null | grep -q .; then | |
| LANGUAGES="${LANGUAGES}python," | |
| fi | |
| if find . -name '*.js' -o -name '*.ts' -o -name 'package.json' 2>/dev/null | grep -q .; then | |
| LANGUAGES="${LANGUAGES}javascript," | |
| fi | |
| if find . -name '*.go' -o -name 'go.mod' 2>/dev/null | grep -q .; then | |
| LANGUAGES="${LANGUAGES}go," | |
| fi | |
| if find . -name '*.java' -o -name 'pom.xml' -o -name 'build.gradle' 2>/dev/null | grep -q .; then | |
| LANGUAGES="${LANGUAGES}java," | |
| fi | |
| LANGUAGES="${LANGUAGES%,}" | |
| # Detect container and check if buildable | |
| HAS_CONTAINER="false" | |
| CONTAINER_BUILDABLE="false" | |
| DOCKERFILE_PATH="" | |
| if [ -f "Dockerfile" ]; then | |
| HAS_CONTAINER="true" | |
| DOCKERFILE_PATH="Dockerfile" | |
| elif find . -name 'Dockerfile' -type f 2>/dev/null | grep -q .; then | |
| HAS_CONTAINER="true" | |
| DOCKERFILE_PATH=$(find . -name 'Dockerfile' -type f 2>/dev/null | head -1) | |
| fi | |
| if [ "$HAS_CONTAINER" = "true" ] && [ -n "$DOCKERFILE_PATH" ]; then | |
| # Check if Dockerfile uses private registries (ECR, GCR, ACR, etc.) | |
| PRIVATE_REGISTRY_PATTERNS="\.ecr\.|\.gcr\.io|\.azurecr\.io|\.dkr\.ecr\.|ghcr\.io/[^/]+/[^/]+-private" | |
| # Extract FROM statements (handling ARG-based image refs) | |
| FROM_IMAGES=$(grep -E "^FROM|^ARG.*IMAGE" "$DOCKERFILE_PATH" 2>/dev/null || true) | |
| if echo "$FROM_IMAGES" | grep -qE "$PRIVATE_REGISTRY_PATTERNS"; then | |
| echo "::notice::Dockerfile uses private registry images - skipping container scan" | |
| CONTAINER_BUILDABLE="false" | |
| SKIP_REASON="private registry" | |
| # Check for required build args that likely need secrets | |
| elif grep -qE "^ARG.*(SECRET|TOKEN|KEY|PASSWORD|CREDENTIAL|LICENSE)" "$DOCKERFILE_PATH" 2>/dev/null; then | |
| echo "::notice::Dockerfile requires secret build args - skipping container scan" | |
| CONTAINER_BUILDABLE="false" | |
| SKIP_REASON="requires secrets" | |
| else | |
| CONTAINER_BUILDABLE="true" | |
| fi | |
| fi | |
| # Detect IaC | |
| HAS_IAC="false" | |
| if find . -name '*.tf' -o -name '*cloudformation*.yml' -o -name '*cloudformation*.yaml' 2>/dev/null | grep -q .; then | |
| HAS_IAC="true" | |
| fi | |
| echo "languages=${LANGUAGES}" >> $GITHUB_OUTPUT | |
| echo "has_container=${HAS_CONTAINER}" >> $GITHUB_OUTPUT | |
| echo "container_buildable=${CONTAINER_BUILDABLE}" >> $GITHUB_OUTPUT | |
| echo "has_iac=${HAS_IAC}" >> $GITHUB_OUTPUT | |
| echo "### Stack Detection Results" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Languages:** ${LANGUAGES:-none detected}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Container:** ${HAS_CONTAINER}" >> $GITHUB_STEP_SUMMARY | |
| if [ "$HAS_CONTAINER" = "true" ]; then | |
| if [ "$CONTAINER_BUILDABLE" = "true" ]; then | |
| echo " - **Buildable:** Yes" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo " - **Buildable:** No (${SKIP_REASON:-unknown})" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| fi | |
| echo "- **IaC:** ${HAS_IAC}" >> $GITHUB_STEP_SUMMARY | |
| sast: | |
| name: SAST Scanning | |
| needs: detect | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Full history for Gitleaks | |
| # Always run Gitleaks (secret detection) | |
| - uses: huntridge-labs/argus/.github/actions/scanner-gitleaks@0.6.8 | |
| with: | |
| enable_code_security: true | |
| post_pr_comment: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} | |
| # CodeQL for detected languages | |
| - uses: huntridge-labs/argus/.github/actions/scanner-codeql@0.6.8 | |
| if: needs.detect.outputs.languages != '' | |
| with: | |
| languages: ${{ needs.detect.outputs.languages }} | |
| enable_code_security: true | |
| post_pr_comment: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # OpenGrep for multi-language analysis | |
| - uses: huntridge-labs/argus/.github/actions/scanner-opengrep@0.6.8 | |
| if: needs.detect.outputs.languages != '' | |
| with: | |
| enable_code_security: true | |
| post_pr_comment: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Bandit for Python projects | |
| - uses: huntridge-labs/argus/.github/actions/scanner-bandit@0.6.8 | |
| if: contains(needs.detect.outputs.languages, 'python') | |
| with: | |
| enable_code_security: true | |
| post_pr_comment: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| container: | |
| name: Container Scanning | |
| needs: detect | |
| if: needs.detect.outputs.has_container == 'true' && needs.detect.outputs.container_buildable == 'true' | |
| runs-on: ubuntu-latest | |
| env: | |
| IMAGE_TAG: scan-target:${{ github.sha }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build container for scanning | |
| run: docker build -t "$IMAGE_TAG" . | |
| - uses: huntridge-labs/argus/.github/actions/scanner-container@0.6.8 | |
| with: | |
| image_ref: scan-target:${{ github.sha }} | |
| enable_code_security: true | |
| post_pr_comment: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - uses: huntridge-labs/argus/.github/actions/scanner-syft@0.6.8 | |
| with: | |
| image_ref: scan-target:${{ github.sha }} | |
| post_pr_comment: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| infrastructure: | |
| name: Infrastructure Scanning | |
| needs: detect | |
| if: needs.detect.outputs.has_iac == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: huntridge-labs/argus/.github/actions/scanner-trivy-iac@0.6.8 | |
| with: | |
| enable_code_security: true | |
| post_pr_comment: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - uses: huntridge-labs/argus/.github/actions/scanner-checkov@0.6.8 | |
| with: | |
| enable_code_security: true | |
| post_pr_comment: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| summary: | |
| name: Security Summary | |
| needs: [detect, sast, container, infrastructure] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: huntridge-labs/argus/.github/actions/security-summary@0.6.8 | |
| with: | |
| post_pr_comment: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |