make-security-episode21-demo.sh
bash
sha256:60261384aebd0385d587313fa975be03725e351bf8012d7e2d1fae604a2c5e95
Add Episode 21 script (Security Model) and security demo driver
Sonnet 5
patch
13 hours ago
| 1 | #!/usr/bin/env bash |
| 2 | # Drives real security-boundary tests for Episode 21 ("Security Model"). |
| 3 | # Requires the local MuseHub dev stack running. |
| 4 | set -euo pipefail |
| 5 | |
| 6 | HUB="https://localhost:1337" |
| 7 | REPO_ID="sha256:6a9b70085b05951c452133f4c499dde446e80689b5578a60d96660e988d73f2a" |
| 8 | ENC_REPO=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$REPO_ID', safe=''))") |
| 9 | |
| 10 | echo "=== Part 1: security headers, on a real live response ===" |
| 11 | curl -sk -D - -o /dev/null "$HUB/gabriel/wire-episode17" | grep -iE "x-frame|x-content-type|strict-transport|content-security" |
| 12 | |
| 13 | echo |
| 14 | echo "=== Part 2: SSRF protection -- webhook targeting the AWS metadata endpoint ===" |
| 15 | echo "--- http scheme (blocked at the scheme layer) ---" |
| 16 | BODY1='{"url":"http://169.254.169.254/latest/meta-data/","events":["push"]}' |
| 17 | printf '%s' "$BODY1" > /tmp/ep21_ssrf1.json |
| 18 | HEADER=$(muse sign header --method POST --path "/api/repos/$ENC_REPO/webhooks" --hub "$HUB" --body-file /tmp/ep21_ssrf1.json --json | python3 -c "import json,sys; print(json.load(sys.stdin)['header_value'])") |
| 19 | curl -sk -X POST "$HUB/api/repos/$ENC_REPO/webhooks" -H "Authorization: $HEADER" -H "Content-Type: application/json" --data-binary @/tmp/ep21_ssrf1.json |
| 20 | echo |
| 21 | echo "--- https scheme (blocked at the IP-range layer) ---" |
| 22 | BODY2='{"url":"https://169.254.169.254/latest/meta-data/","events":["push"]}' |
| 23 | printf '%s' "$BODY2" > /tmp/ep21_ssrf2.json |
| 24 | HEADER=$(muse sign header --method POST --path "/api/repos/$ENC_REPO/webhooks" --hub "$HUB" --body-file /tmp/ep21_ssrf2.json --json | python3 -c "import json,sys; print(json.load(sys.stdin)['header_value'])") |
| 25 | curl -sk -X POST "$HUB/api/repos/$ENC_REPO/webhooks" -H "Authorization: $HEADER" -H "Content-Type: application/json" --data-binary @/tmp/ep21_ssrf2.json |
| 26 | |
| 27 | echo |
| 28 | echo "=== Part 3: mist filename validation -- path traversal, separators, null bytes ===" |
| 29 | python3 - <<'PY' |
| 30 | import sys |
| 31 | sys.path.insert(0, "/Users/gabriel/ecosystem/muse") |
| 32 | from muse.plugins.mist.plugin import validate_mist_filename |
| 33 | |
| 34 | for name in ["validate_assignee.py", "../../../etc/passwd", "a/b.py", "a\x00b.py"]: |
| 35 | try: |
| 36 | validate_mist_filename(name) |
| 37 | print(f"{name!r}: ACCEPTED") |
| 38 | except Exception as e: |
| 39 | print(f"{name!r}: REJECTED -- {type(e).__name__}: {e}") |
| 40 | PY |
| 41 | |
| 42 | echo |
| 43 | echo "=== Part 4: MSign replay -- the real, known, already-tracked gap ===" |
| 44 | BODY3='{"title":"Replay test issue","body":"testing MSign replay behavior"}' |
| 45 | printf '%s' "$BODY3" > /tmp/ep21_replay.json |
| 46 | HEADER=$(muse sign header --method POST --path "/api/repos/$ENC_REPO/issues" --hub "$HUB" --body-file /tmp/ep21_replay.json --json | python3 -c "import json,sys; print(json.load(sys.stdin)['header_value'])") |
| 47 | echo "signed header (will be reused verbatim): $HEADER" |
| 48 | echo "--- request 1 ---" |
| 49 | curl -sk -X POST "$HUB/api/repos/$ENC_REPO/issues" -H "Authorization: $HEADER" -H "Content-Type: application/json" --data-binary @/tmp/ep21_replay.json | python3 -c "import json,sys; d=json.load(sys.stdin); print('issue #', d['number'], d['issueId'])" |
| 50 | echo "--- request 2: exact replay, same header, same body, same timestamp ---" |
| 51 | curl -sk -X POST "$HUB/api/repos/$ENC_REPO/issues" -H "Authorization: $HEADER" -H "Content-Type: application/json" --data-binary @/tmp/ep21_replay.json | python3 -c "import json,sys; d=json.load(sys.stdin); print('issue #', d['number'], d['issueId'])" |
| 52 | |
| 53 | echo |
| 54 | echo "=== Part 5: this exact finding is already known and tracked ===" |
| 55 | muse -C ~/ecosystem/musehub hub issue read 178 --hub https://staging.musehub.ai --json | python3 -c " |
| 56 | import json, sys |
| 57 | d = json.load(sys.stdin) |
| 58 | print('#' + str(d['number']), '--', d['title']) |
| 59 | print('state:', d['state']) |
| 60 | " |
| 61 | |
| 62 | rm -f /tmp/ep21_ssrf1.json /tmp/ep21_ssrf2.json /tmp/ep21_replay.json |
| 63 | |
| 64 | echo |
| 65 | echo "Demo complete." |
File History
1 commit
sha256:60261384aebd0385d587313fa975be03725e351bf8012d7e2d1fae604a2c5e95
Add Episode 21 script (Security Model) and security demo driver
Sonnet 5
patch
13 hours ago