security-model.md markdown
298 lines 9.0 KB
Raw
sha256:5472be4fece32b606c308fad9d57295ce327955fb2b87b8beec6ea1626050473 Add published YouTube URL to Episode 00 Sonnet 5 40 minutes ago

Episode 21 --- Security Model

Working YouTube title:
I Replayed The Exact Same Request And It Worked Twice

Thumbnail thought:
issue #5. issue #6. same header. same timestamp.

Target runtime: ~9:00


[0:00--0:20] COLD OPEN

[CAMERA --- Episode 20's closing line, on screen: "what is this thing actually assuming about the world it's running in."]

GABRIEL:

Twenty episodes of features. One episode of trying to break them on purpose --- headers, SSRF, path traversal, and a replay attack that actually works. Let's find out what Muse defends, and where it doesn't.

[TITLE CARD --- fast]

SECURITY MODEL

[Music enters.]


[0:20--1:00] THE BORING STUFF THAT MATTERS

[TERMINAL]

$ curl -sk -D - -o /dev/null https://localhost:1337/gabriel/wire-episode17
x-frame-options: DENY
x-content-type-options: nosniff
content-security-policy: default-src 'self'; ...; frame-ancestors 'none'; upgrade-insecure-requests

GABRIEL VO:

Not exciting television. Also exactly the headers you want, present on a real response from a real running server, not asserted in a doc.


[1:00--2:20] TRYING TO REACH THE CLOUD METADATA ENDPOINT

[TERMINAL]

$ curl -X POST .../api/repos/.../webhooks --data '{"url":"http://169.254.169.254/latest/meta-data/"}'
{ "msg": "Outbound URL must use https:// ... blocked to prevent credential leakage and SSRF." }

GABRIEL:

Blocked --- but only because I used http. Let's fix that and try again.

$ curl -X POST .../api/repos/.../webhooks --data '{"url":"https://169.254.169.254/latest/meta-data/"}'
{ "msg": "Outbound URL targets a private/reserved IP address (169.254.169.254). ..." }

GABRIEL VO:

Two independent layers. Scheme check, then a real DNS/IP-range check against the exact address cloud metadata services use to leak credentials to anything that can make the server fetch a URL on its behalf. Both had to be defeated; neither was.


[2:20--3:00] A REAL FILENAME ATTACK, REJECTED

[TERMINAL]

$ python3 -c "validate_mist_filename('../../../etc/passwd')"
ValueError: Mist filename must not contain path traversal sequences

GABRIEL:

Same function also rejects path separators and null bytes. This is the guard sitting in front of every Mist artifact this season's episode 20 pushed --- three real attack shapes, three rejections.


[3:00--4:30] THE REPLAY

[CAMERA]

Now the one that actually works. One signed request, sent twice, byte for byte identical --- same header, same body, same timestamp.

$ curl -X POST .../issues -H "Authorization: MSign ...ts=1789246778..." --data '{"title":"Replay test issue"}'
{ "number": 5, "issueId": "sha256:16decb..." }
$ # the exact same curl command, run again, unmodified
{ "number": 6, "issueId": "sha256:bc61a9..." }

[beat]

GABRIEL:

Two different issue numbers. Two different content-addressed IDs. One signature. The server accepted the identical proof of identity twice and did the action twice.


[4:30--5:40] WHY, EXACTLY

[TERMINAL]

$ muse code cat "musehub/auth/request_signing.py" | grep -A2 "abs(server_ts"
if abs(server_ts - ts) > REPLAY_WINDOW_SECONDS:  # 30s
    raise HTTPException(401, ...)

GABRIEL VO:

That's the entire check. It bounds how old a signature can be. It never asks "have I seen this exact signature before." Compare that to how this same codebase handles auth challenges and MPay payments --- both use single-use nonces with a database uniqueness constraint. Per-request MSign signing has no equivalent. It's a freshness check wearing a "replay protection" label.


[5:40--7:00] THE PART THAT MAKES THIS EPISODE DIFFERENT

[CAMERA]

Here's where this stops being a new discovery.

$ muse -C ~/ecosystem/musehub hub issue read 178
#178 -- App security follow-up: MSign replay-protection dedup, content
scanning, retention policy
state: open

GABRIEL VO:

This exact gap. Found, scoped, and tracked five days before I sat down to record this episode --- by a real production-readiness audit of this same codebase. Same root cause, same practical-severity reasoning I just walked through: needs a captured signature within a 30-second window, and the replayed action needs a non-idempotent side effect to matter. Already correctly triaged as real but narrow. Already has an open ticket for the actual fix --- a dedup cache, which turns out to be genuinely non-trivial across a blue/green deployment.

[beat]

GABRIEL:

I'm not filing a duplicate. I'm pointing at it, because independently landing on the same finding, the same severity assessment, and the same "this needs real design work, not a quick patch" conclusion is a better proof this season's methodology holds up than finding something nobody else had ever seen.


[7:00--8:00] WHAT TWENTY-ONE EPISODES OF THIS ACTUALLY ADD UP TO

[CAMERA]

Look back at what's been found across this season versus what's held up. Data loss in shelf save --- real, severe, unknown before this season, filed as a fresh discovery. This replay gap --- real, moderate, already known, already scoped by people actually responsible for this system. Both are the correct outcome of the same discipline: test the actual claim, don't assume either direction.


[8:00--8:40] OUT

[TERMINAL --- fading to black]

GABRIEL VO:

Twenty-one episodes in, every claim tested against the running system, not the pitch deck. One left. Something nobody asked Muse to do, because that's the only way to actually prove "infinite domains" was never marketing copy.

[beat]

That's next. That's the finale.

[CUT TO BLACK]

musehub.ai


Production Notes

Episode 21's spine is a tonal pivot at 5:40: everything before it is "here's a new thing I found," everything after is "here's why finding something already known is the more meaningful result." Don't treat that pivot as a letdown — it's the thesis. Rehearse the transition so it lands as a reveal, not a deflation.

The Replay Demo Needs The Exact Numbers On Screen

Issue #5 vs #6, with the identical ts= value visible in both curl commands, is the entire proof. Don't paraphrase "it worked twice" — show both JSON responses side by side so the audience can read the different issueId/number themselves against the same signature.

Give #178 Its Due, Don't Undersell It

The existing audit document (docs/production-readiness/14-application-security.md) did real, careful work: distinguishing freshness-check from true replay-prevention, scoping exploitability precisely, and explicitly choosing not to overstate risk. Read a piece of it on screen (5:40) — the episode's credibility comes from showing that document exists and is good, not just asserting it.

The Positive Findings Deserve Equal Screen Time

SSRF and path-traversal protection working correctly under direct attack aren't just setup for the replay reveal — they're real, verified engineering that should get the same confident, specific treatment as every bug this season got. Don't let the episode's energy sag until the replay section; the SSRF two-layer defeat attempt (1:00–2:20) should feel just as sharp.

Everything Here Is Real

Every header check, both SSRF attempts, the filename validation calls, and the replay (with real, distinct resulting issue numbers) were run against the actual current build. staging#178's existence and contents were verified live via muse hub issue read, not assumed from the doc alone. Re-run make-security-episode21-demo.sh at record time; if #178 has since closed, Part 5 needs to become "and here's the fix that landed" rather than "here's the open ticket."

The Seed

The viewer arrives thinking:

Security episode — probably a checklist of things that are either fine or broken.

They should leave thinking:

The most convincing security claim isn't "we found nothing wrong" or "here's a scary bug" — it's "we found exactly what a careful internal audit already found, independently, and can explain exactly why it's real but not urgent." That's a harder bar than either extreme, and it's the one this season has actually been running the whole time.

That's the note the finale needs to open on.

File History 1 commit
sha256:5472be4fece32b606c308fad9d57295ce327955fb2b87b8beec6ea1626050473 Add published YouTube URL to Episode 00 Sonnet 5 40 minutes ago