CI/CD Security Best Practices

Integrate Bloodhound into your CI/CD pipeline for automated security scanning on every commit and pull request.

Overview

Shift-left security by integrating vulnerability scanning into your development workflow. Catch issues before they reach production.

CI/CD Security Checklist

  • Run security scans on every pull request
  • Block merges on critical vulnerabilities
  • Scan dependencies for known CVEs
  • Use secrets management, never hardcode credentials
  • Implement quality gates with severity thresholds
  • Generate and archive security reports
  • Set up notifications for new vulnerabilities
  • Regularly scan main branch for drift

GitHub Actions

Add Bloodhound scanning to your GitHub Actions workflow.

YAML
1# .github/workflows/security.yml
2name: Security Scan
3
4on:
5 push:
6 branches: [main, develop]
7 pull_request:
8 branches: [main]
9
10jobs:
11 bloodhound-scan:
12 runs-on: ubuntu-latest
13 steps:
14 - uses: actions/checkout@v4
15
16 - name: Setup Node.js
17 uses: actions/setup-node@v4
18 with:
19 node-version: '20'
20
21 - name: Install Bloodhound
22 run: npm install -g @agnech/bloodhound
23
24 - name: Run Security Scan
25 run: |
26 bloodhound scan . \
27 --mode advanced \
28 --output sarif \
29 --output-file results.sarif
30 env:
31 BLOODHOUND_API_KEY: ${{ secrets.BLOODHOUND_API_KEY }}
32
33 - name: Upload SARIF to GitHub
34 uses: github/codeql-action/upload-sarif@v2
35 with:
36 sarif_file: results.sarif
37
38 - name: Check for Critical Issues
39 run: |
40 bloodhound scan . --mode quick --severity critical
41 if [ $? -ne 0 ]; then
42 echo "Critical vulnerabilities found!"
43 exit 1
44 fi

GitLab CI

Configure Bloodhound in your GitLab CI/CD pipeline.

YAML
1# .gitlab-ci.yml
2stages:
3 - test
4 - security
5 - deploy
6
7security_scan:
8 stage: security
9 image: node:20-alpine
10 before_script:
11 - npm install -g @agnech/bloodhound
12 script:
13 - bloodhound scan .
14 --mode advanced
15 --output json
16 --output-file gl-sast-report.json
17 artifacts:
18 reports:
19 sast: gl-sast-report.json
20 paths:
21 - gl-sast-report.json
22 expire_in: 1 week
23 rules:
24 - if: $CI_PIPELINE_SOURCE == "merge_request_event"
25 - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
26
27# Block merge on critical issues
28quality_gate:
29 stage: security
30 needs: [security_scan]
31 script:
32 - |
33 CRITICAL=$(cat gl-sast-report.json | jq '.vulnerabilities | map(select(.severity == "critical")) | length')
34 if [ "$CRITICAL" -gt 0 ]; then
35 echo "Found $CRITICAL critical vulnerabilities"
36 exit 1
37 fi
38 rules:
39 - if: $CI_PIPELINE_SOURCE == "merge_request_event"

Jenkins

Integrate Bloodhound into Jenkins pipelines.

Groovy
1// Jenkinsfile
2pipeline {
3 agent any
4
5 environment {
6 BLOODHOUND_API_KEY = credentials('bloodhound-api-key')
7 }
8
9 stages {
10 stage('Checkout') {
11 steps {
12 checkout scm
13 }
14 }
15
16 stage('Security Scan') {
17 steps {
18 sh '''
19 npm install -g @agnech/bloodhound
20 bloodhound scan . \
21 --mode advanced \
22 --output json \
23 --output-file bloodhound-report.json
24 '''
25 }
26 post {
27 always {
28 archiveArtifacts artifacts: 'bloodhound-report.json'
29 recordIssues(
30 tools: [sarif(pattern: 'bloodhound-report.sarif')]
31 )
32 }
33 }
34 }
35
36 stage('Quality Gate') {
37 steps {
38 script {
39 def report = readJSON file: 'bloodhound-report.json'
40 def criticalCount = report.vulnerabilities
41 .findAll { it.severity == 'critical' }
42 .size()
43
44 if (criticalCount > 0) {
45 error "Found ${criticalCount} critical vulnerabilities"
46 }
47 }
48 }
49 }
50 }
51}

Quality Gates

Define thresholds to automatically block deployments when security standards are not met.

YAML
1# bloodhound.config.yml
2quality_gates:
3 # Block on any critical or high severity issues
4 fail_on_severity:
5 - critical
6 - high
7
8 # Maximum allowed vulnerabilities by severity
9 thresholds:
10 critical: 0
11 high: 0
12 medium: 10
13 low: 50
14
15 # Specific patterns to always fail on
16 fail_on_patterns:
17 - sql-injection
18 - remote-code-execution
19 - hardcoded-credentials
20
21 # Ignore specific paths
22 ignore_paths:
23 - "test/**"
24 - "**/*.test.ts"
25 - "node_modules/**"
26
27# CI mode settings
28ci:
29 output_format: sarif
30 exit_code_on_findings: true
31 comment_on_pr: true

Secrets Management

Never hardcode secrets. Use your CI/CD platform's secrets management.

YAML
1# GitHub Actions - Using encrypted secrets
2env:
3 BLOODHOUND_API_KEY: ${{ secrets.BLOODHOUND_API_KEY }}
4 DATABASE_URL: ${{ secrets.DATABASE_URL }}
5
6# GitLab CI - Using CI/CD variables
7variables:
8 BLOODHOUND_API_KEY: $BLOODHOUND_API_KEY # Set in Settings > CI/CD
9
10# Jenkins - Using credentials plugin
11environment {
12 BLOODHOUND_API_KEY = credentials('bloodhound-api-key')
13}
14
15# Bloodhound will also scan for hardcoded secrets
16bloodhound scan . --mode quick # Detects hardcoded credentials

Secret Scanning

Bloodhound automatically detects hardcoded API keys, passwords, and tokens in your codebase. Enable this in all scans.

Continuous Monitoring

Schedule nightly scans of your main branch to catch vulnerabilities in dependencies that may be disclosed after your last commit.