Skip to content

fix(ci): remove duplicate trufflehog no-update flag #23

fix(ci): remove duplicate trufflehog no-update flag

fix(ci): remove duplicate trufflehog no-update flag #23

Workflow file for this run

name: DevSecOps Pipeline
on:
push:
branches: [ "main", "master" ]
pull_request:
branches: [ "main", "master" ]
schedule:
- cron: '0 0 * * 0' # Weekly baseline scan
workflow_dispatch:
permissions:
security-events: write
contents: read
packages: write # For pushing images/signatures
id-token: write # For Cosign OIDC (optional)
pull-requests: write # For posting comments
jobs:
secret-scan:
name: Secret Scan (TruffleHog)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: TruffleHog (Diff Mode)
if: github.event_name == 'push' || github.event_name == 'pull_request'
uses: trufflesecurity/trufflehog@abecab0d8fb9fb3e79366abc3909825488e9bb40 # v3.82.12
with:
extra_args: --only-verified
- name: TruffleHog (Baseline Mode)
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
uses: trufflesecurity/trufflehog@abecab0d8fb9fb3e79366abc3909825488e9bb40 # v3.82.12
with:
extra_args: --only-verified --since-commit HEAD
sast-scan:
name: SAST (Semgrep)
runs-on: ubuntu-latest
if: github.actor != 'dependabot[bot]'
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Semgrep Scan
run: |
docker run --rm -v $(pwd):/src semgrep/semgrep semgrep scan --config auto --sarif --output /src/semgrep.sarif
continue-on-error: true
- name: Upload SARIF
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
if: always()
with:
name: semgrep.sarif
path: semgrep.sarif
- name: Upload Security SARIF (CodeQL)
uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
if: always()
continue-on-error: true
with:
sarif_file: semgrep.sarif
sca-scan:
name: SCA (Snyk)
runs-on: ubuntu-latest
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: '16'
- name: Install dependencies
run: |
if [ -f package.json ]; then
npm ci || npm install || true
else
echo "No package.json at repository root; skipping npm install."
fi
- name: Install Snyk CLI
if: env.SNYK_TOKEN != ''
run: npm install -g snyk
- name: Snyk Scan
if: env.SNYK_TOKEN != ''
env:
SNYK_TOKEN: ${{ env.SNYK_TOKEN }}
run: snyk test --all-projects --severity-threshold=high --sarif-file-output=snyk.sarif || true
- name: Upload SARIF
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
if: always() && env.SNYK_TOKEN != ''
with:
name: snyk.sarif
path: snyk.sarif
- name: Upload Security SARIF (CodeQL)
uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
if: always() && env.SNYK_TOKEN != ''
continue-on-error: true
with:
sarif_file: snyk.sarif
- name: Snyk Gatekeeper
if: env.SNYK_TOKEN != ''
continue-on-error: true
env:
SNYK_TOKEN: ${{ env.SNYK_TOKEN }}
run: snyk test --all-projects --severity-threshold=high
- name: Skip Snyk (No Token)
if: env.SNYK_TOKEN == ''
run: echo "SNYK_TOKEN not set. Skipping SCA scan."
iac-scan:
name: IaC Scan (Checkov)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install Checkov
run: python3 -m pip install --upgrade pip checkov
- name: Checkov Scan
run: checkov -d ./terraform --quiet --compact --soft-fail --output sarif > checkov.sarif || true
- name: Upload SARIF
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
if: always()
with:
name: checkov.sarif
path: checkov.sarif
- name: Upload Security SARIF (CodeQL)
uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
if: always()
continue-on-error: true
with:
sarif_file: checkov.sarif
cost-estimation:
name: FinOps (Infracost)
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
env:
INFRACOST_API_KEY: ${{ secrets.INFRACOST_API_KEY }}
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install Infracost
if: env.INFRACOST_API_KEY != ''
run: |
curl -fsSL https://raw.githubusercontent.com/infracost/infracost/master/scripts/install.sh | sh
echo "$HOME/.infracost/bin" >> "$GITHUB_PATH"
- name: Infracost Breakdown
if: env.INFRACOST_API_KEY != ''
run: |
infracost breakdown --path ./terraform --format json --out-file infracost-usage.json
- name: Post Infracost Comment
if: github.event_name == 'pull_request' && env.INFRACOST_API_KEY != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
infracost comment github --path infracost-usage.json --repo $GITHUB_REPOSITORY --pull-request ${{ github.event.pull_request.number }} --behavior update
- name: Skip Infracost (No API Key)
if: env.INFRACOST_API_KEY == ''
run: echo "INFRACOST_API_KEY not set. Skipping cost estimation."
container-build-sign:
name: Build & Sign (Trivy + Cosign)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Build Docker Image
run: docker build -t my-app:${{ github.sha }} .
# 1. Scan (Trivy)
- name: Trivy Image Scan (SARIF)
uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # 0.24.0
with:
image-ref: 'my-app:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
ignore-unfixed: true
vuln-type: 'os,library'
- name: Upload SARIF
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
if: always()
with:
name: trivy-results.sarif
path: trivy-results.sarif
- name: Upload Security SARIF (CodeQL)
uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
if: always()
continue-on-error: true
with:
sarif_file: trivy-results.sarif
- name: Trivy Gatekeeper
uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # 0.24.0
continue-on-error: true
with:
image-ref: 'my-app:${{ github.sha }}'
exit-code: '1'
ignore-unfixed: true
severity: 'CRITICAL,HIGH'
# 2. Sign (Cosign) - mock step for demo
- name: Sign Image
if: github.event_name != 'pull_request'
env:
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
run: |
if [[ -z "$COSIGN_PRIVATE_KEY" ]]; then
echo "Skipping signing: COSIGN_PRIVATE_KEY not set."
else
echo "Cosign key detected. Mock signing for demo."
echo "signature" > cosign.sig
fi
- name: Generate SBOM (SPDX)
uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # 0.24.0
with:
image-ref: 'my-app:${{ github.sha }}'
format: 'spdx-json'
output: 'sbom.spdx.json'
- name: Upload SBOM
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: sbom
path: sbom.spdx.json
dast-scan:
name: Runtime Security (DAST)
runs-on: ubuntu-latest
needs: [container-build-sign]
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Build & Run Container
run: |
docker build -t my-app:${{ github.sha }} .
docker run -d -p 3000:3000 --name test-app my-app:${{ github.sha }}
sleep 5
- name: OWASP ZAP Baseline Scan
uses: zaproxy/action-baseline@290a611c039d91f868c6e26487e0766324263720 # v0.14.0
continue-on-error: true
with:
target: 'http://localhost:3000'
fail_action: false
compliance-audit:
name: Generate Compliance Artifacts
runs-on: ubuntu-latest
needs: [secret-scan, sast-scan, sca-scan, iac-scan, container-build-sign, dast-scan]
if: always()
outputs:
hashes: ${{ steps.hash.outputs.hashes }}
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Download All Artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
path: results
merge-multiple: true
- name: Generate Source SBOM
run: |
mkdir -p results
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
/usr/local/bin/syft dir:. -o spdx-json > results/sbom-source.spdx.json
/usr/local/bin/syft dir:. -o cyclonedx-json > results/sbom-source.cdx.json
- name: Upload SBOM Artifacts
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: sbom-reports
path: results/sbom-*
- name: Generate Audit Record
run: |
echo "{" > results/deployment-audit.json
echo " \"timestamp\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\"," >> results/deployment-audit.json
echo " \"repository\": \"$GITHUB_REPOSITORY\"," >> results/deployment-audit.json
echo " \"commit_sha\": \"$GITHUB_SHA\"," >> results/deployment-audit.json
echo " \"actor\": \"$GITHUB_ACTOR\"," >> results/deployment-audit.json
echo " \"workflow_run_id\": \"$GITHUB_RUN_ID\"," >> results/deployment-audit.json
echo "}" >> results/deployment-audit.json
- name: Upload Audit Artifact
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: deployment-audit
path: results/deployment-audit.json
- name: Run Policy Check
run: ./scripts/fortressci-policy-check.sh .security/policy.yml results/
- name: Generate Compliance Report
run: python3 scripts/generate-compliance-report.py results/ .security/compliance-mappings.yml
- name: AI Triage
if: always() && env.ANTHROPIC_API_KEY != ''
run: python3 scripts/ai-triage.py --results-dir results/ --config .fortressci.yml
- name: Generate Security Badge
if: always()
run: python3 scripts/generate-badge.py results/
- name: Build Attack Graph
if: always()
run: python3 scripts/build-attack-graph.py results/
- name: Generate Hashes
id: hash
run: |
cd results
echo "hashes=$(sha256sum sbom-source.spdx.json sbom-source.cdx.json deployment-audit.json | base64 -w0)" >> "$GITHUB_OUTPUT"
provenance:
name: Provenance Summary
runs-on: ubuntu-latest
needs: [compliance-audit]
if: needs.compliance-audit.result == 'success'
steps:
- name: Generate provenance summary
run: |
cat > provenance.json <<EOF
{
"workflow_run_id": "${GITHUB_RUN_ID}",
"repository": "${GITHUB_REPOSITORY}",
"commit_sha": "${GITHUB_SHA}",
"generated_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
"compliance_hashes_b64": "${{ needs.compliance-audit.outputs.hashes }}"
}
EOF
- name: Upload Provenance Artifact
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: provenance
path: provenance.json
pr-feedback:
name: Developer Feedback (PR Comments)
runs-on: ubuntu-latest
needs: [sast-scan, sca-scan, iac-scan, container-build-sign]
if: always() && github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Download All Artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
merge-multiple: true
- name: Post Summary to PR
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const script = require('./.github/scripts/post_summary.js')
await script({github, context})
auto-remediation:
name: Auto-Remediation (PR)
runs-on: ubuntu-latest
needs: [sast-scan, sca-scan, iac-scan]
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Run Auto-Fix
run: ./scripts/auto-fix.sh
- name: Create Pull Request
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84617901 # v6.0.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "fix: auto-remediation of security findings"
title: "🏰 FortressCI Auto-Remediation"
body: |
This is an automated pull request from FortressCI to fix security findings.
Scanners: Snyk, Checkov
branch: fortressci/auto-remediation
base: main
labels: |
security
automated