/

CI/CD Pipeline Integration

This guide shows how to integrate ByteHide Shield into various CI/CD pipelines for automated .NET application protection using the MSBuild integration package.

ByteHide Shield can be seamlessly integrated into your CI/CD pipelines to automatically protect your .NET applications during the build process. Unlike the JavaScript CLI approach, .NET Shield protection runs during the dotnet build command through the ByteHide.Shield.Integration NuGet package.

Integration Overview

How .NET CI/CD Integration Works

The .NET integration follows a different pattern from JavaScript, leveraging MSBuild's extensibility:

  1. Package Installation: The ByteHide.Shield.Integration NuGet package is added to your project
  2. Configuration: A shield.config.json file is placed next to your .csproj file
  3. Build Process: During dotnet build, Shield automatically protects the assembly
  4. Token Injection: Project tokens are provided via environment variables or configuration

Key Differences from JavaScript Integration

  • No CLI Installation: Protection runs through MSBuild, not a separate CLI tool
  • Configuration Required: A shield.config.json file is mandatory (can be versioned or generated)
  • Build-Time Protection: Protection happens during compilation, not as a post-build step
  • Per-Project Configuration: Each project requiring protection needs its own configuration file

Integration Approaches

Option A: Existing Configuration File (Recommended)

  • Store shield.config.json files in your repository alongside .csproj files
  • Version control your protection settings
  • Use environment variables for token injection
  • Consistent protection across environments

Option B: Dynamic Configuration Generation

  • Create configuration files during the CI/CD process
  • Inject tokens and settings dynamically
  • Useful for environment-specific configurations

Option C: Release-Only Protection

  • Configure protection to run only on Release builds
  • Faster development builds without protection overhead
  • Production-ready protection for deployments

Prerequisites

Before implementing CI/CD integration, ensure you have:

  • A ByteHide Shield project token (see Get Project Token)
  • The ByteHide.Shield.Integration NuGet package referenced in your projects
  • Understanding of your solution structure and which projects need protection
  • .NET SDK 6.0+ available in your CI/CD environment

Security Considerations

Token Security

Never commit your project token to source control. Always use your CI/CD platform's secret management system to store and inject the token securely.

When integrating Shield into CI/CD pipelines:

  • Store tokens as encrypted secrets in your CI/CD platform
  • Use environment variables for token injection in configuration files
  • Consider different tokens for different environments
  • Regularly rotate your project tokens for enhanced security
  • Limit access to tokens to authorized team members only

Multi-Project Considerations

For solutions with multiple projects:

  • Each project requiring protection needs its own shield.config.json file
  • Place the configuration file in the same directory as the .csproj
  • Different projects can have different protection settings
  • Consider using shared configuration templates for consistency

Azure DevOps Integration

Azure DevOps provides robust CI/CD capabilities that work seamlessly with ByteHide Shield's MSBuild integration.

Setup Process for Azure DevOps

  1. Configure Variables: Set up your SHIELD_PROJECT_TOKEN in Azure DevOps Library
  2. Create Pipeline: Add an azure-pipelines.yml file to your repository
  3. Install .NET SDK: Ensure the pipeline uses .NET 6.0 or later
  4. Build Solution: Use dotnet build - Shield protection runs automatically
  5. Handle Artifacts: Publish the protected assemblies

Azure DevOps Variables Configuration

Configure your project token in Azure DevOps:

  1. Go to PipelinesLibraryVariable groups
  2. Create a new variable group or use an existing one
  3. Add a variable named SHIELD_PROJECT_TOKEN
  4. Set the value to your ByteHide Shield project token
  5. Check Keep this value secret to encrypt the token
  6. Save the variable group

Alternatively, you can set the variable directly in your pipeline:

  1. Go to your pipeline EditVariables
  2. Add a new variable SHIELD_PROJECT_TOKEN
  3. Set the value and mark it as Keep this value secret

Linux Agent Configuration

For Linux-based build agents, use the following template:

# azure-pipelines-dotnet.yml
trigger:
- main

pool:
  vmImage: ubuntu-latest

variables:
  # Secret variable defined in Azure DevOps Library → Keep this value secret
  SHIELD_PROJECT_TOKEN: $(SHIELD_PROJECT_TOKEN)
  BUILD_CONFIGURATION: 'Release' # Change to Debug if needed

steps:
- checkout: self
  clean: true

# Use .NET SDK (adjust version if needed)
- task: UseDotNet@2
  inputs:
    packageType: 'sdk'
    version: '8.x'

# (Optional) Install the integration package if the project doesn't reference it yet
# Tip: Prefer committing the PackageReference in your .csproj instead of doing it here.
# - script: |
#     dotnet add path/to/YourProject.csproj package ByteHide.Shield.Integration
#   displayName: 'Install ByteHide.Shield.Integration (optional)'

# --- Option A (ACTIVE): Use an existing shield.config.json in the repo ---
# Place shield.config.json next to the .csproj you want to protect.
# If you have multiple projects, each protected project needs its own config.
# Nothing to do here—just build.
- script: |
    dotnet restore path/to/YourSolution.sln
    dotnet build path/to/YourSolution.sln -c $(BUILD_CONFIGURATION) -v minimal
  displayName: 'Build .NET (Shield integration via existing config)'

# --- Option B (COMMENTED): Generate a minimal config at build time (wildcard for any config) ---
# - script: |
#     # Write config next to the .csproj
#     PROJECT_DIR="path/to/YourProject" # <-- update this
#     mkdir -p "$PROJECT_DIR"
#     cat > "$PROJECT_DIR/shield.config.json" <<'JSON'
#     {
#       "Name": "My Application Protection",
#       "RunConfiguration": "*",
#       "ProjectToken": "$(SHIELD_PROJECT_TOKEN)",
#       "Preset": "custom",
#       "Protections": {
#         "rename": {},
#         "anti_debug": {},
#         "control_flow_advance": {}
#       }
#     }
#     JSON
#     dotnet restore path/to/YourSolution.sln
#     dotnet build path/to/YourSolution.sln -c $(BUILD_CONFIGURATION) -v minimal
#   displayName: 'Generate config and build (.NET)'

# --- Option C (COMMENTED): Only protect Release builds ---
# - script: |
#     PROJECT_DIR="path/to/YourProject" # <-- update this
#     mkdir -p "$PROJECT_DIR"
#     cat > "$PROJECT_DIR/shield.config.json" <<'JSON'
#     {
#       "Name": "My Application Protection (Release only)",
#       "RunConfiguration": "Release",
#       "ProjectToken": "$(SHIELD_PROJECT_TOKEN)",
#       "Preset": "custom",
#       "Protections": {
#         "rename": {},
#         "anti_debug": {},
#         "control_flow_advance": {}
#       }
#     }
#     JSON
#     # Ensure we build Release to trigger protection
#     dotnet restore path/to/YourSolution.sln
#     dotnet build path/to/YourSolution.sln -c Release -v minimal
#   displayName: 'Generate config (Release-only) and build (.NET)'

# Optional: Publish artifacts
- task: PublishBuildArtifacts@1
  inputs:
    pathToPublish: 'path/to/YourProject/bin/$(BUILD_CONFIGURATION)'
    artifactName: 'protected-application'
  displayName: 'Publish protected artifacts'

Windows Agent Configuration

For Windows-based build agents:

# azure-pipelines-dotnet-windows.yml
trigger:
- main

pool:
  vmImage: windows-latest

variables:
  SHIELD_PROJECT_TOKEN: $(SHIELD_PROJECT_TOKEN)
  BUILD_CONFIGURATION: 'Release'

steps:
- checkout: self
  clean: true

- task: UseDotNet@2
  inputs:
    packageType: 'sdk'
    version: '8.x'

# (Optional) Install integration package if not referenced yet
# - script: dotnet add path\to\YourProject.csproj package ByteHide.Shield.Integration
#   displayName: 'Install ByteHide.Shield.Integration (optional)'

# --- Option A (ACTIVE): Existing config in repo ---
- script: |
    dotnet restore path\to\YourSolution.sln
    dotnet build path\to\YourSolution.sln -c $(BUILD_CONFIGURATION) -v minimal
  displayName: 'Build .NET (Shield integration via existing config)'

# --- Option B (COMMENTED): Generate config at build time (wildcard "*") ---
# - script: |
#     set PROJECT_DIR=path\to\YourProject
#     if not exist "%PROJECT_DIR%" mkdir "%PROJECT_DIR%"
#     > "%PROJECT_DIR%\shield.config.json" (
#       echo {
#       echo   "Name": "My Application Protection",
#       echo   "RunConfiguration": "*",
#       echo   "ProjectToken": "$(SHIELD_PROJECT_TOKEN)",
#       echo   "Preset": "custom",
#       echo   "Protections": { "rename": {}, "anti_debug": {}, "control_flow_advance": {} }
#       echo }
#     )
#     dotnet restore path\to\YourSolution.sln
#     dotnet build path\to\YourSolution.sln -c $(BUILD_CONFIGURATION) -v minimal
#   displayName: 'Generate config and build (.NET)'

# --- Option C (COMMENTED): Release-only protection ---
# - script: |
#     set PROJECT_DIR=path\to\YourProject
#     if not exist "%PROJECT_DIR%" mkdir "%PROJECT_DIR%"
#     > "%PROJECT_DIR%\shield.config.json" (
#       echo {
#       echo   "Name": "My Application Protection (Release only)",
#       echo   "RunConfiguration": "Release",
#       echo   "ProjectToken": "$(SHIELD_PROJECT_TOKEN)",
#       echo   "Preset": "custom",
#       echo   "Protections": { "rename": {}, "anti_debug": {}, "control_flow_advance": {} }
#       echo }
#     )
#     dotnet restore path\to\YourSolution.sln
#     dotnet build path\to\YourSolution.sln -c Release -v minimal
#   displayName: 'Generate config (Release-only) and build (.NET)'

- task: PublishBuildArtifacts@1
  inputs:
    pathToPublish: 'path\to\YourProject\bin\$(BUILD_CONFIGURATION)'
    artifactName: 'protected-application'
  displayName: 'Publish protected artifacts'

GitHub Actions Integration

GitHub Actions provides excellent support for .NET projects with ByteHide Shield integration.

GitHub Actions Setup Process

  1. Create Workflow File: Add a .github/workflows/ YAML file to your repository
  2. Configure Secrets: Add your SHIELD_PROJECT_TOKEN to repository secrets
  3. Setup .NET: Use the official actions/setup-dotnet action
  4. Build with Protection: Run dotnet build - Shield runs automatically

GitHub Secrets Configuration

Configure your project token in GitHub:

  1. Go to your repository SettingsSecrets and variablesActions
  2. Click New repository secret
  3. Name: SHIELD_PROJECT_TOKEN
  4. Value: Your ByteHide Shield project token
  5. Click Add secret

GitHub Actions Workflow Example

# .github/workflows/dotnet-protection.yml
name: Build and Protect .NET Application

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

env:
  BUILD_CONFIGURATION: Release

jobs:
  build-and-protect:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

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

    - name: Restore dependencies
      run: dotnet restore path/to/YourSolution.sln

    - name: Build with Shield protection
      env:
        SHIELD_PROJECT_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}
      run: dotnet build path/to/YourSolution.sln -c ${{ env.BUILD_CONFIGURATION }} --no-restore -v minimal

    - name: Upload protected artifacts
      uses: actions/upload-artifact@v4
      with:
        name: protected-dotnet-app
        path: path/to/YourProject/bin/${{ env.BUILD_CONFIGURATION }}/

GitLab CI Integration

GitLab CI/CD integrates seamlessly with .NET projects and ByteHide Shield.

GitLab CI Setup Process

  1. Create Pipeline File: Add a .gitlab-ci.yml file to your repository root
  2. Configure Variables: Set up your SHIELD_PROJECT_TOKEN in GitLab CI/CD settings
  3. Use .NET Image: Configure appropriate Docker images for .NET builds
  4. Build Solution: Use dotnet build with Shield protection

GitLab Variables Configuration

Configure your project token in GitLab:

  1. Go to your project SettingsCI/CDVariables
  2. Click Add variable
  3. Key: SHIELD_PROJECT_TOKEN
  4. Value: Your ByteHide Shield project token
  5. Check Protect variable and Mask variable for security
  6. Click Add variable

GitLab CI Configuration Example

# .gitlab-ci.yml
stages:
  - build
  - protect

variables:
  BUILD_CONFIGURATION: "Release"

build-and-protect:
  stage: build
  image: mcr.microsoft.com/dotnet/sdk:8.0
  script:
    - dotnet restore path/to/YourSolution.sln
    - dotnet build path/to/YourSolution.sln -c $BUILD_CONFIGURATION -v minimal
  artifacts:
    paths:
      - path/to/YourProject/bin/$BUILD_CONFIGURATION/
    expire_in: 1 hour

Configuration Management

Configuration File Structure

A basic shield.config.json file structure:

{
  "Name": "My Application Protection",
  "RunConfiguration": "*",
  "ProjectToken": "${SHIELD_PROJECT_TOKEN}",
  "Preset": "custom",
  "Protections": {
    "rename": {
      "enabled": true
    },
    "anti_debug": {
      "enabled": true
    },
    "control_flow_advance": {
      "enabled": true
    }
  }
}

Token Injection Strategies

Environment Variable Substitution

{
  "ProjectToken": "${SHIELD_PROJECT_TOKEN}"
}

Direct Token (Not Recommended for CI/CD)

{
  "ProjectToken": "your-actual-token-here"
}

Multi-Environment Configurations

Create different configuration files for different environments:

MyProject/
├── shield.config.json              (default)
├── shield.config.development.json  (development)
├── shield.config.staging.json      (staging)
└── shield.config.production.json   (production)

Key Integration Points

Where Configuration Files Go

  • Single Project: Place shield.config.json next to your .csproj file
  • Multiple Projects: Each protected project needs its own configuration file
  • Solution Level: No solution-level configuration - it's always per-project

When Protection Runs

Protection occurs during the dotnet build process when:

  • The RunConfiguration in your config matches the build configuration (-c Release)
  • Or RunConfiguration is set to "*" (wildcard - runs on any configuration)

NuGet Package Requirements

Ensure your projects reference the Shield integration package:

<PackageReference Include="ByteHide.Shield.Integration" Version="latest" />

The package can be added via:

  • Package Manager UI in Visual Studio
  • dotnet add package ByteHide.Shield.Integration
  • Direct PackageReference in .csproj

Troubleshooting

Common Issues

Configuration File Not Found

  • Ensure shield.config.json is in the same directory as your .csproj
  • Check file naming and case sensitivity on Linux builds
  • Verify the file is included in your repository

Token Not Recognized

  • Verify environment variable name matches your configuration
  • Check that the secret is properly configured in your CI/CD platform
  • Ensure proper escaping in JSON configuration

Protection Not Running

  • Check that RunConfiguration matches your build configuration
  • Verify the NuGet package is properly referenced
  • Look for Shield-related messages in build output

Multiple Projects Not Protected

  • Each project needs its own shield.config.json file
  • Verify each project references the NuGet package
  • Check that paths in your CI/CD scripts are correct

Performance Optimization

For large solutions:

  • Use specific build configurations for protection
  • Consider protecting only Release builds to speed up development
  • Implement parallel builds where possible
  • Cache NuGet packages between builds

Next Steps

Previous
Configure Protections