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

render_error_paths_filetest.gno

2.17 Kb · 59 lines
 1// PKGPATH: gno.land/r/test/rendererr
 2package rendererr
 3
 4// Render is reachable unauthenticated via vm/qrender with an attacker-chosen
 5// path. Two pre-existing defects on that path are covered here:
 6//   - the "invalid proposal id" error echoed the raw pid segment (strconv
 7//     quotes it but leaves markdown/HTML metachars), so a crafted pid injected
 8//     inline markup into a govDAO-branded page;
 9//   - a control byte in the query string made the pager's MustGetPageByPath
10//     panic, aborting the landing-page render.
11// Both are now escaped / degraded-gracefully.
12
13import (
14	"strings"
15	"testing"
16
17	"gno.land/r/gov/dao"
18	"gno.land/r/gov/dao/impl/v0"
19	"gno.land/r/gov/dao/memberstore/v0"
20)
21
22const user address = "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"
23
24func init(cur realm) {
25	memberstore.Get(0, cur).DeleteAll()
26	memberstore.Get(0, cur).SetTier(memberstore.T1)
27	memberstore.Get(0, cur).SetMember(memberstore.T1, user, memberstore.NewMember(3))
28	dao.UpdateImpl(cross(cur), dao.NewUpdateRequest(impl.NewGovDAO(), nil))
29}
30
31func main(cur realm) {
32	testing.SetOriginCaller(user)
33	testing.SetRealm(testing.NewUserRealm(user))
34
35	// 1. A non-numeric pid whose segment carries an inline-markdown payload.
36	// No '/', so it routes to {pid}; ParseInt fails and the error is escaped.
37	pout := dao.Render(cross(cur), "99[pwn](evil.example)")
38	println("payload is escaped, not a live link:",
39		strings.Contains(pout, `\[pwn\]`) && !strings.Contains(pout, "[pwn](evil.example)"))
40	println("still shows the invalid-id message:",
41		strings.Contains(pout, "Invalid proposal ID format"))
42
43	// Same on the /votes route.
44	vout := dao.Render(cross(cur), "88[x](evil.example)/votes")
45	println("votes route escapes it too:",
46		!strings.Contains(vout, "[x](evil.example)"))
47
48	// 2. A control byte in the query — url.Parse rejects it. The landing page
49	// must degrade to page 1, not panic.
50	lout := dao.Render(cross(cur), "?\x01")
51	println("control-byte query renders instead of panicking:",
52		strings.Contains(lout, "# GovDAO"))
53}
54
55// Output:
56// payload is escaped, not a live link: true
57// still shows the invalid-id message: true
58// votes route escapes it too: true
59// control-byte query renders instead of panicking: true