security_patterns.gno
2.21 Kb · 68 lines
1package security_patterns
2
3import "gno.land/p/nt/markdown/sanitize/v0"
4
5var (
6 admin = address("g125em6arxsnj49vx35f0n0z34putv5ty3376fg5")
7 message = "Only the admin can edit this message."
8)
9
10func SetMessage(cur realm, next string) {
11 assertAdmin(cur)
12 message = next
13}
14
15func TransferAdmin(cur realm, next address) {
16 if !next.IsValid() {
17 panic("invalid admin")
18 }
19 assertAdmin(cur)
20 admin = next
21}
22
23func Admin() address {
24 return admin
25}
26
27func Message() string {
28 return message
29}
30
31func Render(path string) string {
32 out := "# Security Patterns\n\n"
33 out += "This realm demonstrates three defensive patterns; read the source " +
34 "alongside this page:\n\n"
35 out += "1. **Live-realm guard** — `assertAdmin` panics unless " +
36 "`cur.IsCurrent()` holds, which checks the realm token against the " +
37 "live call frame before any authority is read from it.\n"
38 out += "2. **Caller identity via `cur.Previous().Address()`** — the admin " +
39 "check reads the immediate caller, not `OriginCaller()`, so an " +
40 "intermediary realm cannot pass itself off as the user.\n"
41 out += "3. **Sanitized render output** — every value echoed below is run " +
42 "through `p/nt/markdown/sanitize` first, so caller-controlled text " +
43 "cannot inject markdown or break out of a code span.\n\n"
44 // InlineCode wraps in a backtick run wide enough to outscan any backticks
45 // in the content, so a backtick in path cannot close the span early — a
46 // naive "`" + path + "`" would.
47 out += "Admin: " + sanitize.InlineCode(admin.String()) + "\n\n"
48 out += "Message: " + sanitize.InlineText(message) + "\n"
49 if path != "" {
50 out += "\nPath: " + sanitize.InlineCode(path) + "\n"
51 }
52 return out
53}
54
55// assertAdmin guards a state-mutating call. Callers pass their own cur rather
56// than cross(cur) — a non-crossing call of a crossing function, so
57// PreviousRealm does not shift and still names whoever called SetMessage or
58// TransferAdmin. The cur realm first parameter is what makes it a crossing
59// function: the compiler refuses any other first argument, so the token
60// reaching IsCurrent below is live by construction.
61func assertAdmin(cur realm) {
62 if !cur.IsCurrent() {
63 panic("invalid realm")
64 }
65 if cur.Previous().Address() != admin {
66 panic("admin only")
67 }
68}