JetDatabaseWriter

Static Analysis Modernization TODOs

Status: initial pass shipped (2026-05-27); remaining items intentionally deferred Date: 2026-05-27 (status refreshed 2026-06-30)

This note tracks a performance-first path for keeping static analysis useful without making clean builds slower. The goal is not to add analyzers for their own sake; the goal is a strict, maintainable, fast build where most diagnostics point at real issues and every analyzer package either pays for itself locally or moves to a slower CI/security lane.

Completion status (2026-06-30): the initial pass shipped. Roslynator.Refactorings (§1) and SecurityCodeScan.VS2019 (§2) were removed from local builds (see Current Posture), while StyleCop.Analyzers (§3), Roslynator.Analyzers, and BannedApiAnalyzers were deliberately retained (the last extended with security bans). The remaining unchecked - [ ] items — chiefly the SDK AnalysisLevel / code-style tuning (§4) and the optional later Meziantou.Analyzer trial — are intentionally deferred future trials, not forgotten work, and stay closed unless a new build-time or coverage concern reopens them.

Current Posture

Security coverage clarification (2026-10-07): enabled rules and a warning-free build do not establish hostile-file safety. The SDK’s CA3001 and CA3003 track recognized HTTP-request sources with bounded interprocedural analysis; they do not prove that database bytes, catalog paths, or cross-assembly flows are safe. Banned APIs enforce symbol policy, not allocation budgets, traversal termination, or authorization of opened files. The rule matrix below records the removal decision, not equivalent taint coverage. Current evidence and remaining gaps are in the vulnerability review.

The repo is already using SDK analyzers as the center of gravity. The remaining questions are about local-build cost, analyzer scope, which older broad packages should stay local, and which checks belong in a slower CI/CD lane.

Measurement Notes

Analyzer timing is available from Roslyn when the compiler actually runs. Use a forced rebuild for measurement; up-to-date builds can list analyzer inputs while skipping the compiler pass.

Useful one-project timing command:

dotnet build <project.csproj> --configuration Release --no-restore -t:Rebuild /p:ReportAnalyzer=true /p:TreatWarningsAsErrors=false -v:detailed

Useful solution smoke command:

dotnet build JetDatabaseWriter.slnx --configuration Release --no-restore -m

Notes:

Measured Baseline

Clean Solution Baseline

After fixing the unrelated Release test analyzer failures, a 2026-05-27 forced strict Release rebuild of JetDatabaseWriter.slnx used SDK 10.0.300 and this command:

dotnet build JetDatabaseWriter.slnx --configuration Release --no-restore -m -t:Rebuild /p:ReportAnalyzer=true -bl:obj/AnalyzerTiming/release-sln-rebuild-20260527-133323.binlog -v:detailed

Result: exit code 0, outer stopwatch 00:00:18.8843371, MSBuild reported Time Elapsed 00:00:18.55, 0 Warning(s), and 0 Error(s). Detailed text log: release-sln-rebuild-20260527-133323.log. Binary log: release-sln-rebuild-20260527-133323.binlog.

Analyzer totals by compiler invocation:

Compiler invocation Total analyzer execution time
JetDatabaseWriter net10.0 20.485s
JetDatabaseWriter netstandard2.1 18.199s
JetDatabaseWriter.Scaffold net10.0 0.286s
JetDatabaseWriter.Benchmarks net10.0 1.003s
JetDatabaseWriter.FormatProbe net10.0 15.438s
JetDatabaseWriter.Tests net10.0 21.727s

Library Project

A 2026-05-27 forced Release rebuild of JetDatabaseWriter.csproj with -p:ReportAnalyzer=true showed these analyzer execution-time groups for the two target frameworks:

Analyzer group netstandard2.1 net10.0 Initial read
SDK .NET analyzers 13.935s 11.156s Keep, but latest-all is expensive and should be justified.
SecurityCodeScan.VS2019 9.170s 8.749s High-priority local-build removal or CI-lane candidate.
SDK C# code-style analyzers 7.022s 6.268s Large cost from EnforceCodeStyleInBuild; consider Debug/local relief.
StyleCop.Analyzers 4.879s 6.055s High-priority retirement candidate.
Roslynator.Analyzers 1.116s 1.081s Relatively cheap; tune before removing.
Microsoft.CodeAnalysis.BannedApiAnalyzers less than 0.001s less than 0.001s Keep; nearly free and uniquely local.

Test Project

A 2026-05-27 forced Release rebuild of JetDatabaseWriter.Tests.csproj with TreatWarningsAsErrors=false produced about 19.356s of concurrent analyzer execution time.

Analyzer group Time Initial read
SDK .NET analyzers 6.651s Largest group; CA2000 dominated at about 3.159s.
SecurityCodeScan.VS2019 5.014s Taint and crypto analysis dominate; web-only rules were near zero but irrelevant.
StyleCop.Analyzers 2.790s Broad formatting/layout/documentation pass over many test files.
SDK C# .NET analyzers 2.168s CA1508 dominated at about 1.782s.
xunit.analyzers 1.003s Worth keeping; diagnostics are test-framework-specific and high signal.
Roslynator.Analyzers 0.279s Cheap in tests.
Microsoft.CodeAnalysis.BannedApiAnalyzers less than 0.001s Keep.

The initial strict Release solution baseline attempt on this date failed on test-project analyzer diagnostics unrelated to this note, including SA1216, SA1204, xUnit1026, CA1062, CA1859, and SA1118. Those were fixed before the clean solution baseline above was captured.

FormatProbe Spot Check

A warmed forced Release rebuild of JetDatabaseWriter.FormatProbe.csproj showed the same rough ranking at smaller scale: SecurityCodeScan.VS2019 about 1.224s, SDK C# .NET analyzers about 1.161s with CA1508 about 1.056s, StyleCop.Analyzers about 0.560s, Roslynator.Analyzers about 0.340s, and Microsoft.CodeAnalysis.BannedApiAnalyzers effectively free.

Consolidation Decisions

1. Remove Roslynator.Refactorings From Build Package References First

Verdict: lowest-risk cleanup.

Why:

TODOs:

Completed on 2026-05-27: removed the global package reference and the unused central package version pin. dotnet restore JetDatabaseWriter.slnx removed only direct Roslynator.Refactorings lock-file entries, and dotnet build JetDatabaseWriter.slnx --configuration Release --no-restore -m passed in 50.8s.

2. Remove or Move SecurityCodeScan.VS2019 Out of Local Builds

Verdict: removed from local builds. Bring it back only through an explicit slower CI/security-lane decision.

Why:

Rule-level coverage review from 2026-05-27:

SCS rule What it detects Coverage or replacement read Local recommendation
SCS0001 Command injection through process execution. Existing bans block ambiguous Process.Start overloads, ProcessStartInfo(string, string), and the ProcessStartInfo.Arguments shell-style string. SDK security analyzers cover process-command injection patterns. Future Meziantou MA0161-MA0163 can require safer ProcessStartInfo/UseShellExecute shape, but not full taint replacement. Keep SCS out locally; keep the process bans and add curated Meziantou process rules later.
SCS0002 SQL injection. SDK security analyzers cover SQL-injection patterns. BannedApi cannot model taint, but this pure file-format library should not acquire server-database client surfaces. Keep SCS out locally; keep SDK coverage and project bans on SQL/ODBC/OleDb connection/command APIs unless a deliberate feature changes that policy.
SCS0003 XPath injection. SDK security analyzers cover XPath-injection patterns. BannedApi could ban XPath APIs, but cannot distinguish safe literal queries from unsafe dynamic query construction. Rely on SDK coverage; only add bans if XPath APIs are never intended in this codebase.
SCS0004 Disabled certificate validation. SDK security analyzers cover common certificate-validation bypasses. Future Meziantou MA0039 also flags custom certificate validation. BannedApi now bans TLS-validation callback APIs because this library should not own network trust policy. Use SDK plus project bans; no SCS local build need.
SCS0005 Weak random number generation. SDK CA5394 already covers insecure randomness. BannedApi could ban Random, but this repo has legitimate fuzz/test use. Keep SDK coverage and scoped suppressions for non-security randomness.
SCS0006 Weak hashing such as MD5 or SHA-1. SDK crypto rules plus existing bans for MD5 and SHA1 cover this. Current suppressions are for spec-required legacy formats. Covered locally without SCS.
SCS0007 XML external entity processing. SDK XML security analyzers cover unsafe parser configuration. BannedApi cannot express “configured safely,” but it can ban precise escape hatches such as XmlUrlResolver and DtdProcessing.Parse. Use SDK coverage plus those precise XML escape-hatch bans; avoid broad file/XML API bans.
SCS0008 Cookie without Secure. Web-only. BannedApi can only ban cookie APIs wholesale. The local project policy now bans System.Web.HttpCookie and ASP.NET controller base types to keep web surface out of the library. No SCS local-build need; host applications own cookie policy.
SCS0009 Cookie without HttpOnly. Web-only. Same replacement posture as SCS0008. No SCS local-build need; host applications own cookie policy.
SCS0010 Weak cipher algorithms such as DES/3DES. SDK crypto rules plus existing bans for DES, RC2, Rijndael, and TripleDES cover this. Covered locally without SCS.
SCS0011 Unsafe XSLT settings. SDK XML/XSLT security coverage is the better fit for taint/configuration. BannedApi now bans XslCompiledTransform, XsltSettings.EnableScript, and XsltSettings.TrustedXslt because XSLT execution is outside this library’s scope. Covered locally without SCS unless a deliberate XSLT feature is introduced.
SCS0012 ASP.NET controller action missing authorization annotations. ASP.NET-specific. BannedApi now blocks ASP.NET controller base types as a project-scope guard, not an authorization analyzer replacement. No fit for this library; host applications own authorization policy.
SCS0013 Weak or unauthenticated cipher modes. SDK crypto rules already flag the relevant patterns; BannedApi now bans CipherMode.CBC and CipherMode.ECB so any manual mode assignment must carry an explicit RS0030 compatibility suppression. Static EncryptCbc/DecryptCbc helper use remains covered by SDK crypto rules and existing compatibility suppressions. Covered locally without SCS for enum mode selection; keep intentional Office/Jet suppressions narrow.
SCS0015 Hardcoded password passed to known password APIs. Not well covered by BannedApi unless banning specific password setter APIs. Meziantou does not replace this. Secret scanning or CodeQL/Sonar-style scanning is a better slower-lane fit. Low local value; use slower-lane secret scanning if desired.
SCS0016 Missing anti-forgery token on ASP.NET POST actions. ASP.NET-specific. No fit for this library.
SCS0017 ASP.NET request validation disabled by attribute. ASP.NET-specific. No fit for this library.
SCS0018 Path traversal. SDK CA3003 recognizes HTTP-request taint; it does not establish safety for paths read from database catalog metadata. BannedApi cannot encode path authorization or filesystem identity. Meziantou does not replace this. Linked execution consumes only streams explicitly authorized by the host resolver; catalog paths are untrusted hints and never opened by the library. Retain capability, alias, refusal and ownership regressions; path spelling and a clean analyzer run do not authorize an actual resource.
SCS0019 ASP.NET output cache conflicts with authorization. ASP.NET MVC-specific. No fit for this library.
SCS0021 validateRequest=false in Web.config. ASP.NET/Web.config-specific. No fit for this library.
SCS0022 ASP.NET event validation disabled. ASP.NET/Web.config-specific. No fit for this library.
SCS0023 View state not encrypted. ASP.NET WebForms-specific. No fit for this library.
SCS0024 View state MAC disabled. ASP.NET WebForms-specific. No fit for this library.
SCS0026 LDAP distinguished-name injection. SDK security analyzers cover LDAP-injection patterns. BannedApi now bans DirectoryEntry and DirectorySearcher because LDAP is outside this file-format library’s scope. Meziantou does not replace this. Covered locally as a project-scope ban; revisit only if LDAP support is deliberately introduced.
SCS0027 Open redirect. Web-specific; SDK security analyzers cover common redirect vulnerabilities. BannedApi and Meziantou are poor replacements. No fit for this library.
SCS0028 Insecure deserialization of untrusted data. SDK deserialization rules plus BannedApi cover the highest-value local policy. The ban list now includes BinaryFormatter, SoapFormatter, NetDataContractSerializer, WebForms serializers, JavaScriptSerializer, and dangerous Newtonsoft TypeNameHandling enum values. Meziantou is not a replacement. Covered locally without SCS for known unsafe serializers; use slower-lane scanning for taint/source-flow questions if desired.
SCS0029 Cross-site scripting. Web-output-specific; SDK security analyzers cover common XSS classes. BannedApi and Meziantou are not useful replacements. No fit for this library.
SCS0030 Request validation mode protects only pages, not all requests. ASP.NET/Web.config-specific. No fit for this library.
SCS0031 LDAP filter injection. Same posture as SCS0026: SDK coverage plus project bans on LDAP entry/search APIs. Meziantou does not replace this. Covered locally as a project-scope ban; revisit only if LDAP support is deliberately introduced.
SCS0032 ASP.NET Identity password minimum length too small. ASP.NET Identity-specific. No fit for this library.
SCS0033 ASP.NET Identity password complexity too weak. ASP.NET Identity-specific. No fit for this library.
SCS0034 ASP.NET Identity password required length not set. ASP.NET Identity-specific. No fit for this library.

Actionable interpretation:

Removal experiment completed on 2026-05-27 after the Roslynator.Refactorings package removal. The removed-state command was:

dotnet build JetDatabaseWriter.slnx --configuration Release --no-restore -m -t:Rebuild /p:ReportAnalyzer=true -bl:<binlog> -v:detailed

Control state with SecurityCodeScan.VS2019 still present after Roslynator.Refactorings removal:

Run Text log MSBuild elapsed Warnings Errors
1 securitycodescan-control-run1-20260527-144507.log 00:00:56.82 0 0
2 securitycodescan-control-run2-20260527-144605.log 00:00:37.11 0 0
3 securitycodescan-control-run3-20260527-144644.log 00:00:29.88 0 0

Removed state:

Run Text log Binary log Outer stopwatch MSBuild elapsed Warnings Errors
1 securitycodescan-removed-run1-20260527-152229.log securitycodescan-removed-run1-20260527-152229.binlog 00:00:14.7702552 00:00:14.32 0 0
2 securitycodescan-removed-run2-20260527-152244.log securitycodescan-removed-run2-20260527-152244.binlog 00:00:15.8959698 00:00:15.46 0 0
3 securitycodescan-removed-run3-20260527-152300.log securitycodescan-removed-run3-20260527-152300.binlog 00:00:16.6763203 00:00:16.23 0 0

Result: the removed-state MSBuild median was 15.46s, compared with the control median of 37.11s. That is a median improvement of 21.65s, or about 58%, with no warnings or errors. The removed-state outer stopwatch median was 15.90s; the earlier control outer-stopwatch median was about 38.00s.

The run 1 removed-state analyzer totals by compiler invocation were:

Compiler invocation Total analyzer execution time
JetDatabaseWriter net10.0 10.881s
JetDatabaseWriter netstandard2.1 11.203s
JetDatabaseWriter.Scaffold net10.0 0.133s
JetDatabaseWriter.Benchmarks net10.0 0.495s
JetDatabaseWriter.FormatProbe net10.0 13.767s
JetDatabaseWriter.Tests net10.0 15.627s

Decision: keep SecurityCodeScan.VS2019 out of local builds. The measured speedup is large, the local warning count stayed at zero, and the rule-level coverage review above shows that the useful local concerns are already covered or better handled by SDK analyzers, focused BannedApi policy, and the later curated Meziantou trial. Broad taint/security scanning remains a separate slower-lane decision.

Replacement path:

Post-SCS local hardening completed on 2026-05-27:

3. Keep StyleCop.Analyzers for Now

Verdict: keep StyleCop in strict local builds for now. Defer any retirement, replacement, or CI/CD-lane move until the broader analyzer-lane plan is revisited.

Why:

Deferred path:

Completed on 2026-05-27 and finalized on 2026-05-30: expanded .editorconfig from the StyleCop-oriented Rehan Saeed template, retained its MIT notice at the bottom, added JetDatabaseWriter-specific overrides for mixed existing style, moved the global analyzer/style NoWarn policy into explicit dotnet_diagnostic entries, and kept only NU1605 in Directory.Build.props. The 2026-05-30 strict editorconfig pass kept the intended “only implicit when apparent” type style, cleaned remaining Roslyn style drift, and validated with:

dotnet format style JetDatabaseWriter.slnx --verify-no-changes --no-restore --verbosity minimal
dotnet build JetDatabaseWriter.slnx --configuration Release --no-restore -m
dotnet test --project tests/JetDatabaseWriter.Tests --filter-not-trait Category=Fuzz

These commands record historical validation. For future work, local builds and targeted tests are allowed, but the full-suite test command above is CI-only; excluding fuzz tests does not make it a targeted run. All benchmark runs are also CI-only. See AGENTS.md.

4. Tune SDK Code Style and AnalysisLevel latest-all Last

Verdict: biggest potential speed lever, but highest policy risk.

Why:

TODOs:

5. Keep and Extend Microsoft.CodeAnalysis.BannedApiAnalyzers

Verdict: keep.

Why:

TODOs:

6. Keep xunit.analyzers

Verdict: keep.

Why:

TODOs:

7. Keep Roslynator.Analyzers Unless Its Diagnostics Stop Paying Rent

Verdict: keep for now, tune later.

Why:

TODOs:

Candidate Analyzer Ecosystem Triage

The awesome-analyzers list is useful as a discovery index, but most packages should not be added to local builds under a speed-first goal. Treat new analyzer packages as replacement experiments, CI-only experiments, or technology-specific tools that must match code the repo actually uses.

Reasonable Replacement or CI Trials

Candidate Fit for this repo Local-build default
Meziantou.Analyzer Broad, active, editorconfig-friendly; useful rules around culture, async disposal, regex, process start, stream reads, string comparison, and cancellation. Do not add by default; trial only after removing heavier packages.
SonarAnalyzer.CSharp Active broad bug/security/code-smell analyzer; possible slower-lane replacement for some SecurityCodeScan value. Prefer CI or scheduled trial first.
CodeQL / SonarCloud / Puma Scan Better suited for security/code-smell sweeps than every local compile. CI or scheduled lane, not local build.
IDisposableAnalyzers Relevant because streams/readers/writers and ownership boundaries matter. Trial only if resource-ownership bugs justify measured cost or if it replaces other ownership checks.
AsyncFixer Small async misuse analyzer; overlaps with SDK, Roslynator, xUnit, and banned APIs. Trial only after async gaps are identified.
ErrorProne.NET, Gu.Analyzers, SharpSource General correctness analyzers that may catch useful bugs. CI-only or isolated branch trial; assume overlap/noise until measured.
Exceptionator / SmartAnalyzers.ExceptionAnalyzer Exception-handling focus could be useful, but overlaps with SDK and existing policy. Not a default local-build addition.
Microsoft.CodeAnalysis.PublicApiAnalyzers Relevant to a reusable library if API compatibility baselines become a release policy. Separate API-governance decision, not a build-speed optimization.
.NET project file analyzers Could catch project-file issues, but does not address C# analyzer cost. Optional CI/tooling check, not part of every C# compilation.

Poor Fits or Irrelevant Technologies

Do not add local analyzers for technologies this repo does not use:

Meziantou Trial Rules

Meziantou.Analyzer is the best-looking general-purpose addition, but it is not a drop-in replacement for any existing package. It partially overlaps SDK, Roslynator, StyleCop, and security-adjacent rules without fully replacing them.

TODOs:

Warning and Message Cost

Hypothesis: builds with many diagnostics can be slower than diagnostically clean builds. This is plausible, but the mechanism matters.

Likely true:

Easy to overestimate:

Practical model:

Suggested Order of Work

Experiment Checklist

For each analyzer package add/remove/tune experiment: