PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/gnops/valopers

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
valopers
Namespace
gnops
Files
14 (gnomod.toml)
Exported functions
13
Module
gno.land/r/gnops/valopers
gno
0.9

Files (14)

  • gnomod.tomltoml
  • admin.gnogno
  • init.gnogno
  • valopers.gnogno
  • admin_test.gnogno
  • pubkey_type_test.gnogno
  • rotate_test.gnogno
  • valopers_test.gnogno
  • z_1_filetest.gnogno
  • z_2_filetest.gnogno
  • z_auth_readonly_filetest.gnogno
  • z_foreign_realm_capability_filetest.gnogno
  • z_govdao_only_principal_filetest.gnogno
  • z_operator_authlist_capability_filetest.gnogno
  • z_foreign_realm_capability_filetest.gnogno
    1// PKGPATH: gno.land/r/zzattacker2//3// Consumer-level regression pin for the governance capability leak.4//5// The package-level pins live in p/moul/authz. This is the consumer-level6// one: an unrelated realm must not be able to drive a valopers privileged7// action.

    Functions

    • AddToAuthList(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string, member string)

    • Auth() string

    • DeleteFromAuthList(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string, member string)

    • GetByAddr(addr string) struct{Moniker string; Description string; ServerType string; OperatorAddress .uverse.address; SigningPubKey string; SigningAddress .uverse.address; LastRotationHeight int64; KeepRunning bool; auth *gno.land/p/nt/ownable/exts/authorizable/v0.Authorizable}

    • NewAuthorityRotationProposalRequest(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, newContractPath string) struct{title string; description string; executor gno.land/r/gov/dao.Executor; filter gno.land/r/gov/dao.Filter}

    • NewInstructionsProposalRequest(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, newInstructions string) struct{title string; description string; executor gno.land/r/gov/dao.Executor; filter gno.land/r/gov/dao.Filter}

    • Register(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, moniker string, description string, serverType string, addr string, pubKey string)

    • Render(fullPath string) string

    • UpdateDescription(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string, description string)

    • UpdateKeepRunning(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string, keepRunning bool)

    • UpdateMoniker(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string, moniker string)

    • UpdateServerType(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string, serverType string)

    • UpdateSigningKey(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, addr string, newPubKey string)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    Rendered

    RenderedRawgnoweb ↗
    8//
    9// Before the fix this file could not exist as a negative test — the
    10// realm exported NewInstructionsProposalCallback, a crossing closure
    11// declared in valopers. The VM mints a crossing frame's `cur` from the
    12// CALLEE's declaring package, so invoking it from anywhere ran
    13// updateInstructions with cur.Address() == the ContractAuthority's
    14// contractAddr. The contract-identity gate accepted, the init.gno
    15// handler ran the action, and `instructions` was rewritten with no
    16// proposal and no vote:
    17//
    18// err: undefined
    19// PWNED-BY-ATTACKER
    20//
    21// The capability is now sealed inside a dao.ProposalRequest, whose
    22// executor field is unexported with no accessor. This file asserts the
    23// two halves of that: the leak is gone from the type system, and the
    24// request an attacker can still construct is inert in their hands.
    25//
    26// NOTE for whoever edits valopers next: the property under test is
    27// "no exported function returns anything carrying this realm's frame
    28// identity". Re-exporting a func(realm) error, or returning a
    29// dao.Executor (whose Execute method is exported and directly
    30// invocable), reopens the hole even though this file would still
    31// compile.
    32package zzattacker
    33
    34import (
    35 "strings"
    36 "testing"
    37
    38 "gno.land/p/nt/testutils/v0"
    39 "gno.land/r/gnops/valopers"
    40 "gno.land/r/gov/dao"
    41 daov3init "gno.land/r/gov/dao/init/v0"
    42)
    43
    44// A real GovDAO exists and the attacker is not in it.
    45var govdaoMember address = testutils.TestAddress("govdao-member")
    46
    47func init(cur realm) {
    48 daov3init.InitWithUsers(cross(cur), govdaoMember)
    49}
    50
    51func main(cur realm) {
    52 // 1. The bare capability is gone. Uncommenting this must not compile:
    53 //
    54 // cb := valopers.NewInstructionsProposalCallback("PWNED-BY-ATTACKER")
    55 // cb(cross(cur))
    56 //
    57 // What remains is the sealed request. An unrelated realm may still
    58 // build one — construction is harmless — but dao.ProposalRequest
    59 // exposes only Title/Description/Filter, so there is no way to reach
    60 // the executor and run it. Only GovDAO executing the proposal can.
    61 testing.SetRealm(testing.NewCodeRealm("gno.land/r/zzattacker"))
    62
    63 req := valopers.NewInstructionsProposalRequest(cross(cur), "PWNED-BY-ATTACKER")
    64 println("attacker built a request:", req.Title())
    65
    66 // 2. The privileged write did not happen: the instructions are still
    67 // the genesis text, not the attacker's. Under the exported callback
    68 // this line already printed "defaced: true".
    69 rendered := valopers.Render("")
    70 println("instructions defaced:", strings.Contains(rendered, "PWNED-BY-ATTACKER"))
    71 println("instructions intact:", strings.Contains(rendered, "Welcome to the **Valopers** realm"))
    72
    73 // 3. Runtime pin, not merely a symbol-absence one. dao.ProposalRequest
    74 // exposes Title/Description/Filter and nothing that yields the
    75 // executor, so the one remaining route for a holder is to ask
    76 // GovDAO to adopt the request. A hostile realm cannot: this aborts.
    77 // (A GovDAO *member* still can, and then it needs the votes — that
    78 // is the legitimate path, covered by
    79 // r/gnops/valopers/proposal/filetests/z_governed_instructions_filetest.gno.)
    80 dao.MustCreateProposal(cross(cur), req)
    81 println("UNREACHABLE: outsider got the proposal adopted")
    82}
    83
    84// Output:
    85// attacker built a request: /r/gnops/valopers: Update instructions
    86// instructions defaced: false
    87// instructions intact: true
    88
    89// Error:
    90// proposal creation must be done directly by a user or through the r/gov/dao proxy. caller realm: realm{gno.land/r/gov/dao:g1p84dvfh4wrplyxx4zsmy77a8rxcnjup2j7zv5r}; caller's previous: realm{gno.land/r/zzattacker:g1q577nx395ehscyn9ucutvfpj03a5tuk7x4v3ad}
    91

    vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.