Designing for Security

Trust boundaries, least privilege and capability-passing as design decisions in the code, distinct from the attacker techniques Security Engineering teaches.

Designing for Security

Five questions — what is trusted, what is untrusted, who may call this, what data is sensitive, where privilege changes — asked before implementation, because afterwards they are structural changes.

Q · Which security decisions are design decisions, made before any code exists, rather than review findings?
Trust Boundaries

A trust boundary is a line in your code, not a line on a network diagram: the place past which data is assumed clean, which is only true if one place made it so.

Q · Where in the code does untrusted data become trusted, and what makes that a place rather than a habit?
Least Privilege as a Design Decision

Least privilege is usually taught as an infrastructure setting. At code granularity it is a parameter type: a function handed a reader cannot write, and that is enforced rather than reviewed.

Q · How do I give a module only the access it needs, in a way the next engineer cannot casually undo?
Capability Passing

Instead of handing a module a service container and hoping, hand it the specific things it may do: CanSendEmail, CanChargePayment. Powerful, honest, and more ergonomic cost than most codebases will accept.

Q · What changes if a module can only perform effects it was explicitly handed, rather than any effect it can reach?
Sensitive State

Which data is sensitive, where it is allowed to travel, and why a type beats a convention: a value that cannot be stringified cannot be logged by accident.

Q · How do I stop sensitive data ending up somewhere nobody designed it to go?