The OWASP Walkthroughs
The format is always the same: "A security review found XSS on the candidate search page β explain the vulnerability and fix it." Substitute SQLi or CSRF at will. The rubric wants three beats per vulnerability: what it is (one sentence), where the framework already protects you, and exactly where those protections stop. That third beat is the whole interview β anyone can recite definitions.
XSS: Razor protects you until you opt out
Cross-site scripting = attacker-controlled input rendered as executable script in someone
else's browser. Razor's protection: @model.Name HTML-encodes by default β that's why
naive MVC apps are mostly safe. Where it stops, name all four: Html.Raw() (every use is
a code-review flag β justify or remove), JavaScript contexts (injecting model values into
inline <script> blocks; encoding rules differ β pass data via data-* attributes or a
serialized JSON island instead), href/src attributes (javascript: URLs survive HTML
encoding), and anything a rich-text editor or your Kendo grid renders with encoding disabled
(client-side templates have their own escaping syntax β #: # vs #= # in Kendo). Mention
Content-Security-Policy as defense in depth, not the fix.
SQL injection: EF protects you until you concatenate
SQLi = user input changing the structure of a query instead of being data in it. EF
Core's protection: LINQ queries are always parameterized β there is no string to inject
into. Where it stops: FromSqlRaw/ExecuteSqlRaw with string concatenation or
interpolation into the raw string. The interview-winning nuance: FromSqlInterpolated
(and FromSql in current EF) captures the interpolated values as parameters, so
FromSqlInterpolated($"... WHERE Region = {region}") is safe while
FromSqlRaw("... WHERE Region = '" + region + "'") is a finding. Also flag the un-parameterizable
inputs β dynamic column/table names for sorting must go through an allowlist. Stored
procedures are only safe if they don't build dynamic SQL inside.
CSRF: the browser is the confused deputy
CSRF = a hostile site making the victim's browser submit a state-changing request to your
app, riding the auth cookie the browser attaches automatically. ASP.NET Core's protection:
antiforgery tokens β <form> tag helpers emit them automatically, and
[AutoValidateAntiforgeryToken] (or AddControllersWithViews + filter) validates on unsafe
verbs. Where it stops: AJAX posts (your Kendo grid's updates!) need the token sent in a
header explicitly; GET handlers that mutate state dodge validation entirely β that's a
design bug, not a token bug. SameSite=Lax cookies are the modern second layer; say "belt
and suspenders," not "so tokens are obsolete." Pure-JWT APIs without cookies aren't
CSRF-targets β tokens aren't auto-attached.
Answers that fall flat
- "Razor/EF handles that" with no knowledge of the escape hatches.
- Proposing input sanitization as the primary XSS defense instead of output encoding.
- Not knowing their own grid's AJAX calls bypass the form-tag antiforgery flow.
Practice prompts
- Run all three walkthroughs aloud: definition, framework protection, where it stops, fix.
- Review this line as an interviewer:
FromSqlRaw($"SELECT * FROM Candidates WHERE Name = '{q}'")β everything wrong with it, and two safe rewrites. - Explain how you'd add the antiforgery token to a Kendo grid's inline-edit AJAX requests.