Skip to main content

Free 30-min security demo  — We'll scan your real code and show live findings, no commitment Book Now

Offensive360
Application Security

dotnet ef RunAnalyzersDuringBuild=false: Fix Migration Errors

dotnet ef failing due to Roslyn analyzers? Use -- /p:RunAnalyzersDuringBuild=false. Exact CLI fix, GitHub Actions & Azure DevOps YAML, and why not to disable analyzers globally.

Offensive360 Security Research Team — min read
dotnet ef RunAnalyzersDuringBuild Roslyn analyzers .NET SAST Entity Framework static code analysis .NET security CI/CD security SAST

If you’ve ever run dotnet ef migrations add or dotnet ef database update in a project with Roslyn security analyzers enabled, you may have seen your EF command fail with build errors that have nothing to do with your migration. The common workaround — passing /p:RunAnalyzersDuringBuild=false — works, but understanding why this conflict happens and what security implications it carries is important for any .NET team using SAST tooling in their CI/CD pipeline.


Why dotnet ef Triggers Roslyn Analyzers

The dotnet ef CLI tool works by building your project to extract EF model and context information. This means it runs dotnet build internally, which invokes the full Roslyn compiler pipeline — including any analyzers configured in your project.

When you have analyzers like:

  • Microsoft.CodeAnalysis.NetAnalyzers (security and quality rules)
  • SecurityCodeScan.VS2019
  • SonarAnalyzer.CSharp
  • Third-party SAST analyzer packages

…and those analyzers are configured with <TreatWarningsAsErrors>true</TreatWarningsAsErrors> or /warnaserror in your .csproj, an analyzer warning becomes a build error. The dotnet ef internal build fails, and your migration command aborts — even though the code is fine for EF purposes.


The Correct Way to Pass /p:RunAnalyzersDuringBuild=false

The flag needs to be passed through dotnet ef’s -- argument separator, which forwards MSBuild properties to the underlying build:

# Pass MSBuild property through the -- separator
dotnet ef migrations add MyMigration -- /p:RunAnalyzersDuringBuild=false

# For database update
dotnet ef database update -- /p:RunAnalyzersDuringBuild=false

# Combined — useful in CI scripts
dotnet ef migrations add "AddUserRoles" -- /p:RunAnalyzersDuringBuild=false
dotnet ef database update -- /p:RunAnalyzersDuringBuild=false

The -- is critical. Arguments before -- are processed by the dotnet ef tool. Arguments after -- are passed directly to MSBuild as additional properties. Without the --, the /p: flag will be interpreted as an unknown argument to dotnet ef and cause a different error.

In an Azure DevOps Pipeline

- task: DotNetCoreCLI@2
  displayName: 'EF Migrations'
  inputs:
    command: 'custom'
    custom: 'ef'
    arguments: 'database update -- /p:RunAnalyzersDuringBuild=false'
    workingDirectory: '$(Build.SourcesDirectory)/src/YourProject'

In GitHub Actions

- name: Apply EF Migrations
  run: |
    dotnet ef database update \
      --project src/YourProject \
      -- /p:RunAnalyzersDuringBuild=false
  env:
    ConnectionStrings__DefaultConnection: ${{ secrets.DB_CONNECTION_STRING }}

In a Makefile or Shell Script

#!/bin/bash
set -e

echo "Applying EF migrations..."
dotnet ef database update \
  --project ./src/DataAccess \
  --startup-project ./src/Api \
  -- /p:RunAnalyzersDuringBuild=false

echo "Migrations complete."

Alternative: Disable Analyzers Only for EF Tool Builds

Instead of passing the flag at the command line each time, you can configure EF build behavior in your .csproj to conditionally skip analyzers when the build is invoked by dotnet ef:

<!-- In your .csproj file -->
<PropertyGroup Condition="'$(EFMigrationsTarget)' == 'true'">
  <!-- Disable analyzers for EF tool builds only -->
  <RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
</PropertyGroup>

However, this approach requires passing -EFMigrationsTarget:true to MSBuild, which isn’t available as a standard EF CLI flag — so the -- /p: method is more practical in most cases.

A cleaner alternative for CI/CD environments is to use a separate MSBuild property group that’s targeted by your migration pipeline but not your security scan pipeline:

<!-- .csproj -->
<PropertyGroup Condition="'$(SkipSecurityAnalyzers)' == 'true'">
  <RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
  <RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>

Then in your CI migration step:

dotnet ef database update -- /p:SkipSecurityAnalyzers=true

And in your security scan step, SkipSecurityAnalyzers is not passed — analyzers run normally.


Why You Should Not Disable Analyzers Globally

It is tempting to solve the dotnet ef problem by adding this to your .csproj globally:

<!-- ⚠️ DO NOT DO THIS — disables ALL analyzer runs -->
<PropertyGroup>
  <RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
</PropertyGroup>

This silently disables all Roslyn security analyzers on every build — not just EF tool builds. If your CI/CD pipeline relies on analyzer warnings/errors to catch security issues (SQL injection, hardcoded credentials, use of BinaryFormatter, etc.), this configuration change will suppress all of them without any error or warning.

The correct approach is surgical: pass /p:RunAnalyzersDuringBuild=false only for the specific EF migration/update commands where analyzers are causing false-fail build errors. Analyzer runs on your actual application build should remain enabled.


Understanding the Security Risk of Analyzer Suppression

Roslyn security analyzers run as part of your build pipeline serve as a fast, low-cost layer of static analysis. The rules most commonly relevant to EF-based projects include:

RuleDescriptionCWE
CA2100SQL Injection in ADO.NETCWE-89
CA3001XSS via HttpResponse.WriteCWE-79
CA3002LDAP injectionCWE-90
CA3006Process command injectionCWE-78
CA3007Open redirectCWE-601
CA3012Regex injectionCWE-730
CA5369Insecure deserialization (XmlSerializer)CWE-502
CA5350/CA5351Weak cryptography (3DES, MD5)CWE-327

When you suppress analyzer runs for migration builds, you’re not affecting your application code’s security posture — EF migration files themselves are not attack surfaces for injection. The risk only materializes when the suppression leaks into your main application build.

What Roslyn Analyzers Miss

Roslyn analyzers are valuable but have significant limitations for security scanning:

  • No interprocedural taint analysis — they detect SQL injection in a single method, but miss injection chains that span multiple methods, classes, or files
  • No detection of second-order injection — data that enters via user input, is stored in the database, and then used unsafely in a later query is invisible to Roslyn analyzers
  • No DAST — Roslyn only analyzes source code, not the running application’s behavior
  • Pattern-based only — complex data flow vulnerabilities require taint analysis that Roslyn’s rule architecture cannot express

This is why Roslyn analyzers are best thought of as a first layer of defense — catching obvious patterns during development — rather than a complete security solution. Enterprise .NET teams typically combine Roslyn analyzers (fast, in-IDE feedback) with a dedicated SAST platform (deep taint analysis, CI gating) such as Offensive360.


The Complete dotnet ef + SAST CI/CD Pattern

Here’s a recommended pattern for a .NET CI/CD pipeline that runs both EF migrations and SAST security scanning without conflict:

GitHub Actions — Full Pattern

name: Build, Migrate & Scan

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

env:
  DOTNET_VERSION: '8.x'
  PROJECT_PATH: 'src/YourApp.Api'

jobs:
  build-and-scan:
    name: Build + Security Analysis
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: ${{ env.DOTNET_VERSION }}

      - name: Restore dependencies
        run: dotnet restore

      - name: Build with Roslyn analyzers enabled
        # Analyzers run here — treat warnings as errors in Production
        run: |
          dotnet build \
            --configuration Release \
            --no-restore \
            /p:RunAnalyzersDuringBuild=true \
            /p:AnalysisLevel=latest-recommended \
            /warnaserror:CA2100,CA3001,CA3006,CA5350,CA5351

  migrate:
    name: Apply EF Migrations
    runs-on: ubuntu-latest
    needs: build-and-scan
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: ${{ env.DOTNET_VERSION }}

      - name: Install EF tools
        run: dotnet tool install --global dotnet-ef

      - name: Apply migrations
        # Analyzers disabled ONLY for the EF migration build step
        run: |
          dotnet ef database update \
            --project ${{ env.PROJECT_PATH }} \
            -- /p:RunAnalyzersDuringBuild=false
        env:
          ConnectionStrings__Default: ${{ secrets.PROD_DB_CONNECTION }}

This pattern ensures:

  1. The main build runs with full analyzer enforcement — any security issue fails the build
  2. EF migrations run separately, with analyzers suppressed only for that step
  3. Migration jobs only run after a successful security-analyzed build

Troubleshooting Common Errors

Error: unknown option '--'

Your dotnet ef version is too old. Update to the latest:

dotnet tool update --global dotnet-ef

MSBuild property '/p:RunAnalyzersDuringBuild=false' is not recognized

This usually means the -- separator is not being used correctly. Ensure you have a space before and after --:

# Correct
dotnet ef migrations add Name -- /p:RunAnalyzersDuringBuild=false

# Wrong — flag parsed by dotnet ef, not MSBuild
dotnet ef migrations add Name /p:RunAnalyzersDuringBuild=false

Analyzers still running after disabling

If analyzers still run after setting RunAnalyzersDuringBuild=false, check whether your analyzer NuGet packages have <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> or a separate MSBuild target that triggers analysis outside the normal build pipeline. Some SonarQube scanner integrations run a separate analysis step that is not controlled by RunAnalyzersDuringBuild.

dotnet ef failing in a container

If running in a Docker build layer:

# Ensure EF CLI is installed in the build layer
RUN dotnet tool install --global dotnet-ef
ENV PATH="$PATH:/root/.dotnet/tools"

# Apply migrations with analyzers disabled
RUN dotnet ef database update -- /p:RunAnalyzersDuringBuild=false

Summary

ScenarioRecommended Command
Run EF migration without analyzer conflictsdotnet ef migrations add Name -- /p:RunAnalyzersDuringBuild=false
Apply database update in CIdotnet ef database update -- /p:RunAnalyzersDuringBuild=false
Main application builddotnet build /p:RunAnalyzersDuringBuild=true
Security scan builddotnet build /warnaserror:CA2100,CA3001,CA3006

The key principle: pass /p:RunAnalyzersDuringBuild=false only to the dotnet ef command, not to your main application build. This eliminates the EF build conflict while preserving security analysis coverage on your application code.

For deeper security coverage beyond what Roslyn analyzers provide — including interprocedural taint analysis, second-order injection detection, and full SAST across your entire .NET codebase — Offensive360 runs as a separate analysis step in your CI/CD pipeline, independent of your Roslyn analyzer configuration.


Looking to add enterprise-grade SAST to your .NET CI/CD pipeline without breaking EF migrations? See how Offensive360 integrates with Azure DevOps, GitHub Actions, and Jenkins — or run a one-time scan for $500 to baseline your current codebase.

Offensive360 Security Research Team

Application Security Research

Updated April 18, 2026

Find vulnerabilities before attackers do

Run Offensive360 SAST and DAST against your applications and get a full vulnerability report in minutes.