Senior Engineering Interview Handbook / Chapter 143
Security Engineering
A specialty-track chapter that follows an external-collaboration feature from threat model through authorization, controlled launch, detection, incident response, and risk ownership.
Page tools
The sharing feature is ready. The boundary is not.
An interviewer gives you a feature that sounds ordinary:
A B2B product lets customers invite outside collaborators into selected
workspaces. Sharing must stay simple, but enterprise customers require tenant
isolation, immediate revocation, and useful audit evidence. Design the launch.
An ordinary system-design answer can draw an invitation service, a membership table, and an email link. A security answer has to follow what the invitation changes. Before acceptance, a stranger has a token. After acceptance, an identity has a relationship to a tenant. From then on, every file read, search result, preview, export, background job, cache entry, and support action must honor that relationship. When an administrator revokes it, those paths must stop agreeing that access exists.
Security interviews concentrate senior judgment at precisely this kind of boundary. The system still has latency, releases, migrations, support work, and product trade-offs. It also has actors who may misuse valid features, compromised identities that look legitimate, and controls whose failure may remain invisible until someone goes looking.
That argument is more useful than a recital of vulnerability names. It is also harder. It forces you to decide which harm deserves attention first and to keep following the decision after the first plausible control appears.
Begin with harm, not with a catalog
For the collaboration feature, “protect the application” is too vague to design against. The consequential assets are workspace files, membership and invitation state, administrative actions, exports, audit history, support access, and the customer’s confidence that one tenant cannot see another.
The actors are not just anonymous attackers. A workspace owner can invite the wrong address. An external collaborator can enumerate identifiers or export more than expected. A customer account can be compromised. A support operator or service account can have more reach than its job requires. An automated client can turn a low-volume sharing feature into abuse at scale.
Now trace credible paths. An invitation might be forwarded. A guest might retain a session after revocation. An API might check workspace membership but return a file that belongs elsewhere. Search or preview generation might omit the policy enforced by the main read path. A background export worker might run under a broad service identity and trust object identifiers placed on its queue. Audit events might record that an export finished without recording whose authority caused it to begin.
This is threat modeling at interview scale. It is deliberately incomplete. The point is to find the few paths that combine meaningful harm with credible reach, then place controls where those paths cross a boundary. A ten-minute model that changes the design is better than a comprehensive diagram nobody uses.
The first model can fit in six lines:
Asset: tenant files and the capability to share or export them.
Actor: invited user, compromised member, support operator, or service account.
Path: invitation or membership becomes authority on an object-access path.
Control: constrain, verify, observe, revoke, and recover that authority.
Evidence: cross-tenant tests, policy traces, audit events, and a response drill.
Owner: the team making the launch decision owns the documented residual risk.
Each line should become more specific as the interviewer adds facts. “Add encryption” does not answer an authorization defect. “Use zero trust” does not say which identity may perform which action. “Security review passed” does not prove that revocation reaches an export worker.
Follow the grant through every state
The invitation begins as a narrowly scoped, expiring capability. Bind it to the intended tenant, role, and preferably the verified recipient rather than letting possession of a forwarded link silently create broad membership. Rate limit creation and redemption. Record creation, resend, acceptance, expiry, and revocation as security-relevant state changes without putting the token itself into logs.
Acceptance should create an external role distinct from an ordinary employee or full member. “Guest” is not a complete policy, so name the actions: read a shared file, comment, upload, invite, search, preview, export, delete, and administer. A role may permit some and forbid others. Sensitive actions may also depend on tenant policy, resource classification, recent authentication, or an explicit grant on that object.
The decisive check belongs on the object being returned or changed. A route
guard that proves the caller can enter workspace A does not prove that file
F belongs to A, that the caller may export it, or that the grant is still
current. Prefer tenant-scoped lookup and an action-specific policy decision
before data leaves the service boundary.
A practical coding round may reduce the design to something like this:
authorize(principal, "file.read", file, context)
context includes:
current tenant and membership generation
external or internal role
tenant sharing policy
resource classification
authentication strength when relevant
deny before returning content, metadata, preview, search hit, or signed URL
emit a bounded policy decision event without exposing file contents
The syntax is unimportant. The invariants are not:
- the object is resolved inside the tenant boundary rather than checked only after a global lookup;
- read, write, share, export, delete, and administration are distinct actions;
- default behavior is denial when policy context is missing or contradictory;
- caches cannot outlive the authority facts on which their decisions depend;
- background jobs carry the initiating principal and policy context, not just a list of object identifiers;
- tests exercise cross-tenant identifiers, moved objects, revoked users, stale sessions, service identities, search, preview, export, and legacy endpoints.
This is where application-security knowledge becomes useful rather than decorative. Injection asks whether untrusted input can change a command sent to a privileged interpreter. SSRF asks whether a caller can make a trusted service reach a forbidden destination. Cross-site scripting asks whether attacker-controlled content can execute in another browser’s authority. Unsafe upload processing asks whether hostile content can escape its storage or transformation boundary. In each case, name the privileged interpreter, network, browser, or worker first; then choose validation, encoding, parameterization, isolation, egress restriction, or least privilege that fits that boundary.
Service and human identities belong in the same design
The user-facing policy is only one layer. Search indexers, preview workers, notification services, backup jobs, deployment systems, and support tools all touch the collaboration state. A sound answer asks what identity each one uses, which resources it can reach, how its privilege is changed or revoked, and what evidence remains after use.
Prefer workload identity or managed short-lived credentials where the platform supports them. Long-lived copied secrets are difficult to inventory and revoke. Narrow service permissions by action and resource; a preview worker that can read every tenant and write arbitrary production objects has turned a rendering compromise into a platform compromise. Rotation needs to be exercised, not merely promised, and an emergency revocation must have a known effect on running work.
Human access deserves equal attention. Support and incident responders may need customer data, but permanent broad access is a weak default. Time-bounded access, approval for sensitive actions, reason capture, session or action logging, customer-visible evidence where appropriate, periodic review, and a tested break-glass path make the operational need explicit. A break-glass account that nobody can use safely during an incident is theater; one that is used casually is another standing privilege.
Data protection follows the same discipline. Minimize what the feature collects, define retention and deletion, restrict key use, and keep sensitive payloads out of broad telemetry. Encryption protects data on particular paths or at rest; it does not repair an overpowered service, an authorized but inappropriate export, or indefinite retention.
Treat rollout as part of the control
The first release should make uncertainty smaller without transferring it to every customer. Begin with internal or consenting tenants, a narrow external role, export disabled or tightly limited, and a migration that can be reversed. Run cross-tenant and revocation tests against API, search, preview, cached, and asynchronous paths. Exercise invitation expiry, repeated redemption, account recovery, and administrative policy changes.
Audit evidence should answer an investigation question, not simply increase log volume. For a grant or export, capture the acting principal, tenant, resource class or identifier, action, policy result and version, membership generation, relevant request or job identifier, and time. Protect the log from casual modification and limit access to it. Do not copy file contents or raw credentials into the event merely because they might help later.
Detection then begins with behaviors an owner can investigate: unusual invitation volume, repeated denied cross-tenant access, a guest touching many resources quickly, export after a recent grant, new privileged membership, or support access outside its expected workflow. Each detector needs a data source, a triage route, a containment option, and a tuning owner. Paging on every failed login or every export spends response capacity without distinguishing routine use from attack.
Residual risk must be stated plainly. Object authorization will not stop a compromised collaborator from downloading files they are legitimately allowed to read. Step-up authentication, export limits, customer controls, anomaly detection, and visible audit history can reduce that risk, but product leadership still has to decide how much friction the feature can impose for a given customer and data class.
The export that survived revocation
During a limited launch, a customer administrator reports that a revoked guest received an export link. The main application denies the guest’s ordinary file requests, so the surface appears healthy.
Contain the likely exposure before explaining it. Disable or restrict external exports for the affected cohort, revoke the guest’s active sessions and links, preserve the membership, policy, job, storage-access, and audit records, and tell the incident owner what is known, suspected, and still unknown. If the customer needs an immediate answer, give the current scope and next decision time rather than a confident guess.
Now follow the state. The guest requested an export while still a member. The API checked authorization at enqueue time and placed file identifiers on a queue. Minutes later the administrator revoked the membership. The export worker, running with a service identity that could read all tenant objects, trusted the queued identifiers and created a signed download link without rechecking the initiating principal or membership generation.
The system had enforced revocation on synchronous reads but not on deferred authority. Shortening the link lifetime would reduce exposure, but it would not close the mechanism. The repair is to carry the initiating principal, tenant, requested action, and an authority version into the job; scope object lookup to the tenant; reauthorize before each consequential read or at a carefully defined execution boundary; cancel or invalidate jobs when relevant membership changes; and narrow the worker’s service permission so a queue message alone is not unlimited authority.
Verification should reproduce the interleaving: authorize, enqueue, revoke, execute. Add variants for role reduction, tenant-policy change, moved or deleted objects, retries, partial exports, and old queue messages. The audit trail must connect request, job, reauthorization result, output object, and link revocation. Detection can then look for a job rejected after an authority change and for completed work whose recorded authority version is stale.
Recovery also includes impact analysis. Determine which objects entered the export, whether the link was delivered or used, what logs and storage systems received it, which other queued jobs share the defect, and how confidently the team can bound the affected tenants and time window. Involve the organization’s incident, legal, privacy, compliance, support, and communications owners when the facts make their responsibilities relevant. Do not invent notification rules or deadlines in the interview.
The incident earns its place in the design because it exposes a reusable lesson: authorization is a changing fact, and asynchronous work can preserve authority longer than intended unless the system models that change.
What the interview loop can reveal
The same case can support very different rounds without requiring a new framework each time.
In a coding or code-review round, identify the exploitable path before editing syntax. State which principal, object, action, and tenant the decision concerns. Fix the class of bypass across cache, search, export, preview, and worker paths, then add tests that would fail under the old design. For input validation, secret rotation, detection queries, or log parsing, say what must remain true under malformed input, retries, partial failure, and attacker-controlled size.
In system design, draw identities, data flow, and trust boundaries early. Then follow one action from invitation through storage, policy, audit, asynchronous work, revocation, and recovery. The interviewer can change tenancy, scale, latency, insider access, regulatory context, or availability without forcing you to replace the whole design.
In an incident round, resist the urge to name the root cause from the first symptom. Bound harm, contain, preserve evidence, form testable hypotheses, restore safe service, communicate uncertainty, and leave a mechanism-specific guard. Prevention, detection, response, and recovery are one operating system, not separate security specialties.
For a project deep dive, choose a moment when security changed an engineering decision. Explain the unsafe path, competing constraints, evidence, rollout, adoption, failure or challenge, and durable artifact that remained: a policy library, migration tool, abuse-case suite, identity inventory, detector, incident playbook, or exception process. A story that ends with “the review passed” hides whether anyone used the work.
Behavioral questions often put the risk argument under schedule pressure. A product leader wants a broad launch while object-level authorization is still incomplete. Another team resists a new identity library. An executive asks whether an exposure is “serious” before scope is known. Strong answers state the failing path and confidence level, recommend a decision, offer a bounded alternative, identify the risk owner, and say what evidence will reopen the decision.
Make the safer path usable
Security teams rarely control every product schedule. Influence therefore has to produce adoption, not just objection. If teams repeatedly implement tenant checks incorrectly, a reusable policy library, tenant-scoped data-access primitive, migration tooling, example tests, and observable decision trace may reduce more risk than another launch checklist.
A useful escalation is concrete:
I recommend holding broad external sharing because export jobs authorize only
when queued. A guest revoked before execution can still receive tenant data.
For a limited beta, disable export, restrict the cohort, review sharing events
daily, and assign the product owner to the remaining compromised-account risk.
Broad launch can resume when deferred actions reauthorize and the revoke-
before-execute tests pass across every export path.
This gives engineering a failing mechanism and acceptance evidence, product a bounded alternative, and leadership a decision. It neither dramatizes the risk nor hides it behind policy language.
Vulnerability management needs the same judgment. A severity label begins the conversation; it does not determine the work alone. Ask what asset is exposed, whether an attack path is reachable, what privilege or user action it needs, how widely the component is deployed, whether exploitation is active or plausible, which compensating controls exist, how disruptive the repair is, and when verification can happen. Exceptions need an owner, expiry, rationale, compensating control, and a route back into the queue.
Practice by changing the boundary
Use the collaborator feature until your answer stops depending on memorized phrases:
- Give yourself ten minutes to name the assets, actors, data flow, trust boundaries, three consequential abuse paths, controls, evidence, and residual-risk owner.
- Review one file-read endpoint. Trace tenant scoping through lookup, cache, preview, search, export, and background work; write the cross-tenant and revoke-before-use tests.
- Allow public invitation links. Decide which risk the convenience creates, how expiry and redemption work, what abuse is observable, and when the link must be disabled.
- Require immediate revocation for ten million active sessions. Separate the policy promise from cache, token, and distribution mechanics, then define what “immediate” can honestly mean and how you will measure it.
- Add a support workflow. Specify temporary access, approval, evidence, customer visibility, emergency use, and review without inventing authority the operator does not need.
- Run the stale export incident aloud. Keep facts, hypotheses, containment, impact, recovery, communication, and mechanism change distinct.
- Explain the launch decision to an engineer, a product lead, and an executive. Keep the facts constant while changing the level of detail.
Then rehearse one real project of your own. Remove product names and see whether the risk argument still has a precise asset, reachable path, adopted control, evidence, decision owner, and lesson. If it does not, more security terminology will not rescue the story.
Rehearse the decision, not the vocabulary
When a prompt sprawls, speak in the order the decision needs. Name the harm and the asset. Identify credible actors and entry points, then draw the data flow and trust boundary. Choose the highest-consequence reachable path and put a preventive or limiting control on that path. Add detection, containment, and recovery; say what will verify them before launch and during operation. Finish with the residual risk, its decision owner, and the evidence that will cause the team to revisit the choice.
You are ready when adding an adversary makes your engineering answer more exact rather than more theatrical. You can show where authority begins, where it travels, where it must end, how failure becomes visible, and who decides what remains. That is the security specialty: ordinary engineering made accountable under hostile and uncertain conditions.
Related links
Continue reading
Full table of contents