Code review can catch security mistakes when reviewers know which boundaries a change touches. A generic instruction to “check security” is too vague. In multi-tenant SaaS, a useful review asks where tenant context comes from, who may perform the operation, what data crosses a boundary, and how failure is handled. The aim is to find meaningful risks without making every small change wait for a large security ceremony.
Start with the data path
Trace input from the browser or external service through API validation, business operation, database or storage, and response. Identify the tenant and actor at each step. A new query by item ID alone may bypass a tenant filter; a new cache entry may omit locale or permission scope. Look at derived systems such as search, exports, files, and queued jobs, because they often hold copies of data outside the main route. Ask whether any response field exposes more than the client needs. A short data-path sketch in the review description can make hidden dependencies visible.
Check authorization on the server
A UI condition is not protection. Confirm that the API or business operation checks the caller's permission for the specific resource and state transition. Test a wrong-tenant item and a valid user with insufficient role. If a support tool has elevated access, review its scope and audit trail. Avoid role checks scattered in several controllers; shared rules should have one implementation. For a new action, ask whether an old session or revoked membership still permits it. The reviewer should be able to point to the line or operation that owns the decision.
Inspect secrets and external boundaries
Look for credentials in source, logs, URLs, build output, or browser bundles. An integration should use least-privilege keys and validate callbacks or webhooks. Review timeouts, retries, and idempotency for actions that can be repeated. A file upload needs size, type, and ownership rules; a download needs authorization independent of the page that links to it. Treat third-party response bodies as untrusted input. These checks are particularly important when a small feature adds a new provider, because the surface area expands even if the UI diff is tiny.
Review failure behavior
What happens if a database write succeeds and cache invalidation fails? Can a job be retried without duplicating a payment or email? Does an error reveal private record names or internal stack traces? Security and reliability often meet at these edges. The platform's centralized error helpers and response layer should own status and localized keys. Logs can carry diagnostic detail but should omit raw tokens and sensitive payloads. Ask whether an operator can detect and recover from a partial failure, not only whether the happy path passes.
Use focused evidence
Request tests for the high-risk boundary: a cross-tenant read, duplicate webhook, expired invitation, or unauthorized file download. Do not demand implementation-mirroring tests for every helper. Run composed-product checks when a change crosses repositories or processes. If a reviewer finds the same missing tenant filter repeatedly, improve the shared data access abstraction and policy checks rather than relying on human memory. Automation can catch mechanical import and response conventions, leaving review time for business meaning.
Keep comments useful
A review comment should explain the risk and suggest a concrete safer path. Distinguish a blocking exposure from an optional improvement. Be open to evidence that a control already exists in a broader layer. Record significant security decisions so future contributors understand the boundary. For SMB teams, a concise review focused on actual data and privilege flows can prevent serious customer harm without slowing ordinary delivery unnecessarily. When a new risk is found, add it to a short reviewer checklist only if it is likely to recur. The checklist should remain small enough to use and point to shared platform controls where those controls exist.