Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}