Fundamentalsassetsthreatstrustriskblast radiuscontrols

What Security Engineering Actually Is

Security engineering is not a checklist of vulnerabilities; it is the discipline of deciding what you value, who can reach it, what you are trusting, and what happens when one of those assumptions turns out to be wrong.

▶ Run the labFollow the failure

Frame the problem

Security starts with a concrete asset, attacker capability and trust crossing.

Asset
Everything the system is responsible for: user accounts, customer data, money, availability, and the reputation that depends on all three.
Attacker & capability
Anyone who can reach any part of the system and wants an outcome you did not intend — from an opportunistic scanner to a logged-in customer poking at URLs to a compromised dependency running inside your build.
Trust boundary
Every place where data or control passes from something you do not control into something you do.
AssetThreatAttack SurfaceTrust BoundaryVulnerabilityExploit PathImpactMitigationDefense in DepthResidual Risk

The six questions

A vulnerability list tells you what other people got wrong. It does not tell you whether *your* system is exposed, how badly, or what to do first. Security engineering starts one level up, with a sequence of questions that works on any system, in any language, at any scale — and that you can answer for a component in about ten minutes.

The order matters. Asking "are we vulnerable to XSS?" before asking "what do we have that is worth stealing?" produces a backlog with no priorities. Asking "what is the blast radius?" before "which control prevents this?" is what turns a finding into a design decision instead of a ticket.

Notice that two of the six questions are not about prevention at all. Detection and failure-of-control are where real systems live: every prevention you deploy will eventually be bypassed, misconfigured, or shipped around by a deadline, and the question that separates a security engineer from a checklist is *what happens then*.

  • What is the asset? Name the specific thing: the users table, the signing key, the ability to issue refunds. "The system" is not an asset.
  • Who is the attacker? An unauthenticated stranger, a logged-in customer, another tenant, a compromised worker, an insider, a malicious dependency. Each has a different starting position.
  • What capability does the attacker have? Can they send HTTP requests? Run code in a browser you serve? Read your build logs? Capability, not intent, decides what is reachable.
  • What trust boundary is crossed? The interesting bugs are always at a boundary: browser → API, API → database, CI → production, model → tool.
  • What is the blast radius? One user, one tenant, every tenant, the whole company. This is the number that decides priority.
  • Which control prevents it, which control detects it, and what happens if that control fails? Three questions that must be answered together, because a system with only prevention is a system that fails silently.
Internet
untrusted
Anyone. Every byte is attacker-controlled until proven otherwise, including headers, cookies and the shape of the request.
┃ trust boundary ┃
Internet → Public API: authenticate the caller, validate the shape and the semantics of every field, and rate-limit before doing work.
Public API
semi-trusted
Requests here have been authenticated, but authentication only establishes *who*, never *what they may do*.
┃ trust boundary ┃
Public API → Internal Services: carry the *user* identity, not just a service identity, so authorization can still be decided downstream.
Internal Services
trusted
The dangerous zone: "internal" is a network fact, not an identity fact, and treating it as trust is how one compromise becomes many.
┃ trust boundary ┃
Internal Services → Database: connect as a role scoped to exactly the tables and verbs this service needs, so a bug above cannot become a `DROP TABLE` below.
Database
privileged
Holds the asset itself. Whatever credentials reach it define the maximum damage any bug upstream can do.

Prevention, detection, recovery

Controls come in three kinds and teams routinely buy only the first. Prevention stops the action: a parameterized query, an authorization check, a network rule. Detection notices that it happened: an alert on a spike of 403s, an audit log entry, an anomaly in egress volume. Recovery limits the duration: credential rotation, session revocation, a restore from backup, a rollback.

The reason all three are needed is arithmetic. Prevention has some failure rate — a missed check, a new endpoint, a dependency upgrade that changes escaping behaviour. If detection is absent, the expected time an attacker spends inside your system is not bounded by anything. Most catastrophic breaches are not remarkable exploits; they are ordinary exploits that nobody noticed for eight months.

This is also why "we fixed it" is never the end of an incident. The fix is prevention. The questions that follow — *would we have seen it? how long would it have taken? what would we have had to rotate?* — are what turn one incident into a system that survives the next one.

The same threat, seen through three kinds of control
ThreatPreventDetectRecover
Stolen session tokenHttpOnly + Secure cookies, short lifetime, rotation on privilege changeSame session ID from two countries within minutes; sudden burst of sensitive readsRevoke the session server-side; force re-authentication; notify the user
SQL injectionParameterized queries everywhere; a database role that cannot read other tablesQuery errors with syntax fragments; unusual row counts; WAF signal as a *hint*, not a gateRotate database credentials; audit what the role could reach; restore from a known-good backup
Leaked API key in gitSecret scanning in pre-commit and CI; secret manager instead of filesProvider-side alerts on unusual usage; scanner hits on public reposRevoke first, investigate second; rotate everything the key could reach
Over-privileged worker compromisedScoped machine identity; egress allowlistWorker calls an API it has never called before; new outbound destinationKill the workload, rotate its credentials, review what it touched via audit logs

Never say "secure"

"Is it secure?" has no answer, because security is not a property a system has; it is a relationship between a system, a set of assets, and a set of attackers with capabilities. A system can be entirely adequate against opportunistic scanning and entirely inadequate against a determined insider, and both statements are true at once.

The honest replacement is a four-part answer that a reviewer can actually act on: identified controls (what we have), known risks (what we have decided to accept, with the reason), residual risks (what survives the controls we deployed), and unknowns (what we have not examined yet). This framing survives contact with reality; "we are secure" does not survive the first pentest.

It also fixes the incentive problem. A team that must declare "secure" learns to avoid looking. A team that maintains a residual-risk list is rewarded for finding things, which is the behaviour you actually want. See Risk, Residual Risk and Honest Reporting for how to keep that list from becoming a graveyard.

Key points

  • Start from the asset, not the vulnerability. A vulnerability list without assets produces a backlog with no priorities.
  • Capability, not intent, decides what an attacker can reach. Model what they can *do* from where they already stand.
  • Every control belongs to one of three families — prevention, detection, recovery — and a system with only prevention fails silently.
  • Blast radius is the number that sets priority: one user, one tenant, all tenants, the company.
  • Replace "is it secure?" with identified controls, known risks, residual risks and unknowns.

Boundary control exercise

This lesson uses the shared boundary-control exercise.

Boundary control check
Untrusted input / identity
Trust boundary
Privileged asset
Prevention may fail silently.

Follow the attack

Safe conceptual simulation: capability → missing control → crossed boundary → asset impact.

  1. 1
    Attacker → reachable surface: enumerate what answers on the public internet — endpoints, subdomains, a forgotten admin panel, an object store left readable.
  2. 2
    Reachable surface → weakest crossing: pick the boundary that validates least. Usually the newest endpoint or the one written under deadline.
  3. 3
    Crossing → capability: turn "I can send a request" into "I can run a query / read a file / call an internal service".
  4. 4
    Capability → asset: use that capability to reach the thing with value — data, money, or the ability to grant themselves more access.
  5. 5
    Asset → persistence: create a second way in (a new API key, an added OAuth app, a modified CI workflow) so that fixing the first bug changes nothing.
Blast radius
  • Confidentiality: data that was supposed to be readable by one person becomes readable by anyone.
  • Integrity: records are modified with no reliable way to tell which ones, which turns a security incident into a data-quality incident that lasts months.
  • Availability: the service stops answering, which is a security failure even when nothing was stolen.
  • Trust and obligation: notification duties, contractual consequences, and the slower cost that every future security request now gets funded reactively.

Defend, detect, recover

One prevention is a single point of security failure. Layer it and make failure observable.

Prevent
  • • Write down the assets before writing the controls; a control with no named asset is a guess.
  • • Enumerate trust boundaries explicitly in the architecture diagram, and require every crossing to name what it validates.
  • • Default to deny: new endpoints, new buckets, new roles start closed and are opened deliberately.
  • • Reduce what has to be trusted rather than trying to make more things trustworthy — the smallest trusted computing base wins.
Detect
  • • Audit-log every privileged operation with who, what, which resource, when, from where and the result.
  • • Alert on control *absence*, not only on attacks: an endpoint deployed without an authorization decorator, a bucket that turned public, a role that gained a wildcard.
  • • Track authentication and authorization failures as a rate, per identity and per resource — a slow climb is more informative than a spike.
Respond & recover
  • • Contain before you investigate: revoke the credential, kill the session, isolate the workload. Evidence is worth less than stopping the bleeding.
  • • Assume everything the compromised identity could reach was reached, until logs prove otherwise.
  • • Rotate transitively: the leaked key, everything it could read, and anything that was itself a credential.
  • • Write the timeline while it is fresh, and turn the missing detection into a specific alert before closing the incident.
Residual risk
  • • You cannot enumerate every asset; systems accrete data stores, and the forgotten ones are the ones nobody protects.
  • • Threat models age. The model is accurate on the day it is written and drifts with every deploy.
  • • An insider with legitimate access defeats most boundary controls by definition; the remaining defenses are least privilege, audit and separation of duties.
  • • Supply chain compromise starts inside your trust boundary, which is exactly where the model assumed safety.

Misconceptions

Claim
“We use HTTPS, so we are secure.”
Reality
TLS protects data *in transit between two endpoints*. It says nothing about whether the endpoint you are talking to should be allowed to see the data, whether the server stores it safely, or whether the logged-in user is authorized to read the record they just requested.
Claim
“The internal network is trusted.”
Reality
"Internal" is a statement about routing, not identity. Any service that can be reached from a compromised host is reachable by the attacker who compromised it — which is the entire premise of [[network-segmentation]] and zero-trust designs.
Claim
“Nobody knows that endpoint exists.”
Reality
Obscurity is not a control. Certificate transparency logs, JavaScript bundles, mobile app strings and internet-wide scanning find undocumented endpoints within hours.