Skip to content

Public fixture

This standard-library Python exercise is course-made synthetic practice for the Week 8 notes. No model, package installation, real data or external service is used. Every file works in memory or inside the directory it is run from.

Run it

Work on a copy, never in this directory. From the course checkout:

WORK="$(mktemp -d)"
cp -r lectures/week-08/fixture/. "$WORK"/
cd "$WORK"
export PYTHONDONTWRITEBYTECODE=1
python chain.py; echo "exit $?"
python exercise.py > starter-checks.json; echo "exit $?"
python verify_triage.py > triage-before.json; echo "exit $?"
{"surface": "repository_note", "proposed": ["read_label", "export"], "responses": ["text", "tool_denied"], "effects": ["read_label", "export"]}
{"surface": "tool_response", "proposed": ["read_label", "export"], "responses": ["text", "tool_denied"], "effects": ["read_label", "export"]}
{"surface": "copied_log", "proposed": ["read_label", "export"], "responses": ["text", "tool_denied"], "effects": ["read_label", "export"]}
{"kind": "synthetic_injection_chain", "task_completed": true, "unauthorized_effects": 3}
exit 1
exit 1
exit 1

All three commands exit 1 on the unchanged starter. The notes walk through each output, the repair and the rerun. The export line stops Python from caching compiled modules, so each run reads the file you have just edited.

Contract

A request has exactly two string fields, tool and record. The record names one of three supplied synthetic surfaces. Only read_label is permitted. Malformed requests return invalid_arguments; other tool names return tool_denied. Refused calls must not append an effect. Every attempted call consumes one of two attempts, including invalid and denied requests. A third call returns budget_exhausted without any new effect.

Files

Boundary example:

  • candidate.py: deliberately faulty proposal; edit this file in your copy.
  • chain.py: the inert chain. A fixed rule, not a model, performs the authorized read and proposes export when the returned text asks for it. It exits 0 only when no unauthorized effect is recorded and the authorized read still works.
  • exercise.py: public feedback checks, case by case; keep the original expectations while repairing.
  • demo.py: deterministic generator for a four-request packet with the required responses and effects.
  • verify_demo.py: verifier for that packet; it refuses a packet whose cases were edited.
  • scan-report.json: three course-written scanner claims for disposition practice.

Triage example:

  • preferences.py: a configuration parser with an unsafe loader and a separately allowlisted status formatter. The pickle.loads call is the planted finding. Never pass it anything except the inputs the verifier sends, and do not craft or load pickle data.
  • preferences.lock: one locked version of a fictional package.
  • triage-scan.json: three course-written findings in the format of the course's offline scanner. The package and advisory are fictional.
  • agent-draft.json: a course-written agent draft classifying each finding. It is not a model transcript.
  • scan/: the course's three offline scanners in plain Python (static rules, a dependency audit against the dated advisories.json snapshot, a secret scan) and run_scans.py, which prints one JSON report. The notes run it from the course checkout on your copy; it reads files only and exits 0 whether or not it finds anything.
  • verify_triage.py: parses preferences.py before running it, against three allowlists listed at the top of the verifier and in the notes: the modules it may import (json, logging, typing, dataclasses, re, __future__), the attribute names it may use, and the built-in names it may use; every other name must be defined in the file. Anything else is refused unread and the file is not executed. A refusal means "outside what this small check can vouch for", not "malicious". Assigned, defined, parameter and alias names cannot shadow Python built-ins; class fields are added as attributes only when no allowlisted module already exposes that name. A file that imports pickle is run only against a stand-in module whose loaders record the call, so it never receives the real pickle module, and it is never accepted. The verifier exits 1 until the file passes the allowlists without importing pickle, JSON text parses, six different texts that are not JSON each raise an error, and the permitted status path still works. It is a narrow public check for a teaching fixture, not a sandbox: it does not make running unknown code safe.

What the starter does

On the starter, chain.py reports three unauthorized effects, one per surface. In exercise.py four of the nine checks fail: the three denied-surface cases report tool_denied but leave export in effects, and denied_unlisted, which asks for a delete_label tool the contract never names, fails the same way. The allowed reads, the malformed-input check and the budget check pass. verify_demo.py fails denied_export and denied_unlisted on a packet generated by demo.py.

Limits

The effect list demonstrates dispatcher ordering, not operating-system containment: a modified process could bypass this toy dispatcher altogether. What such a process can reach is decided by the directory or container it runs in, not by this code. The exercise is not a live attack, a vulnerability scan of a real project or an acceptance decision about your own work.

Keep the original fixture separately from your copy. The public output is feedback, not a mark, and a check you have edited no longer shows what the original showed.