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 -- /p:RunAnalyzersDuringBuild=false: Complete Guide

Fix dotnet ef migrations and database update failures caused by Roslyn analyzers. Exact commands, CI/CD YAML, .csproj config, and security implications explained.

Offensive360 Security Research Team — min read
dotnet ef RunAnalyzersDuringBuild RunAnalyzersDuringBuild=false dotnet ef migrations dotnet ef database update Roslyn analyzers .NET SAST Entity Framework static code analysis .NET security CI/CD security SAST dotnet ef runanalyzersduring build false dotnet ef runanalyzers dotnet ef migrations runanalyzersduring build

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 fix is to pass RunAnalyzersDuringBuild=false through the -- MSBuild separator:

# Quick fix — pass the flag after the -- separator
dotnet ef migrations add MyMigration -- /p:RunAnalyzersDuringBuild=false
dotnet ef database update -- /p:RunAnalyzersDuringBuild=false

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. Read on for CI/CD YAML, .csproj config, troubleshooting, and the complete safe pattern.


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

Quick Reference: All RunAnalyzersDuringBuild Command Variants

The exact command varies depending on your shell, OS, and EF operation. Every variant below is equivalent — pick whichever matches your environment:

dotnet ef migrations add

# Windows-style MSBuild property (works on all platforms)
dotnet ef migrations add MyMigration -- /p:RunAnalyzersDuringBuild=false

# Unix-style MSBuild property (works on all platforms)
dotnet ef migrations add MyMigration -- -p:RunAnalyzersDuringBuild=false

# With explicit project path
dotnet ef migrations add MyMigration \
  --project src/DataAccess \
  --startup-project src/Api \
  -- /p:RunAnalyzersDuringBuild=false

dotnet ef database update

# Apply all pending migrations
dotnet ef database update -- /p:RunAnalyzersDuringBuild=false

# Target a specific migration
dotnet ef database update MyMigration -- /p:RunAnalyzersDuringBuild=false

# With explicit project paths
dotnet ef database update \
  --project src/DataAccess \
  --startup-project src/Api \
  -- /p:RunAnalyzersDuringBuild=false

Both slash and dash prefix work

The MSBuild property syntax is flexible — /p: (Windows-style) and -p: (Unix-style) are interchangeable on all platforms in modern .NET:

# These are identical in behavior:
dotnet ef migrations add Name -- /p:RunAnalyzersDuringBuild=false
dotnet ef migrations add Name -- -p:RunAnalyzersDuringBuild=false

# On Windows PowerShell, quote if the shell strips the slash:
dotnet ef migrations add Name -- "/p:RunAnalyzersDuringBuild=false"

Frequently Asked Questions

Does dotnet ef with -- and /p:RunAnalyzersDuringBuild=false work on Linux and macOS?

Yes. Both /p: and -p: prefix styles work on Linux, macOS, and Windows. The -- separator is a standard EF CLI feature available in EF Core 5.0+ tooling. If you receive Error: unknown option '--', update your EF tools: dotnet tool update --global dotnet-ef.

Why does dotnet ef migrations add run my analyzers at all?

Because dotnet ef builds your project internally to discover the DbContext and apply the EF model. That internal build triggers the full MSBuild pipeline, including Roslyn analyzer execution. If your analyzers emit errors (due to <TreatWarningsAsErrors>true</TreatWarningsAsErrors>), the internal build fails and the EF command aborts.

Can I add RunAnalyzersDuringBuild=false permanently in my .csproj?

You can, but you should not do so unconditionally — that disables analyzers on all builds including your security scan build. Use a conditional property group instead:

<!-- Disable analyzers only during design-time / EF tool builds -->
<PropertyGroup Condition="'$(DesignTimeBuild)' == 'true'">
  <RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
</PropertyGroup>

What is the difference between -p:RunAnalyzersDuringBuild=false and -- /p:RunAnalyzersDuringBuild=false?

The -- is the argument separator that tells dotnet ef to pass everything after it directly to the underlying MSBuild invocation. Without --, the ef CLI tries to interpret /p:RunAnalyzersDuringBuild=false as its own argument and fails. The /p: or -p: is just the MSBuild property flag — both work identically.

Does dotnet ef database update -- /p:RunAnalyzersDuringBuild=false skip running migrations?

No. It only skips running Roslyn analyzers during the internal project build that EF uses to discover your DbContext. The migration logic itself runs normally. Your database schema changes are applied exactly as they would be without the flag.

What if my EF command still fails after adding the flag?

Check whether your project uses <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>, which runs code style analysis separately from RunAnalyzersDuringBuild. You may need to also pass /p:EnforceCodeStyleInBuild=false in the same command:

dotnet ef database update \
  -- /p:RunAnalyzersDuringBuild=false /p:EnforceCodeStyleInBuild=false

Summary

ScenarioRecommended Command
EF migrations add (Windows-style)dotnet ef migrations add Name -- /p:RunAnalyzersDuringBuild=false
EF migrations add (Unix-style)dotnet ef migrations add Name -- -p:RunAnalyzersDuringBuild=false
EF database updatedotnet 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 May 8, 2026

Find vulnerabilities before attackers do

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