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

stringify_proposal_00_filetest.gno

3.77 Kb · 116 lines
  1// PKGPATH: gno.land/r/test
  2package test
  3
  4import (
  5	"strings"
  6	"testing"
  7
  8	"gno.land/p/nt/testutils/v0"
  9	"gno.land/r/gov/dao"
 10	"gno.land/r/gov/dao/impl/v0"
 11	"gno.land/r/gov/dao/memberstore/v0"
 12)
 13
 14var (
 15	testUser = testutils.TestAddress("test")
 16)
 17
 18// StringifyProposal carries its own copy of the disclosure expression, separate
 19// from the one in render.gno. It has no production caller today, but it is
 20// exported, and an untested copy of a security-relevant expression is free to
 21// drift from the tested one. This executor pins it: CreationRealm is reached
 22// through the public interface, so it can return anything, and the run of two
 23// backticks closes a narrower fence.
 24type hostileExec struct{}
 25
 26func (e *hostileExec) Execute(cur realm) error { return nil }
 27
 28func (e *hostileExec) String() string { return "" }
 29
 30// Padded on both ends as well as fenced: without the TrimSpace, InlineCode
 31// pads the fence to protect the leading and trailing spaces, and the expected
 32// span below no longer matches. That makes one payload cover both the escaping
 33// and the trim.
 34func (e *hostileExec) CreationRealm() string { return "  gno.land/r/evil`` **INJECTED**  " }
 35
 36func memberByTier(tier string) *memberstore.Member {
 37	switch tier {
 38	case memberstore.T1:
 39		t, _ := memberstore.GetTier(memberstore.T1)
 40		return memberstore.NewMember(t.InvitationPoints)
 41	default:
 42		panic("unsupported tier: " + tier)
 43	}
 44}
 45
 46func init(cur realm) {
 47	// Load members for testing
 48	mstore := memberstore.Get(0, cur)
 49	mstore.DeleteAll()
 50	mstore.SetTier(memberstore.T1)
 51	mstore.SetMember(memberstore.T1, testUser, memberByTier(memberstore.T1))
 52
 53	// Set up the DAO implementation using proper constructor
 54	govDAO := impl.NewGovDAO()
 55	dao.UpdateImpl(cross(cur), dao.NewUpdateRequest(govDAO, []string{"gno.land/r/test", "gno.land/r/gov/dao/impl/v0"}))
 56}
 57
 58func main(cur realm) {
 59	// Create an executor in a specific realm to test creation realm tracking
 60	testing.SetRealm(testing.NewCodeRealm("gno.land/r/template/contract"))
 61	executor := dao.NewSimpleExecutor(0, cur, func(realm) error { return nil }, "Test executor description")
 62
 63	// Create a proposal request
 64	proposalRequest := dao.NewProposalRequest(
 65		"Test Proposal Title",
 66		"This is a test proposal description to verify StringifyProposal works correctly.",
 67		executor,
 68	)
 69
 70	// Switch to user realm to create the proposal
 71	testing.SetOriginCaller(testUser)
 72	testing.SetRealm(testing.NewUserRealm(testUser))
 73	pid := dao.MustCreateProposal(cross(cur), proposalRequest)
 74
 75	// Get the proposal and test the core functionality
 76	prop := dao.MustGetProposal(pid)
 77
 78	// Test that executor string is captured correctly
 79	println("Executor string:", prop.ExecutorString())
 80
 81	// Test that executor creation realm is captured correctly
 82	println("Executor creation realm:", prop.ExecutorCreationRealm())
 83
 84	// Stringify
 85	println("----")
 86	println(impl.StringifyProposal(prop))
 87
 88	// The same disclosure, through a hostile executor.
 89	hpid := dao.MustCreateProposal(cross(cur), dao.NewProposalRequest(
 90		"Hostile", "creation realm attacks the code span", &hostileExec{}))
 91	hout := impl.StringifyProposal(dao.MustGetProposal(hpid))
 92
 93	println("stringify widens the fence too:",
 94		strings.Contains(hout, "```gno.land/r/evil`` **INJECTED**```"))
 95	println("and no bold escapes it:", !strings.Contains(hout, "\n**INJECTED**"))
 96}
 97
 98// Output:
 99// Executor string: Test executor description
100// Executor creation realm: gno.land/r/template/contract
101// ----
102//
103// ### Title: Test Proposal Title
104//
105// ### Proposed by: g1w3jhxazlta047h6lta047h6lta047h6lwmjv0n
106//
107// This is a test proposal description to verify StringifyProposal works correctly.
108//
109// This proposal contains the following metadata:
110//
111// Test executor description
112//
113// Executor created in: `gno.land/r/template/contract`
114//
115// stringify widens the fence too: true
116// and no bold escapes it: true