Skip to content

Commit 03a1f12

Browse files
mmsqeHuangYi
andauthored
Problem: path parameter in debug_goTrace is not safe when serve public rpc (#576)
* Problem: no specific dir for the log from debug_goTrace * lint * allow any * revert * cleanup * fix format * fix config * Apply suggestions from code review --------- Co-authored-by: HuangYi <huang@crypto.com>
1 parent 76bf49e commit 03a1f12

File tree

6 files changed

+49
-2
lines changed

6 files changed

+49
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
110110
* [#555](https://github.com/crypto-org-chain/ethermint/pull/555) Update cometbft to 0.38.14 and rocksdb to 9.7.4.
111111
* [#565](https://github.com/crypto-org-chain/ethermint/pull/565) Add back CacheWrapWithTrace api.
112112
* [#563](https://github.com/crypto-org-chain/ethermint/pull/563) Bump ibc-go to v9.0.2.
113+
* [#576](https://github.com/crypto-org-chain/ethermint/pull/576) Add config `json-rpc.restrict-user-input` to restrict
114+
user input when serving json-rpc in public.
113115

114116
## v0.21.x-cronos
115117

rpc/namespaces/ethereum/debug/trace.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ package debug
2222
import (
2323
"errors"
2424
"os"
25+
"path/filepath"
2526
"runtime/trace"
27+
"strings"
2628

2729
stderrors "github.com/pkg/errors"
30+
31+
srvflags "github.com/evmos/ethermint/server/flags"
2832
)
2933

3034
// StartGoTrace turns on tracing, writing to the given file.
@@ -33,16 +37,46 @@ func (a *API) StartGoTrace(file string) error {
3337
a.handler.mu.Lock()
3438
defer a.handler.mu.Unlock()
3539

40+
restrictUserInput := a.ctx.Viper.GetBool(srvflags.JSONRPCRestrictUserInput)
41+
3642
if a.handler.traceFile != nil {
3743
a.logger.Debug("trace already in progress")
3844
return errors.New("trace already in progress")
3945
}
40-
fp, err := ExpandHome(file)
46+
var err error
47+
file, err = ExpandHome(file)
4148
if err != nil {
4249
a.logger.Debug("failed to get filepath for the CPU profile file", "error", err.Error())
4350
return err
4451
}
45-
f, err := os.Create(fp)
52+
53+
file, err = filepath.Abs(file)
54+
if err != nil {
55+
a.logger.Debug("failed to get absolute path for the CPU profile file", "error", err.Error())
56+
return err
57+
}
58+
59+
if restrictUserInput {
60+
// Ensure that the trace file is in the data directory.
61+
absDataDir, err := filepath.Abs(a.ctx.Config.RootDir)
62+
if err != nil {
63+
a.logger.Debug("failed to get absolute path for the data directory", "error", err.Error())
64+
return err
65+
}
66+
67+
if !strings.HasPrefix(file, absDataDir) {
68+
a.logger.Debug("trace file must be in the data directory")
69+
return errors.New("trace file must be in the data directory")
70+
}
71+
}
72+
73+
var f *os.File
74+
if restrictUserInput {
75+
// Create the file with O_EXCL to ensure that the file does not exist.
76+
f, err = os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o666)
77+
} else {
78+
f, err = os.Create(file)
79+
}
4680
if err != nil {
4781
a.logger.Debug("failed to create go trace file", "error", err.Error())
4882
return err

server/config/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,9 @@ type JSONRPCConfig struct {
182182
FixRevertGasRefundHeight int64 `mapstructure:"fix-revert-gas-refund-height"`
183183
// ReturnDataLimit defines maximum number of bytes returned from `eth_call` or similar invocations
184184
ReturnDataLimit int64 `mapstructure:"return-data-limit"`
185+
// RestrictUserInput will restrict some user input to the JSON-RPC debug apis,
186+
// must be set to true if serving debug namespace to the public.
187+
RestrictUserInput bool `mapstructure:"restrict-user-input"`
185188
}
186189

187190
// TLSConfig defines the certificate and matching private key for the server.
@@ -300,6 +303,7 @@ func DefaultJSONRPCConfig() *JSONRPCConfig {
300303
MetricsAddress: DefaultJSONRPCMetricsAddress,
301304
FixRevertGasRefundHeight: DefaultFixRevertGasRefundHeight,
302305
ReturnDataLimit: DefaultReturnDataLimit,
306+
RestrictUserInput: false,
303307
}
304308
}
305309

@@ -435,6 +439,7 @@ func GetConfig(v *viper.Viper) (Config, error) {
435439
MetricsAddress: v.GetString("json-rpc.metrics-address"),
436440
FixRevertGasRefundHeight: v.GetInt64("json-rpc.fix-revert-gas-refund-height"),
437441
ReturnDataLimit: v.GetInt64("json-rpc.return-data-limit"),
442+
RestrictUserInput: v.GetBool("json-rpc.restrict-user-input"),
438443
},
439444
TLS: TLSConfig{
440445
CertificatePath: v.GetString("tls.certificate-path"),

server/config/toml.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ fix-revert-gas-refund-height = {{ .JSONRPC.FixRevertGasRefundHeight }}
108108
# Maximum number of bytes returned from eth_call or similar invocations.
109109
return-data-limit = {{ .JSONRPC.ReturnDataLimit }}
110110
111+
# RestrictUserInput will restrict some user input to the JSON-RPC debug apis,
112+
# must be set to true if serving debug namespace to the public.
113+
restrict-user-input = {{ .JSONRPC.RestrictUserInput }}
114+
111115
###############################################################################
112116
### TLS Configuration ###
113117
###############################################################################

server/flags/flags.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ const (
7272
JSONRPCEnableMetrics = "metrics"
7373
JSONRPCFixRevertGasRefundHeight = "json-rpc.fix-revert-gas-refund-height"
7474
JSONRPCReturnDataLimit = "json-rpc.return-data-limit"
75+
JSONRPCRestrictUserInput = "json-rpc.restrict-user-input"
7576
)
7677

7778
// EVM flags

server/start.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ which accepts a path for the resulting pprof file.
217217
cmd.Flags().Int(srvflags.JSONRPCMaxOpenConnections, config.DefaultMaxOpenConnections, "Sets the maximum number of simultaneous connections for the server listener") //nolint:lll
218218
cmd.Flags().Bool(srvflags.JSONRPCEnableIndexer, false, "Enable the custom tx indexer for json-rpc")
219219
cmd.Flags().Bool(srvflags.JSONRPCAllowIndexerGap, true, "Allow block gap for the custom tx indexer for json-rpc")
220+
cmd.Flags().Bool(srvflags.JSONRPCRestrictUserInput, false, "Restrict some user input to the JSON-RPC debug apis, must be set to true if serving debug namespace to the public") //nolint:lll
220221
cmd.Flags().Bool(srvflags.JSONRPCEnableMetrics, false, "Define if EVM rpc metrics server should be enabled")
221222

222223
cmd.Flags().String(srvflags.EVMTracer, config.DefaultEVMTracer, "the EVM tracer type to collect execution traces from the EVM transaction execution (json|struct|access_list|markdown)") //nolint:lll

0 commit comments

Comments
 (0)