CodeRigor

FREE LESSON

Trust boundaries, validation & output contexts

Validate a canonical request identifier while preserving legitimate comment text and encoding it for one explicit HTML context.

A trust boundary is a point where one component accepts facts from another component with different authority. A request can propose a ticket number; it cannot establish that the caller owns that ticket. A database can return a stored comment; storage does not establish that the comment is safe to interpret as HTML. Begin by naming the source, the sink and the decision at each crossing.

This course uses small local Python functions and real in-memory SQLite queries. It runs no browser, login provider or public service. Failing tests expose specific violated contracts. Passing those tests gives evidence about these fixtures, not a guarantee that an application is secure.

Follow the authority, then the representation
start / 3
A valid identifier and an encoded comment have different guarantees.
Follow the authority, then the representation
A valid identifier and an encoded comment have different guarantees.

Validation asks whether a value belongs to the application's accepted domain. The lab's ticket identifier is an ASCII decimal string from "1" to "9999", without leading zeroes. Its comment is a Python string of 1–80 Unicode code points without NUL. These are product choices, not universal identifier or name rules. Reject invalid input with ValueError; silently repairing " 7" or accepting True changes the contract.

Encoding asks how accepted data should be represented at a particular sink. A comment such as Mina & Jo <3 is valid text. Removing punctuation would damage it. In the fixed HTML text position between <p> and </p>, html.escape preserves its meaning while representing angle brackets and ampersands as character references.

Python
from html import escape
comment = 'Mina & Jo <3'
print('<p>' + escape(comment, quote=True) + '</p>')

The result is <p>Mina &amp; Jo &lt;3</p>. This transformation is not SQL parameter binding, JavaScript string encoding, URL scheme validation or an authorization check. Escaping a value for a quoted HTML attribute also does not make an arbitrary URL scheme acceptable. Prefer a framework's context-aware template autoescaping in an actual service; the fixed wrapper makes this exercise's sink explicit.

One string, two representations
start / 2
Encoding happens for a fixed HTML text context. It preserves text rather than deleting punctuation.
One string, two representations
Encoding happens for a fixed HTML text context. It preserves text rather than deleting punctuation.

Store original text when the data model calls for text, and encode when producing the output representation. Encoding an already encoded value can display &amp;lt; where a reader expected &lt;. Conversely, unescaping input before rendering can reintroduce syntax. In this lab render_comment always receives original text, so a literal "&lt;" becomes "&amp;lt;" in the HTML source and remains that literal text on display.

Work through three cases before coding: a valid ticket with punctuation, a Unicode digit that resembles an ASCII digit, and a comment of exactly 80 code points. Python's isdecimal() alone accepts more scripts than the ticket grammar permits. Python's string length counts code points, not UTF-8 bytes or user-perceived grapheme clusters; uploads later use byte limits.

The build separates parse_ticket from render_comment so neither operation accidentally grants the other's authority. The first bug hunt weakens the identifier alphabet; the second bypasses the output transformation. Test rejected input as carefully as happy paths, then explain which downstream decisions still need their own checks.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Watch 11:48–39:26 for code injection, stored data and character escapes, then 1:07:51–1:12:44 for server-side validation. The whole lecture is free; the local lab runs no browser.