| id | course-secure-code-l05 | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| type | course | |||||||||||||||
| title | Lesson 5: Review your own AI-written code | |||||||||||||||
| summary | Take the five questions and the scanner pass to a repository you own: find where input crosses a trust boundary, check each crossing for a mechanism, and write down what you did not review. | |||||||||||||||
| lang | en-US | |||||||||||||||
| content_version | 1 | |||||||||||||||
| status | reviewed | |||||||||||||||
| reviewed_on | 2026-10-11 | |||||||||||||||
| hints |
|
You review a repository you own — ideally code an assistant wrote — with the same method, fix at least one finding with a test that proves it, and record what you did not review.
The notes service was a sandbox with planted flaws and known answers. Your code has neither. What transfers is the method: find each place input crosses a trust boundary, ask who controls it and what they want, and check that the code uses a mechanism rather than a hope.
- List the trust boundaries. Search for where input enters: web
routes, CLI arguments, uploaded files, queue consumers,
os.environreads. Write the list before reading any of them closely. - Run the scanner.
ruff check --select S(or the scanner your team already uses) gives you the pattern-level findings in seconds. Triage each one: real, false positive, or accepted risk — and write down why. - Ask the five questions the scanner cannot. For each boundary:
- Does any input reach SQL, a shell, or a template other than as a bound parameter or argument list?
- Does any input become part of a filesystem path, and is containment checked after resolving?
- Is there any default, fallback, or example secret in the code path that runs in production?
- Are passwords or tokens hashed with a slow, salted function and
compared with
hmac.compare_digest? - Does anything deserialize client data with
pickle,marshal,shelve, or an unsafe YAML loader?
- Fix one finding with a test first. Write the attack as a failing test, fix it with a mechanism, watch the test pass. Ask your agent for the fix after the test exists, and review its diff against the mechanism, not just the test.
- Record. Verified / not verified / known limits. "Not verified" includes every boundary you listed but did not read.
If you find something serious in code other people depend on, follow your organization's or the project's security disclosure process before you open a public issue.
Ask your coding agent to list the trust boundaries in your repository, then compare its list with yours. Note what each of you missed.
This checkpoint is self-attested. When you can answer the questions below,
claim it with python verify.py --attest l05:
- How many trust boundaries did you list, and how many did you actually read?
- Which finding did you fix, and what test proves it?
- Which scanner finding did you mark as a false positive or accepted risk, and why?
Your boundary list, the scanner triage, the failing-then-passing test, and the three-line record. Keep findings about unfixed vulnerabilities out of public places until they are fixed.