Security Engineering
The discipline of finding where a system trusts something it shouldn't and closing that gap before an attacker finds it first - spanning secure code, threat modeling, and the response when prevention fails anyway.
Assumes you know: Comfort reading and writing code in at least one language, A working understanding of how a web request travels from client to server, Basic familiarity with databases and how a query is built
Overview
What this area actually covers
Security engineering is the work of finding the places a system trusts something it should not, and closing that gap before someone hostile finds it instead. That sounds abstract until you see the shape it takes in practice: a login form that trusts whatever string arrives in the username field enough to build a database query out of it directly, an API endpoint that trusts a caller's claimed identity enough to skip checking whether that identity actually owns the resource being requested, a build pipeline that trusts a dependency's published version number enough to never ask whether a newer version fixed a known flaw. Every one of those is a place where a design decision assumed good faith, and security engineering is the discipline of noticing the assumption, deciding whether it is safe to keep, and building the check that makes it safe if it is not.
The area covers three things that are related but genuinely distinct, and interviews test them separately. The first is application security: writing code and designing systems so that the common ways attackers get in - injection, broken access control, weak cryptography, misconfiguration - are closed by default rather than by developer vigilance. The second is threat modeling: reasoning systematically, before or alongside building something, about who might attack it, what they would want, and where the design currently lets them get it. The third is incident response: what happens when the first two were imperfect, which they always eventually are, and something got through anyway. A security engineer's day touches some mixture of all three, and a security interview typically probes all three separately because a strong answer in one does not predict a strong answer in another - plenty of engineers who write careful, injection-free code have never sat in a room reasoning about an attacker's incentives, and plenty of people fluent in STRIDE have never had to explain to a panicking executive, at two in the morning, what is actually known about a breach twenty minutes after it was discovered.
What gets wrongly bundled into this area, and needs pulling apart explicitly. Compliance and audit work - proving to a regulator or a customer that controls exist - overlaps with security engineering but is a different job with different incentives; a compliance answer is "we have a documented policy," a security engineering answer is "here is the mechanism that makes the bad thing structurally hard to do." Network security and traditional perimeter administration - firewalls, VPNs, network segmentation - is a real adjacent specialism, but a growing share of the field, driven by cloud adoption, no longer treats the network boundary as the primary control at all. And "security" as a business or governance function - risk registers, insurance, vendor questionnaires - is real work that shares vocabulary with this area but is not engineering in the sense this site means it: nothing there requires reading or writing code, and nothing here requires it either, but the two draw on very different skills day to day.
The two areas underneath
This section is divided into two subsections, and the division tracks a genuine difference in when the work happens and what it produces. Application security is mostly about a system that already exists, or is actively being built: finding and closing specific vulnerability classes in running code. Threat modeling is mostly about a system before it exists, or before a specific change lands: reasoning about what could go wrong structurally, so the application-security work that follows has fewer holes to find. Neither replaces the other - a perfectly threat-modelled design still needs the code that implements it to actually avoid injection flaws, and the most careful secure-coding practice cannot compensate for a boundary nobody thought to draw.
| Subsection | What it is for |
|---|---|
| Application Security | OWASP Top 10, SAST/DAST/SCA tooling, and secure coding practices for code that exists or is being written |
| Threat Modeling | STRIDE, attack trees, and reasoning about trust boundaries before or alongside a design |
Application Security is where most of the discipline's day-to-day work lives, and where most interview questions land first, because it is the part with the most concrete, checkable content. It covers the OWASP Top 10 by mechanism rather than by name - not just that injection exists but why a parameterised query closes it structurally rather than merely making it harder; the trade-offs between static analysis, dynamic analysis and dependency scanning, and specifically what each one cannot see no matter how well it is run; and the harder organisational question of what to do when a scanner hands you thousands of findings and a roadmap has no room for all of them. Inside this subsection you will find questions that assume you can read a vulnerable code sample and say precisely why it is vulnerable, not just recognise the vulnerability's name.
Threat Modeling is where the discipline gets structured rather than reactive, and it is the subsection that most separates a senior security engineer from a junior one in an interview, because it rewards a process rather than a memorised list. It covers STRIDE applied to real, specific boundaries rather than recited as an acronym; the complementary role of attack trees, which start from an attacker's goal rather than a category of harm; and the organisational reality that a threat model is only useful if it stays current as the system changes and if its findings actually make it onto a roadmap competing with feature work. This is also where the discipline's least code-heavy material lives - a strong threat-modeling answer is often entirely prose and diagrams, which surprises candidates who expected every security question to want a code sample.
Where it sits in a real system
Security engineering is not a layer bolted onto a system after the architecture is decided; done well, it is present at every point a request or a piece of data crosses from one level of trust to another, and those crossing points exist throughout an architecture rather than at one edge of it.
flowchart TD
A[Request arrives at the edge] --> B[Authenticate: who is this]
B --> C[Authorise: may they do this,<br/>to this specific resource]
C --> D[Validate and encode<br/>every input and output]
D --> E[Call downstream services<br/>and stores]
E --> F[Log and monitor<br/>what happened]
F --> G[Detect and respond<br/>to anomalies]The arrow worth staring at is between B and C, because they are so often collapsed into one step in people's mental model despite being genuinely different decisions made with different information. Authentication answers "who is making this request," typically by validating a token's signature. Authorisation answers "may this specific, now-known identity perform this specific action on this specific resource," which requires knowing something about the resource that authentication never touches. The single most common serious defect found in real security assessments is code that gets the first step right and treats the second as implied by it - checking that a token is valid, then fetching whatever id the request asked for with no check that the caller actually owns it. That gap is invisible in a functional test, because the endpoint returns exactly the response a legitimate caller would get; it only shows up when someone asks the question a functional test never asks, which is what happens if a different, equally valid caller supplies someone else's id.
The arrow from E to F matters just as much, in the opposite way. A system with excellent prevention and no visibility into what is happening at runtime will eventually be compromised by something prevention did not anticipate - a novel attack pattern, a misconfiguration nobody's scanner flagged, a zero-day in a dependency - and when that happens, the difference between a contained incident and a catastrophic one is almost entirely a function of how quickly it is detected and how well understood the blast radius is once it is. That is why incident response is not a separate discipline bolted onto security engineering as an afterthought; it is the acknowledgement, built into the architecture from the start, that prevention will not always work.
The trust-boundary framing generalises past this one request-lifecycle diagram to the whole of a distributed system. Every service-to-service call is a boundary. Every third-party integration is a boundary. Every place a build pipeline pulls in code someone else wrote is a boundary. A security engineer's mental model of a system is, to a first approximation, a map of these boundaries with a specific answer at each one for what happens when the assumption on the other side turns out to be false.
| Boundary | What crosses it | What has to happen there |
|---|---|---|
| Client to edge | Untrusted user input, over the public internet | TLS, rate limiting, input validation |
| Edge to service | An authenticated but not yet authorised request | Authorisation scoped to the specific resource |
| Service to service | A request carrying a service identity, often over an internal network | Mutual authentication - "internal" is not the same as "trusted" |
| Application to database | A query built partly from user-supplied values | Parameterisation, least-privileged database credentials |
| Build pipeline to dependency | Someone else's code, pulled in by version number | Dependency scanning, pinned and reviewed versions |
| Log pipeline to observability tooling | Whatever the application chose to write down | Deciding what a log line may contain before it is written, not after |
Who does this work
Application security engineers sit closest to the code, and their day is a mixture of reviewing pull requests for the vulnerability classes automated tooling misses, triaging the output of SAST and SCA scanners into a backlog engineering teams can actually act on, and building or maintaining the internal libraries and frameworks that make the secure path the easy path for everyone else. Penetration testers and red teamers are hired specifically to attack a system the way an adversary would, and the best of them think in terms of attack trees rather than checklists - given a goal, what is the cheapest realistic path to it, rather than a fixed list of things to try in order.
Security architects and threat modeling specialists work earlier in the lifecycle, in design reviews and architecture decision records, asking what trust boundaries a proposed change introduces before a single line of the implementation exists. This is deliberately the cheapest point in the lifecycle to catch a structural flaw, and it is also the point most often skipped under deadline pressure, which is why a mature organisation ties the review to a process step - an ADR template, a pull request checklist - rather than relying on someone remembering to schedule it.
Detection engineers and incident responders own the other end: building the alerting and monitoring that catches what prevention missed, and running the actual response when something does get through - containing the compromise, understanding its scope, and running the post-incident review that feeds back into what application security and threat modeling do differently next time. This is the group most people picture when they imagine "security" from television, and it is real work, but it is a minority of the discipline's total effort in most organisations; the unglamorous majority is upstream of any incident ever happening.
The distinction worth holding onto across all of these roles is between people who build the thing being secured and people whose job is specifically to attack or audit it. A backend engineer who writes a parameterised query because their framework makes it the default path is doing security engineering without the title. A dedicated security engineer who reviews that same code, or who runs a scanner against it, or who tries to break the endpoint it belongs to, is doing security engineering as the whole job. Both are necessary, and an organisation that relies entirely on the second group while giving the first group no secure defaults to lean on is understaffed relative to the amount of code it ships.
Demand, adoption and how that is changing
Demand for security engineering skills is high and has been rising steadily rather than spiking, for reasons that are structural rather than fashion-driven. Regulatory pressure is a real and growing driver - data protection law in most jurisdictions now carries genuine financial consequences for a breach, which has moved security spend from a discretionary line item to a mandatory one in many industries. Cloud adoption is a second driver, and a specific one: moving infrastructure to a cloud provider shifts a large amount of configuration responsibility onto the customer under the shared-responsibility model, and that responsibility - identity permissions, storage access, network rules - turns out to be exactly the kind of thing that goes wrong quietly and expensively when nobody owns it. The sheer growth in attack surface, as more of every business's operations move online and more systems talk to more other systems, is the third and least glamorous driver, and probably the largest one in raw volume of work.
What is genuinely changing the shape of demand right now is the same shift reshaping backend engineering: AI-powered features are backend features, and they need the same security thinking applied to an unusually novel set of risks - what happens when an attacker manipulates the input to a model in a way that gets it to leak data it was never supposed to reveal, or manipulates it into taking an action it should have refused. That is a genuinely new category of concern layered on top of, not replacing, everything this area already covers; a system with an AI-powered feature still needs its authorisation checks done correctly and its dependencies scanned, and the new risk is additive rather than a wholesale change in what the job is.
What is not changing, and is worth saying plainly rather than glossing over: the fundamentals of this field move slowly by design. The OWASP Top 10 categories have been broadly stable for over a decade, not because nobody has found anything new but because the underlying mechanisms - untrusted input treated as code, missing authorisation checks, weak defaults - recur endlessly across new technology stacks. That stability is good news for anyone learning the area, because depth here does not depreciate the way framework-specific knowledge does, but it also means the field rewards patient, structural understanding over chasing whatever the newest named vulnerability class happens to be.
What makes it hard
The genuine difficulty is not memorising a vulnerability catalogue - that part is finite and well documented. It is that security engineering asks you to reason from an adversary's incentives rather than from the system's intended behaviour, and that is a different cognitive move from the one most of software engineering trains. A functional test asks "does this work when used as intended." A security review asks "what happens when someone deliberately uses this in a way it was never intended to be used, and does that person have any reason to bother." Most engineers are trained extensively in the first question and never explicitly trained in the second, which is why it takes real, deliberate practice rather than experience alone - years of writing correct code does not automatically produce the habit of asking what an attacker would try instead.
A second, more subtle difficulty is that the field's successes are invisible and its failures are extremely visible, which distorts how the work gets valued day to day. A threat model that correctly identifies a missing authorisation check before it ships prevents an incident that consequently never happens, and nobody outside the review ever knows what was avoided. A missed one becomes a breach with a name, a disclosure, and a post-mortem read by people well beyond the team that shipped it. That asymmetry means the discipline is structurally undervalued in the moment and only vindicated after the fact, which makes it a genuinely hard sell for resourcing - "prevented nothing visible" is a real accomplishment that looks, from the outside, exactly like doing nothing.
The third difficulty, and the one that decides how a threat-modeling career actually plays out, is organisational rather than technical: finding a real vulnerability is frequently the easy part, and getting it prioritised against a roadmap full of committed feature work is the hard part. A security engineer who can find flaws but cannot translate a finding into a concrete cost a product leader will act on ends up with an accurate, ignored backlog, which is a worse outcome in practice than a slightly less thorough review that actually gets acted on. That translation skill - stating exploitability and blast radius in the same currency the rest of the business is prioritised in - is not taught alongside the technical material, and it is where a lot of otherwise strong technical security engineers plateau.
Why study it
The honest case for studying this area is that it is one of the few places in software engineering where a single missed detail has a genuinely asymmetric cost, and that asymmetry makes the discipline of careful, adversarial thinking transferable well beyond security itself - once you have internalised the habit of asking "what happens if this assumption is false," you apply it to reliability, to data correctness, to concurrency, not only to attackers. It is also one of the more durable specialisations available: the underlying mechanisms move slowly, so depth accumulated here compounds rather than depreciating the way familiarity with a specific framework does, and the roles that need this depth - application security engineer, security architect, incident responder - are not roles that AI-assisted code generation has made less necessary, because generated code is exactly as capable of skipping an authorisation check as hand-written code is.
It is also, honestly, not for everyone, and the field is more interesting to some engineering temperaments than others. If what motivates you is building things people use, security engineering will feel like an unusually large amount of finding fault with other people's work relative to the amount of building you get to do yourself, and that trade is real and worth weighing before committing years to it. If you want fast, visible positive feedback, this is a difficult place to get it, because the discipline's best outcome - nothing happened - produces no feedback signal at all in the moment. And if your interest in security is specifically the offensive, attacker-mindset side - penetration testing, red teaming - be aware that most security engineering roles, day to day, spend far more time on defensive triage and process than on the genuinely adversarial creative work that attracted you to the area in the first place; that work exists, but it is a smaller slice of the field than its public profile suggests.
Your first hour
Take one endpoint from any project you already have running, ideally one that fetches or modifies a specific record by id, and try to break its authorisation rather than its authentication. Log in as one user, note the id of a resource that user owns, then log in as a second user and request the first user's resource id directly - change the number in the URL or the request body and see what comes back. If you get the first user's data, you have just found, by hand, the single most common serious vulnerability class in real production systems, and you now understand viscerally why "the token was valid" and "this caller may see this resource" are different checks rather than one check twice.
Then fix it, and write down the fix in one sentence: the query that fetches the resource must include the caller's identity as part of the lookup itself, not as a separate check performed after the fetch. That sentence - scope at the query, not with an if-statement afterwards - is worth more than reading a chapter on access control, because you derived it from watching the bug happen rather than being told about it.
Before: SELECT * FROM invoices WHERE id = ?
(then, separately, check if the result belongs to the caller
- easy to forget, and the code still "looks" correct)
After: SELECT * FROM invoices WHERE id = ? AND customer_id = ?
(there is no code path that can return someone else's invoice,
because the wrong-owner case simply returns nothing)
If you want a second exercise in the same hour, take any form in the same project that accepts free text and echoes it back somewhere - a comment, a display name - and try submitting a value containing a simple script tag to see whether it renders as a tag or as literal text on the page that displays it. That single check, repeated across every place user input reaches another user's screen, is most of what cross-site scripting testing actually is in practice, and doing it once by hand demystifies a vulnerability class that otherwise sounds more exotic than it is.
What this is not
It is not the same as compliance work, even though the two are frequently confused and frequently sit in the same team. Compliance asks whether a documented control exists and can be evidenced to an auditor; security engineering asks whether the control actually stops the thing it claims to stop. A system can pass every compliance checklist item and still have a missing authorisation check that a fifteen-minute manual review would have found, because the checklist asked "is there an access control policy document" and never asked "does this specific endpoint enforce it."
It is not primarily about firewalls and network perimeters, despite that being the popular image of the field. Perimeter controls remain a real layer, but a growing share of the discipline's actual effort has moved to assuming the perimeter will eventually be crossed and designing every layer behind it to still hold - the zero-trust shift, in short, and it means a security engineer's daily attention is often on application code and identity systems rather than on routers and firewall rules.
It is not the same discipline as penetration testing, even though the two overlap in skills and people move between them. Penetration testing is a point-in-time, adversarial assessment of a specific target; security engineering is the ongoing, structural work of building and operating systems that need fewer things a penetration test would find. A great penetration tester is not automatically a great security architect, and the reverse is equally true, because the first role rewards depth in attack technique and the second rewards breadth across an organisation's whole design and process.
And it is not a solved problem that a sufficiently good tool or a sufficiently strict framework eliminates the need for human judgement in. Scanners and secure-by-default frameworks close entire categories of mechanical mistake, which is real and valuable progress, but they have no opinion on whether a specific business rule - whether this discount code should apply to this customer, whether this refund should be permitted for this order - is being enforced correctly, because that is a decision unique to the application, and no general-purpose tool can be secure with respect to a rule it was never told.
The discipline's whole difficulty is asking "what happens if this assumption is false" about every assumption a system quietly makes, and that habit is learned by finding a real gap yourself far faster than it is learned by reading about someone else's.
Where to go next
Now practise it
9 interview questions in Security & InfoSec, each with the rubric the interviewer is scoring against.
- You are accepting webhooks from two hundred partners. Threat model the ingestion pipeline - what are you actually defending against, and what does the endpoint have to do before it trusts a payload?
- Traffic is a hundred times normal and some of it is real customers. What do you drop first?
- Walk me through applying STRIDE to the boundary where our order service calls the payments service over the network.
- You've run a threat model and found real issues, but engineering leadership says the roadmap has no room this quarter. How do you get the fixes prioritised?