TL;DR: Start with context (what the code does, who calls it, what it protects), then trace untrusted sources to dangerous sinks and check what stands between them: authentication, authorization on the specific object, validation, encoding, parameterisation. Look first at entry points, authorization logic, data access, and calls to interpreters, file systems, network fetchers and deserializers. In AI features, treat model output and tool arguments as untrusted sources. Report findings with a concrete exploit path, impact and fix.
How to approach it
Describe a method, not a checklist recitation: scope, map, trace, verify, report. Say what you look at first and why. Interviewers often hand you code afterwards, so show the habit of tracing data flow.
A strong answer
Context
what it protects
Sources
requests, files, model output
Between them
authn, authz, validation
Sinks
SQL, shell, HTML, files
Findings
impact and fix
1. Context first (minutes, not hours). What does this change do, who can reach it (anonymous, users, internal services, the model), and what does it touch (money, personal data, credentials, other tenants)? Read the design or ticket. This tells you which bugs would matter.
2. Map entry points and trust boundaries. HTTP routes, message consumers, scheduled jobs, webhook receivers, tool handlers called by an LLM. Note which authenticate and how.
3. Trace sources to sinks.
| Sources (untrusted) | Sinks (dangerous) | Check that should sit between |
|---|---|---|
| Request params, headers, bodies | SQL / query builders | Parameterisation |
| Uploaded files, archives | Shell, subprocess | Argument arrays, allowlists |
| Webhooks, third-party API responses | HTML rendering | Contextual encoding, sanitisation |
| Model output, tool-call arguments | File paths | Resolve and confine to a root |
| Retrieved documents | Outbound HTTP | Destination validation |
| Environment from other tenants | Deserializers | Data-only formats |
| Data access by ID | Object-level authorization |
4. What I look at first.
- Authorization on data access. Every query or fetch by ID: is the object checked against the caller and tenant? This is the most common serious bug.
- Authentication boundaries. New routes default to authenticated? Webhooks verify signatures with constant-time comparison?
- Interpreter and system calls. Any string-built query, shell call, template compilation,
eval, or deserialization of external data. - Secrets and crypto. Hard-coded keys, disabled TLS verification, custom crypto, tokens in logs.
- AI-specific sinks. Model output rendered as HTML, passed to tools, used in paths or queries; tool handlers that trust model-supplied IDs.
5. Verify, then report. Confirm exploitability with a quick test where possible. Each finding states the path (source, sink, missing check), the impact in terms of an asset, a severity, and a concrete fix with code. Separate must-fix from defence-in-depth suggestions.
Scale. Automate what can be automated (SAST rules for known sinks, secret scanning, dependency checks) and spend human time on authorization logic and business rules, which tools miss.
What interviewers probe next
- "You have 30 minutes for a 2,000-line change. What do you do?" Context, then authorization and data access, then interpreter calls; note what you did not review.
- "How do you review code written by an AI assistant?" Same method, with extra attention to plausible-looking but unchecked authorization, invented package names, and disabled validation.
- "How do you keep developers receptive to findings?" Clear exploit paths, fixes with code, and severity they can trust.
What if?
What if · interview follow-ups
Hold your answer as the constraints change
You have one day to security-review a 20,000-line service before launch, including a new AI summarisation feature.
Start here
Where do you start?
What would an attacker want from this service?
With context: what the service does, who calls it, what data and actions it protects and its trust boundaries. Without that, you cannot tell which code paths matter.
Carry it forwardContext first, then code.
Weak answerReading files in alphabetical order.
Constraint changes
How do you trace risk through the code?
Where does attacker-controlled data go?
Trace untrusted sources to dangerous sinks and check what stands between them: authentication, authorisation on the specific object, validation, encoding and parameterisation. Sources include requests, files, queues and model output.
Carry it forwardTrace sources to sinks.
Weak answerSearching only for known bad function names.
Constraint changes
Which areas get attention first?
Where do serious bugs usually live?
Entry points, authorisation logic, data access, and calls to interpreters, file systems, network fetchers and deserialisers. Authorisation bugs are the most common serious flaws and need reading, since scanners rarely find them.
Carry it forwardPrioritise entry points, authorisation and sinks.
Weak answerSpending the day on style issues.
Constraint changes
What about the AI feature?
What does the code do with model output?
Treat model output and tool arguments as untrusted sources. Check where output is rendered or executed, whether retrieval respects permissions and whether tools enforce authority in code.
Carry it forwardModel output is an untrusted source.
Weak answerSkipping AI code as 'just prompts'.
Constraint changes
How do you use tools and report?
What should the report say about coverage?
Run SAST and dependency scanning to cover breadth while you read the highest-risk paths. Report findings with severity, evidence and fixes, and state clearly what you did not review.
Carry it forwardTools for breadth, reading for depth, honest scope.
Weak answerImplying full coverage.
Now defend it
How would you structure the day?
Learn context and trust boundaries; run SAST and dependency scans; read entry points, authorisation, data access and sinks, tracing untrusted sources including model output; review AI rendering, retrieval and tool authority; and report findings with severity, evidence and fixes plus what was not covered.
How it's scored
Weak: Reads line by line for "bad functions" with no prioritisation.
Hire: Describes source-to-sink tracing, prioritises authorization and interpreter calls, and reports with impact and fixes.
Strong Hire: Starts from context and trust boundaries, includes AI-specific sources and sinks, balances automation with manual review, and states review scope honestly.
Common mistakes
- Spending the review on style or minor issues while missing authorization.
- Treating model output or tool arguments as trusted.
- Reporting findings without an exploit path or fix.