Integrating Security Into Your CI/CD Pipeline

Adding security to your CI/CD pipeline means every commit, pull request, and release goes through automated checks before it reaches production. This guide shows how to set up Radar as a security gate, Shield as a build step, and Secrets as a credential manager in the most common CI/CD platforms.


What Goes Where in the Pipeline

Security tools fit into specific stages of the CI/CD pipeline. Each stage runs different checks:

On commit / PR: Radar scans the code for vulnerabilities (SAST), insecure dependencies (SCA), and exposed secrets. This is the security gate. If critical issues are found, the pipeline fails before the code merges.

After build: Shield protects the compiled binary with obfuscation, string encryption, and anti-tamper checks. This runs only on release/production builds.

Throughout: ByteHide Secrets manages credentials. The pipeline injects the project token and any required secrets without storing them in code or configuration files.


Setting Up Radar as a Security Gate

Radar scans your repository for three categories of issues:

  • SAST: Code vulnerabilities mapped to OWASP Top 10 and CWE
  • SCA: Known CVEs in your dependencies
  • Secrets: Hardcoded credentials, API keys, and tokens

GitHub Actions

YAML
name: Security Scan
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  radar-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run ByteHide Radar
        uses: bytehide/radar-action@v1
        with:
          api-key: ${{ secrets.BYTEHIDE_API_KEY }}
          project-token: ${{ secrets.BYTEHIDE_PROJECT_TOKEN }}
          fail-on: critical

The fail-on parameter controls the threshold. Set it to critical to fail only on critical findings, high to include high-severity issues, or medium for a stricter gate.

Azure DevOps

YAML
trigger:
  branches:
    include:
      - main

pool:
  vmImage: 'ubuntu-latest'

steps:
  - task: Bash@3
    displayName: 'Run ByteHide Radar'
    inputs:
      targetType: 'inline'
      script: |
        npx @bytehide/radar-cli scan \
          --api-key $(BYTEHIDE_API_KEY) \
          --project-token $(BYTEHIDE_PROJECT_TOKEN) \
          --fail-on critical
    env:
      BYTEHIDE_API_KEY: $(BYTEHIDE_API_KEY)
      BYTEHIDE_PROJECT_TOKEN: $(BYTEHIDE_PROJECT_TOKEN)

GitLab CI

YAML
radar-scan:
  stage: test
  image: node:20
  script:
    - npx @bytehide/radar-cli scan
        --api-key $BYTEHIDE_API_KEY
        --project-token $BYTEHIDE_PROJECT_TOKEN
        --fail-on critical
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"

See the full Radar CI/CD Integration documentation for additional options, output formats, and advanced configuration.


Adding Shield as a Build Step

Shield protects the compiled binary. It runs after the build and before deployment.

.NET with MSBuild (NuGet Package)

The simplest integration for .NET is the NuGet package. It runs automatically during dotnet publish:

YAML
# GitHub Actions example
- name: Build and Protect
  run: dotnet publish -c Release
  env:
    BYTEHIDE_PROJECT_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}

No additional step is needed. Shield runs as part of the MSBuild pipeline. See MSBuild CI/CD Integration.

.NET with CLI

For more control, use the Shield CLI as a separate step:

YAML
- name: Build
  run: dotnet publish -c Release -o ./publish

- name: Protect with Shield
  run: |
    dotnet tool install -g ByteHide.Shield.CLI
    shield protect \
      --project ${{ secrets.SHIELD_PROJECT_TOKEN }} \
      --input ./publish/

Android with Gradle

Shield for Android integrates as a Gradle plugin. Protection runs automatically during the release build:

YAML
- name: Build Protected APK
  run: ./gradlew assembleRelease
  env:
    BYTEHIDE_PROJECT_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}

See Android Gradle Setup and Android CI/CD.

iOS with CLI

Shield for iOS runs as a post-build step on the IPA:

YAML
- name: Build IPA
  run: |
    xcodebuild -workspace MyApp.xcworkspace \
      -scheme MyApp -configuration Release \
      -archivePath build/MyApp.xcarchive archive
    xcodebuild -exportArchive \
      -archivePath build/MyApp.xcarchive \
      -exportOptionsPlist ExportOptions.plist \
      -exportPath build/

- name: Protect IPA
  run: |
    pip install shield-ios
    shield-ios protect \
      --input build/MyApp.ipa \
      --config shield-ios.json

See iOS CI/CD for full pipeline configuration.

JavaScript with Bundler Plugin

Shield for JavaScript integrates into your bundler. No separate CI step is needed:

JavaScript
// webpack.config.js
const ShieldPlugin = require('@bytehide/shield-webpack-plugin');

module.exports = {
  plugins: [
    new ShieldPlugin({
      projectToken: process.env.BYTEHIDE_PROJECT_TOKEN,
    }),
  ],
};

See Webpack Installation, Vite Installation, or Next.js Installation.


Managing Secrets in the Pipeline

Credentials needed during the build (project tokens, API keys, signing certificates) should never be stored in the repository. Use your CI platform's secret management to inject them as environment variables.

PlatformWhere to Store Secrets
GitHub ActionsSettings > Secrets and variables > Actions
Azure DevOpsPipelines > Library > Variable groups
GitLab CISettings > CI/CD > Variables

For application-level secrets (database passwords, third-party API keys used at runtime), use ByteHide Secrets to manage them in a centralized vault. The application retrieves them at runtime, so they never appear in your build configuration or artifacts.

See Securing API Keys and Secrets in Your Codebase for the full approach.


Complete Pipeline Example

Here is a complete GitHub Actions workflow that combines all three: Radar scanning on PRs, Shield protection on release builds, and secret injection throughout.

YAML
name: Security Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  # Stage 1: Security Scan (runs on every PR and push)
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Radar Scan
        uses: bytehide/radar-action@v1
        with:
          api-key: ${{ secrets.BYTEHIDE_API_KEY }}
          project-token: ${{ secrets.RADAR_PROJECT_TOKEN }}
          fail-on: critical

  # Stage 2: Build and Protect (runs only on main)
  build-and-protect:
    runs-on: ubuntu-latest
    needs: security-scan
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.0.x'

      - name: Build and Protect
        run: dotnet publish -c Release -o ./publish
        env:
          BYTEHIDE_PROJECT_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}

      - name: Upload Artifact
        uses: actions/upload-artifact@v4
        with:
          name: protected-build
          path: ./publish/

Pipeline Strategy by Application Type

Different application types need different pipeline configurations:

Application TypeRadarShield StepNotes
.NET API / BackendSAST + SCA + SecretsMSBuild (NuGet) or CLIAdd Monitor for runtime RASP
.NET DesktopSAST + SCA + SecretsMSBuild (NuGet) or CLIAdd anti-debug and anti-dump
Android MobileSAST + SCA + SecretsGradle pluginAdd Monitor for mobile RASP
iOS MobileSAST + SCA + SecretsCLI post-buildAdd Monitor for mobile RASP
JavaScript WebSAST + SCA + SecretsBundler pluginRuns during webpack/vite build
Unity GameSAST + SecretsMSBuild (NuGet)Test protected build on target platforms

Notifications

Configure Radar to send notifications when new findings are detected:

  • GitHub: Radar can post results as PR comments and status checks. See GitHub Integration.
  • Webhooks: Send findings to Slack, Teams, or any webhook endpoint. See Notifications.

Next Steps

Previous
Security Pipeline: Dev to Production