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
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: criticalname: 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: criticalThe 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
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)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
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"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:
# GitHub Actions example
- name: Build and Protect
run: dotnet publish -c Release
env:
BYTEHIDE_PROJECT_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}# 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:
- 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/- 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:
- name: Build Protected APK
run: ./gradlew assembleRelease
env:
BYTEHIDE_PROJECT_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}- 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:
- 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- 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.jsonSee iOS CI/CD for full pipeline configuration.
JavaScript with Bundler Plugin
Shield for JavaScript integrates into your bundler. No separate CI step is needed:
// webpack.config.js
const ShieldPlugin = require('@bytehide/shield-webpack-plugin');
module.exports = {
plugins: [
new ShieldPlugin({
projectToken: process.env.BYTEHIDE_PROJECT_TOKEN,
}),
],
};// 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.
| Platform | Where to Store Secrets |
|---|---|
| GitHub Actions | Settings > Secrets and variables > Actions |
| Azure DevOps | Pipelines > Library > Variable groups |
| GitLab CI | Settings > 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.
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/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 Type | Radar | Shield Step | Notes |
|---|---|---|---|
| .NET API / Backend | SAST + SCA + Secrets | MSBuild (NuGet) or CLI | Add Monitor for runtime RASP |
| .NET Desktop | SAST + SCA + Secrets | MSBuild (NuGet) or CLI | Add anti-debug and anti-dump |
| Android Mobile | SAST + SCA + Secrets | Gradle plugin | Add Monitor for mobile RASP |
| iOS Mobile | SAST + SCA + Secrets | CLI post-build | Add Monitor for mobile RASP |
| JavaScript Web | SAST + SCA + Secrets | Bundler plugin | Runs during webpack/vite build |
| Unity Game | SAST + Secrets | MSBuild (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
- Radar CI/CD Integration - Full reference for all CI platforms
- Setting Up a Security Pipeline - The complete security lifecycle
- Securing API Keys and Secrets - Eliminate hardcoded credentials