Investigate a denied request

Read a useful security event and walk through an incident response decision.

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

Produce an access-denial log and use it to complete a short incident worksheet.

Before you start

The fixed API, Node.js 24, and incident-playbook.txt from the starter folder.

You’re finished when

You have observed a 403 event, completed the worksheet prompts, and stopped the server.

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. Terminal 1 · extracted starter folder

    Start the server and keep its output visible

    TERMINAL 1
    node app.mjs

    Lab 05 ended by stopping the server. Start it again now, and leave this terminal open so you can see the log output.

    Check before continuing

    Learning fixture listening on port 3000.

  2. Terminal 2

    Generate one allowed and one denied request

    Open a second terminal in the project folder. Run Alice’s request, then Bob’s request, one at a time.

    TERMINAL 2 · ALICE
    node -e "fetch('http://127.0.0.1:3000/records/1', {headers:{Authorization:'Bearer demo-alice'}}).then(async r=>console.log(r.status, await r.json()))"
    TERMINAL 2 · BOB
    node -e "fetch('http://127.0.0.1:3000/records/1', {headers:{Authorization:'Bearer demo-bob'}}).then(async r=>console.log(r.status, await r.json()))"
    Check before continuing

    Terminal 2 shows 200 for Alice and 403 for Bob.

  3. Terminal 1

    Find the denial in the server log

    Look at Terminal 1, where the server is running. It should show these decision events:

    {"event":"record_read","status":200}
    {"event":"record_read","status":403}

    The second line records the denial you just generated. These log lines should not contain bearer tokens or Alice’s note title. One denial by itself is not proof of an attack.

    Check before continuing

    You can point to the 403 event and explain which request produced it.

  4. Text editor · incident-playbook.txt

    Complete the incident worksheet

    Open incident-playbook.txt. Read the scenario: a client update is causing repeated requests for stale record IDs. Fill in the three role blanks; one practice name may cover all roles. Then answer all four prompts:

    • What evidence would distinguish a client bug from deliberate enumeration?
    • Who can approve a containment action?
    • How would you measure recovery?
    • What improvement will you make, who owns it, and by when?

    For example, compare the denial rate before and after the client update, identify affected client versions, and check whether record IDs are being requested sequentially. Save your decisions; you do not need to install a monitoring service.

    Check before continuing

    The worksheet has named roles and concrete answers to all four exercise prompts.

  5. Terminal 1 → this page

    Stop the server and finish the course

    Press Ctrl+C in Terminal 1. Answer the quick check below. Mark the lesson complete once the worksheet is saved.

    Check before continuing

    The server has stopped and your incident worksheet is saved beside the threat model.

Why it works & help if you get stuck

READ THE DECISION

A denial is evidence to interpret.

EXCERPT / CHECKED SERVER OUTPUT
Learning fixture listening on port 3000
{"event":"record_read","status":401}
{"event":"record_read","status":200}
{"event":"record_read","status":403}

The 403 tells you the access decision denied the request. It doesn’t tell you whether the caller made a mistake, the client has a bug, or someone is deliberately probing. In this exercise, you know it came from the synthetic Bob request.

Run a ten-minute tabletop

  1. Minute 0: record the denial and ask how it compares with normal traffic. Who is looking at it?
  2. Minute 3: a client update has just shipped. What evidence would distinguish stale links from repeated enumeration?
  3. Minute 6: choose a proportionate action and name who can approve it. Write down the evidence you would retain.
  4. Minute 10: define recovery and assign one improvement, such as a new regression case or useful correlation context.

Use the incident worksheet to record the decisions. The validation checked that the example logs contain a denial event and omit the synthetic bearer values and private note title. It did not validate a production alert, SIEM integration, or an incident response team.

IF YOUR RESULT IS DIFFERENT

Common wrong turns

What happenedWhy it mattersWhat to do instead
Treat every 403 as a confirmed breach.Denials can be expected behavior or client mistakes.Validate context, baseline, and impact.
Log the bearer value or full record for debugging.The log becomes a new source of sensitive data.Record the decision and suitable correlation context instead.
Finish the worksheet without an owner.The improvement may never reach the next change.Assign a specific follow-up, owner, and verification method.

AFTER THE SIX LESSONS

Try one change of your own.

Make a separate copy of your fixed starter project. Add a synthetic record with ID 2, owner bob, and a different title to the existing records Map. Keep the existing identities unchanged.

  1. Predict the results when Bob and Alice request record 2.
  2. Add tests in security.test.mjs using the existing readRecord examples: Bob gets 200 and the new title; Alice gets 403 with no title.
  3. Run the tests. The original five must still pass, together with your new tests.
  4. Explain why your ownership guard should need no changes.

Use Node directly or your chosen Docker test route. Keep this separate from the original five-test lesson copy, and do not use real data.

Next, practice resolving a Git conflict, or revisit where these checks fit in a pipeline.

TRY WITHOUT COPYING · OPTIONAL

Explain the evidence

Does one 403 log event prove an attack? Name one useful follow-up question and one piece of information that should not go in the log.

Compare your reasoning

No. It could be a mistake or a deliberate request. Ask whether denials repeat in an unusual pattern and what context is available. Do not log bearer credentials or private note contents.

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

A QUICK CHECK

What should you do with one access-denied event?

Choose an answer
Compare with the solution +
Keep logs structured and focused on the decision. Validate scope, preserve evidence with access controls, and choose a proportionate response. In a real system, define retention and add suitable correlation context without recording secrets.
OWASP logging guidance ↗

Done with this one?

Marking complete is your own record.

Confirm your results

Confirm both results before marking this lab complete.