Some checks cannot be expressed with the local DSL predicates, because they need
data-flow across the whole program: SQL injection, XML external-entity (XXE)
processing, and other taint-based security findings. Rather than reinvent that
analysis, CodeCharter delegates it to the maintained, MIT-licensed
Microsoft.CodeAnalysis.NetAnalyzers security analyzers
and surfaces each finding as a typed fact in the Diagnostics collection — the
same typed surface every other rule uses.
The Diagnostics collection
Diagnostics is a top-level collection (like Types or Methods). Each element
is a DiagnosticModel with these members:
| Member | Type | Meaning |
|---|---|---|
Rule |
string | The analyzer rule id, e.g. CA2100 or CA5351. |
Category |
string | The analyzer category, e.g. Security. |
Message |
string | The human-readable diagnostic message. |
OffendingText |
string | The source text the diagnostic points at (may be null). |
SourceFile |
string | Absolute path to the file the diagnostic was reported in. |
Line |
int | 1-based source line. |
Column |
int | 1-based source column. |
Filter by a named alias, not a CA… string
Do not compare d.Rule == "CA2100". Filter by a readable alias member.
Aliases document intent and keep a rule working if the underlying id set changes:
| Alias | Underlying ids | Flags |
|---|---|---|
SqlInjection |
CA2100, CA3001 |
SQL built from untrusted / non-constant text |
WeakHashing |
CA5350, CA5351 |
MD5 / SHA1 / DES and other broken algorithms |
XmlExternalEntity |
CA3075 |
Unsafe XML external-entity (XXE) processing |
DisabledCertificateValidation |
CA5359 |
Certificate validation turned off |
DeprecatedSecurityProtocol |
CA5364 |
SSL3 / TLS 1.0 and other deprecated protocols |
@name "SQL injection"
@severity error
@category "Security"
Diagnostics.Where(d => d.SqlInjection)
Referencing an alias that does not exist (a typo like d.SqlInjektion) is a
clear authoring error, not a silently-false match.
Local checks stay in the typed members
Weak crypto is available both as an alias here (WeakHashing) and, for the parts
that are a purely local decision, through the ordinary typed members. The boundary
is simple: a check you can make by looking at a single expression belongs in the
local members (m.Invocations, m.MemberAccesses, …); a check that needs the
whole program — where does this string come from, does it reach a SQL sink —
belongs in Diagnostics.
Two things to know
- Opt-in. The analyzers only run when a rule reads the
Diagnosticscollection. A run whose rules never touch it pays nothing for analyzer execution. - Full-solution only. These findings populate during a real solution analysis
with complete references. The in-memory spec harness (used by
test) has a thin reference set, so taint-heavy analyzers cannot resolve there. A diagnostic that cannot run for lack of references is logged, not silently dropped.
Source and licence
The diagnostics come exclusively from Microsoft.CodeAnalysis.NetAnalyzers, which
is MIT-licensed. The LGPL-3.0 SecurityCodeScan analyzers are deliberately not
bundled. Analysis runs locally, in-process — no code leaves your machine, matching
CodeCharter's overall privacy posture.
What's next
- Selectors — the collections every rule starts from
- Predicate catalog — the full member surface