CYART // SCHEMA · DEFENSE-LAYERS7 NODES · 7 LINKSBLOCKED HERETELEMETRYALERTTHREAT · Attacker — phish, creds, exploitTHREAT01Attackerphish, creds, exploitEDGE · Edge — WAF, DDoS, TLSEDGE02EdgeWAF, DDoS, TLSSERVICE · Identity — SSO, MFA, deviceSERVICE03IdentitySSO, MFA, deviceSERVICE · Application — input validation, authzSERVICE04Applicationinput validation, authzDATA · Data — encryption, DLP, KMSDATA05Dataencryption, DLP, KMSSTREAM · Detection — logs, EDR, SIEMSTREAM06Detectionlogs, EDR, SIEMSTREAM · Response — runbooks, isolate, rotateSTREAM07Responserunbooks, isolate, rotate

Secure design principles that still hold

Saltzer and Schroeder's eight principles applied to cloud, APIs and microservices, plus secure defaults and attack surface reduction, worked through real design reviews.

● Must know for interviewsFREELesson·26 min read·Beginner → Intermediate
secure designleast privilegeattack surfacedesign review

01Eight principles from 1975, still undefeated

✓What you will learn
  • Name the Saltzer and Schroeder principles and give a modern example of each
  • Spot which principle a design violates in a review
  • Argue for secure defaults and attack surface reduction with concrete changes
  • Turn principles into review questions a team can actually answer

Saltzer and Schroeder wrote their design principles for time-sharing systems in 1975. Almost every modern breach write-up maps to one of them being broken. Treat them as a shared vocabulary for design reviews: "this violates complete mediation" is faster and less personal than "this is insecure".

PrincipleMeansModern example
Least privilegeEvery subject gets only the rights it needs, only for as long as it needs themPer-service IAM role scoped to one bucket prefix; JIT admin that expires in an hour
Fail-safe defaultsAccess is denied unless explicitly grantedDefault-deny network policy; authz middleware that returns 403 when the policy engine is unreachable
Complete mediationEvery access to every object is checked, every timeObject-level authz on each read, not just at login or at the route; no long-lived cached grants
Economy of mechanismKeep security mechanisms small and simple enough to reviewOne shared authz library instead of forty hand-rolled checks
Separation of privilegeSensitive actions need more than one condition or personTwo-person approval for production IAM changes; MFA plus device posture
Least common mechanismMinimise mechanisms shared between users or tenantsPer-tenant encryption keys and queues instead of one shared worker with every tenant's secrets
Psychological acceptabilitySecurity must be easy to use correctly or people route around itPasskeys instead of 20-character rotation rules; a paved-road deploy that is faster than the unsafe one
Open designSecurity must not depend on the design being secretPublished crypto (AES-GCM, Argon2id), secret keys; no home-made obfuscation
◎Interview radar

Expect "give me an example of least privilege going wrong" or "what does fail-safe mean in practice?". Answer with a system you have seen, the principle it broke and the specific change that fixed it.

02Secure defaults and attack surface

Most production misconfigurations are not decisions; they are defaults nobody changed. If the safe setting is opt-in, a fraction of teams will forget it forever. Make the safe setting the default and make the unsafe one require a visible, reviewed override.

▭On the whiteboard · Secure by default, in practice4 points
01
storage
buckets private, encrypted, versioned; public access needs an exception tag and a ticket
02
services
new service template ships with mTLS, authn middleware and default-deny ingress
03
frameworks
templates auto-escape; ORM is parameterised; raw query helper needs a lint waiver
04
accounts
no shared logins; SSO only; break-glass accounts sealed and alarmed

Attack surface is everything an attacker can send input to or reach: ports, endpoints, parameters, file uploads, admin panels, debug routes, third-party webhooks, IAM roles that can be assumed. Every item is code that must be correct forever. Removing it is the only fix with zero maintenance cost.

  • Delete what is not used: old API versions, debug endpoints, unused IAM roles, stale DNS records.
  • Disable optional features by default: XML external entities, server-side template evaluation, verbose errors.
  • Move admin and management interfaces off the public internet, behind the zero trust gateway.
  • Narrow inputs: accept a schema, not "any JSON"; accept an enum, not a free string.
Fail-safe defaults in codets
// Fail-safe authorisation middleware: errors and timeouts deny, never allow.
export async function authorise(req: Request, action: string, resource: string) {
  try {
    const decision = await policy.check({ subject: req.user, action, resource }, { timeoutMs: 200 });
    if (decision.allow !== true) throw new Forbidden(decision.reason ?? "denied");
  } catch (err) {
    log.warn({ action, resource, err: String(err) }, "authz denied");
    throw err instanceof Forbidden ? err : new Forbidden("policy unavailable");
  }
}

// The anti-pattern this replaces:
// const ok = await policy.check(...).catch(() => true); // fail open "for availability"
!Fail open is a decision, so make it explicitly

Some controls should fail open (a rate limiter in front of a login page during a provider outage, for example). That is fine when it is written down, alarmed and reviewed. A silent catch(() => true) is how authz quietly disappears during an incident.

03Principles in a design review

A design review is not a hunt for bugs; it is a hunt for decisions that make whole classes of bugs likely. Walk the data flow, then ask one question per principle. Three worked examples:

ProposalPrinciple brokenBetter design
Report worker gets a role with s3:* on all buckets because "it needs to read reports"Least privileges3:GetObject on reports/tenant-* only; writes go to a separate output prefix
Mobile app hides the admin API by not linking it; backend trusts an isAdmin flag in the requestOpen design, complete mediationServer derives role from the token and checks it on every admin call; assume every endpoint is discovered
One shared Redis for all tenants' sessions and job payloadsLeast common mechanismPer-tenant key prefixes with ACLs at minimum; separate instances for regulated tenants
Prod deploy can be triggered by any engineer from a laptopSeparation of privilegeDeploys only from CI on protected branches, with a second approver for production
  1. Who can call this, and how does the service know? (complete mediation)
  2. What is the smallest permission set that works? (least privilege)
  3. What happens when a dependency is down or slow? (fail-safe defaults)
  4. Could a reviewer read the whole security mechanism in one sitting? (economy of mechanism)
  5. What is shared between tenants, and what leaks if it is compromised? (least common mechanism)
  6. Will engineers and users actually follow it under deadline pressure? (psychological acceptability)
iDefence in depth is not on the list

Saltzer and Schroeder also discussed work factor and compromise recording. Modern lists add defence in depth and zero trust. They complement the eight; they do not replace them.

“How to say it in the room

"I review designs against a short list: least privilege, fail-safe defaults and complete mediation first, because those catch most real issues. Then I ask what is shared between tenants and whether the secure path is also the easy path. If it is not, people will route around it."

Test yourself

A service caches a user's permissions for 24 hours after login to save policy lookups. Which principle is most directly at risk?

Q1Is security through obscurity always bad?+

Obscurity as the only control is bad. As an extra layer (non-default ports, hidden admin paths) it can cut noise, but the design must stay secure if the obscured detail is published.

Q2How do least privilege and developer speed coexist?+

Generate policies from observed access (access analysers), grant broad rights in dev and narrow ones in prod, and make JIT elevation fast. Least privilege that takes a week to request becomes standing admin.

Q3Which principle is violated most often in the cloud?+

Least privilege, by far: wildcard IAM actions, long-lived keys and roles reused across services. Fail-safe defaults is next, through public-by-default resources in older accounts.

04When principles collide

Principles pull against each other. Separation of privilege adds approvals, which costs psychological acceptability. Economy of mechanism argues for one shared authz service, which least common mechanism might question. The engineering job is to choose deliberately and write down why.

TensionUsual resolution
Separation of privilege vs speedTwo-person rule only for high-blast-radius actions; everything else is single approver with audit
Economy of mechanism vs least common mechanismOne shared authz library (simple, reviewed) with per-tenant data and keys underneath
Fail-safe vs availabilityFail closed for authz and data access; fail open only for controls whose failure is not a security boundary, and alarm it
FigPrinciples applied as layers
CYART // SCHEMA · DEFENSE-LAYERS7 NODES · 7 LINKSBLOCKED HERETELEMETRYALERTTHREAT · Attacker — phish, creds, exploitTHREAT01Attackerphish, creds, exploitEDGE · Edge — WAF, DDoS, TLSEDGE02EdgeWAF, DDoS, TLSSERVICE · Identity — SSO, MFA, deviceSERVICE03IdentitySSO, MFA, deviceSERVICE · Application — input validation, authzSERVICE04Applicationinput validation, authzDATA · Data — encryption, DLP, KMSDATA05Dataencryption, DLP, KMSSTREAM · Detection — logs, EDR, SIEMSTREAM06Detectionlogs, EDR, SIEMSTREAM · Response — runbooks, isolate, rotateSTREAM07Responserunbooks, isolate, rotate
  • EDGE
  • SERVICE
  • DATA
  • STREAM
  • THREAT
  • Live flow
  • Lookup / async
//Each layer applies the same principles at a different level: network default deny, identity with least privilege, per-request authorisation, and encrypted data with per-tenant keys. A failure in one layer is caught by the next.
Finished this one?
Tick it and it shows as done on the roadmap and the course.