Lesson map
Lesson 04 published. Map, example, EX010.
flowchart TD
N0["Learning outcomes"]
N1["4.1 Small functions"]
N2["4.2 Explicit errors"]
N3["4.3 Testing"]
N4["4.4 Secure defaults"]
N5["4.5 Readability"]
N6["4.6 CWE vocabulary"]
N7["Version control"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX010"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["4.1 Small functions"]
N2["4.2 Explicit errors"]
N3["4.3 Testing"]
N4["4.4 Secure defaults"]
N5["4.5 Readability"]
N6["4.6 CWE vocabulary"]
N7["Version control"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX010"]
[Learning outcomes]
|
v
[4.1 Small functions]
|
v
[4.2 Explicit errors]
|
v
[4.3 Testing]
|
v
[4.4 Secure defaults]
|
v
[4.5 Readability]
|
v
[4.6 CWE vocabulary]
|
v
[Version control]
|
v
[Worked example] --> [Exercise EX010]
Learning outcomes
You will (1) write clear, small functions; (2) handle errors explicitly; (3) read and test simple code; (4) apply secure defaults from the start.
4.1 Small functions
A function should do one thing. Kwame writes fare_for(zone, passengers) that returns a price, separate from code that reads the form.
Separating calculation from input handling means fare_for can be tested with plain values, without a browser or a web form, and the form code can be reviewed for validation on its own. If prices change, only one small function changes. If a flaw appears in form handling, the pricing logic is not involved. Kwame keeps each function short enough to read on one screen, which also makes the review comment he received easy to act on.
4.2 Explicit errors
If zone is unknown, the function raises an error instead of returning zero, which would make tickets free. Failing safely is a security property.
Returning zero looks harmless in a test that only checks valid zones, but in production it would quietly hand out free tickets to anyone who sent a strange zone code. An exception stops the request and leaves a log entry, so the problem is visible. The caller decides what the rider sees, usually a polite message, while the detail stays in the log for engineers.
4.3 Testing
Each function has small tests: valid zones, unknown zone, zero passengers. Tests run on every change.
The unknown-zone test is the most important of the three, because it checks the error path, which normal use rarely exercises. Running tests on every change means a later edit that breaks the error handling is caught within minutes. Kwame also adds a test with a negative passenger count, since a value nobody expects is exactly what an attacker or a buggy client might send.
4.4 Secure defaults
Defaults should be the safe choice: deny unless allowed, escape output unless told otherwise. The template flaw in tmpl arose when one function's default skipped escaping for certain attributes.
A safe default protects every caller who does not think about the issue, which is most of them. An unsafe default requires every caller to remember an extra step, and some will forget. In tmpl, developers who used the affected attributes got unescaped output without asking for it. The fix changed the default, so existing code became safe without any change by ticket-web's developers.
4.5 Readability
Clear names and short functions make review effective; reviewers miss flaws in long, tangled code.
Reviewers have limited attention. A function that fits on one screen and uses names like unescaped_title can be checked in minutes, while a long function with names like t2 hides mistakes. Readability is therefore a security property as well as a courtesy. Kwame's rule of thumb is that if he needs a comment to explain what a line does, the line should probably be rewritten with clearer names first.
4.6 CWE vocabulary
MITRE's CWE Top 25 lists weaknesses such as improper input validation (CWE-20) and cross-site scripting (CWE-79). Learning their names early helps read advisories.
The tmpl flaw is an example of CWE-79: output reached a page without proper escaping. Advisories name the CWE, and knowing it tells a reader at once what kind of mistake caused the flaw and where to look in their own code for the same pattern. Kwame keeps a short list of the CWEs relevant to ticket-web and checks new code against it during review.
Version control
All code lives in version control with history. Each change has a message explaining why it was made and links to a ticket. When the tmpl advisory arrived, the team could see exactly when the framework version that brought tmpl had been added and who reviewed it. History turns questions about the past into simple searches, and it lets the team undo a bad change quickly. Kwame learns to write commit messages that a stranger could understand a year later.
Code style
A shared formatter keeps code consistent, so reviews focus on logic rather than layout.
Worked example
Kwame's first pull request adds fare_for with four tests. Ingrid's review asks him to make the error message avoid echoing user input directly into the page, preventing a possible output-escaping problem.
Synthetic case. Code and review are synthetic.
Errors and limits
Tests show presence of expected behaviour, not absence of all flaws.
Exercises
- EX010 — Fail safely. Why raise an error for an unknown zone?
Show marking criteria
Rubric: 3 = returning zero would make tickets free; 2 = partial; 1 = vague; 0 = none. - EX011 — Default flaw. What default caused the tmpl flaw?
Show marking criteria
Rubric: 3 = skipped escaping for some attributes; 2 = partial; 1 = vague; 0 = none. - EX012 — Review comment. What did Ingrid's review ask?
Show marking criteria
Rubric: 3 = avoid echoing input into page in error; 2 = partial; 1 = vague; 0 = none.
Synthesis
Small, tested functions with safe defaults are the first security control.
Continue studying — chapter 04 of 50
← Chapter 03 (draft) · Course chapter index · Chapter 05 (draft) →