Map the risk before the code

Trace a private record request and write a testable security requirement.

Where do you want to run the labs?

Local machine instructions selected. You can switch at any time.

Switching changes the instructions only. Stop any exercise server or container yourself before starting the other route. Both routes use the same files and completion marks.

YOUR TASK · LOCAL MACHINE

Fill in one small threat-model worksheet. You will identify what could go wrong before changing any code.

Before you start

A text editor. No terminal, Node.js, Docker, or GitHub account needed for this lesson.

You’re finished when

Your saved threat-model.txt has an owner, date, and answers to all four “Your turn” prompts.

Go to step 1 ↓

Do the exercise on your computer. This page provides instructions and saves completion marks; it does not run commands or check your files.

Follow these steps

  1. File manager

    Download and extract the exercise

    Download the ZIP below. Find it in Downloads and extract it into a new folder called opsrung-lab. On Windows, right-click the ZIP → Extract All. Open the extracted folder, not the ZIP preview.

    Download starter ZIP ↓

    You should see eight files: README.txt, app.mjs, security.test.mjs, Dockerfile, security.yml, threat-model.txt, incident-playbook.txt, and verify-lab.mjs. Keep this folder for every lab.

    Check before continuing

    Eight extracted files are visible, including verify-lab.mjs. You can open and edit the text files.

  2. Text editor · threat-model.txt

    Open the worksheet and read the scenario

    Open threat-model.txt in a text editor. Alice owns record 1, a private note. Bob has his own valid demo identity. Bob asks the API for Alice’s record. Read the six filled-in lines: asset, flow, boundary, threat, control, and proof.

    The key decision is on the server: being signed in does not mean Bob can read Alice’s note.

    Check before continuing

    You can explain why Bob must get 403 (access denied), while Alice must still get 200 (success).

  3. Text editor · threat-model.txt

    Fill in the four blank prompts

    Add your name or a practice name and today’s date at the top. Under Your turn, replace each blank with your answer:

    • Availability risk: what could stop legitimate users from getting a response?
    • Mitigation and owner: what control would reduce that risk, and who would maintain it?
    • Test: what result would tell you the control works?
    • Assumption: what have you assumed that a real project would need to confirm?
    Need an example to get started?

    Risk: too many requests exhaust the API. Mitigation and owner: the API maintainer adds a request limit. Test: excess requests are limited while normal requests still succeed. Assumption: normal request volume is known. This is a planning example; you do not implement a rate limiter in this course.

    Check before continuing

    All four prompts contain a concrete answer rather than underscores.

  4. Text editor → this page

    Save the worksheet and check your answer

    Save threat-model.txt. Check that your proposal protects availability without blocking every legitimate request. Answer the quick check below, then mark this lesson complete.

    Next, you’ll use the same extracted folder to reproduce and fix the ownership bug.

    Check before continuing

    You have a saved worksheet and can describe one risk, one control, an owner, and a test.

Why it works & help if you get stuck

WORKED EXAMPLE

Trace one request, not the whole internet.

Our asset is Alice’s private note. Bob can sign in with his own demo identity. The risk appears when Bob changes the record ID in a request: knowing an ID is not permission to read it.

THE TRUST BOUNDARY
Untrusted caller
  GET /records/1 + Bearer demo-bob
             ↓ request boundary
API → maps token to bob → looks up record 1
             ↓ access decision
    Does record.owner equal bob?
        yes → 200   no → 403
QuestionAnswer for this fixture
What belongs to whom?Record 1 belongs to Alice. Its title must not reach Bob.
What can the caller choose?The URL and bearer value. Neither should decide record ownership.
What is the requirement?Bob gets HTTP 403 with no title; Alice still gets HTTP 200.
What would prove it?One negative test for Bob and one positive test for Alice, plus HTTP boundary checks.

Your deliverable: fill in the worksheet’s availability risk, mitigation owner, and verification method. One reasonable risk is excessive requests exhausting the service; a possible mitigation is a rate limit with a load test. That control is a planning example and is not implemented in this fixture.

IF YOUR RESULT IS DIFFERENT

Common wrong turns

What happenedWhy it mattersWhat to do instead
“Hide Alice’s record in Bob’s interface.”Bob can still send the HTTP request directly.Put the ownership decision in the API.
“Return 403 for every request.”Private data stays private, but Alice loses legitimate access.Keep both allow and deny acceptance criteria.

TRY WITHOUT COPYING · OPTIONAL

Change the story

Imagine the note belongs to Bob instead of Alice. Who should receive 200, who should receive 403, and which rule stays the same?

Compare your reasoning

The owner gets 200 and a different recognized user gets 403. Authorization compares the requester with the owner, rather than permanently allowing one particular name.

Explain your answer aloud or write a sentence before opening the explanation. This does not change your completion record.

A QUICK CHECK

Where should record ownership be enforced?

Choose an answer
Compare with the solution +
Asset: Alice’s private note. Threat: an authenticated user guesses another record ID. Control: compare the authenticated user with record.owner. Evidence: a regression test expects 403 and an absent title.
OWASP threat modeling ↗

Done with this one?

Marking complete is your own record.

Confirm your results

Confirm both results before marking this lab complete.