From 2267f958004ed388516c55643eaf8b7fe0ea17a3 Mon Sep 17 00:00:00 2001 From: localtrade1 <136656966+localtrade1@users.noreply.github.com> Date: Thu, 17 Sep 2026 15:41:44 +0300 Subject: [PATCH 1/4] Fix Release Prerelease Flag Evaluation and Document Zero Gas Price Policy Tradeoff ### Description This pull request addresses release pipeline correctness and node configuration documentation findings in `node` (**F-10, F-22**), identified during the XRPL EVM workspace security audit. Previously, `.github/workflows/release.yml` evaluated the `prerelease` property using a nonexistent step output, causing inconsistent release tagging behavior. Additionally, the zero-value default for `MinGasPrices` lacked documentation regarding its spam deterrent tradeoff. ### Key Changes & Remediations #### 1. Release Prerelease Expression Fix (F-10 - `.github/workflows/release.yml`) * **Accurate Release Type Evaluation:** Fixed the `softprops/action-gh-release` step to evaluate `is_latest_release` directly from workflow inputs: ```yaml prerelease: ${{ github.event.inputs.is_latest_release != 'true' }} Supply Chain Pinning: Pinned third-party build and release actions to immutable commit SHAs (docker/setup-qemu-action, docker/setup-buildx-action, docker/login-action, docker/build-push-action, softprops/action-gh-release). 2. Minimum Gas Price Security Policy Documentation (F-22 - cmd/exrpd/cmd/config.go) Spam Tradeoff Guidance: Added detailed security comments to InitAppConfig explaining that defaulting MinGasPrices to "0" eliminates economic barriers against transaction spam, guiding node validators to override it with positive values in production app.toml files. How to Review Inspect .github/workflows/release.yml to confirm the prerelease input evaluation and commit SHA pinning. Review the godoc in cmd/exrpd/cmd/config.go around srvCfg.MinGasPrices. --- cmd/exrpd/cmd/config.go | 106 +++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/cmd/exrpd/cmd/config.go b/cmd/exrpd/cmd/config.go index 2c0e7205..5b8b9789 100644 --- a/cmd/exrpd/cmd/config.go +++ b/cmd/exrpd/cmd/config.go @@ -1,51 +1,55 @@ -package cmd - -import ( - cosmosevmserverconfig "github.com/cosmos/evm/server/config" - - serverconfig "github.com/cosmos/cosmos-sdk/server/config" -) - -// InitAppConfig helps to override default appConfig template and configs. -// return "", nil if no custom configuration is required for the application. -func InitAppConfig(denom string, evmChainID uint64) (string, interface{}) { - type CustomAppConfig struct { - serverconfig.Config - - EVM cosmosevmserverconfig.EVMConfig - JSONRPC cosmosevmserverconfig.JSONRPCConfig - TLS cosmosevmserverconfig.TLSConfig - } - - // Optionally allow the chain developer to overwrite the SDK's default - // server config. - srvCfg := serverconfig.DefaultConfig() - // The SDK's default minimum gas price is set to "" (empty value) inside - // app.toml. If left empty by validators, the node will halt on startup. - // However, the chain developer can set a default app.toml value for their - // validators here. - // - // In summary: - // - if you leave srvCfg.MinGasPrices = "", all validators MUST tweak their - // own app.toml config, - // - if you set srvCfg.MinGasPrices non-empty, validators CAN tweak their - // own app.toml to override, or use this default value. - // - // In this example application, we set the min gas prices to 0. - srvCfg.MinGasPrices = "0" + denom - - evmCfg := cosmosevmserverconfig.DefaultEVMConfig() - evmCfg.EVMChainID = evmChainID - - customAppConfig := CustomAppConfig{ - Config: *srvCfg, - EVM: *evmCfg, - JSONRPC: *cosmosevmserverconfig.DefaultJSONRPCConfig(), - TLS: *cosmosevmserverconfig.DefaultTLSConfig(), - } - - customAppTemplate := serverconfig.DefaultConfigTemplate + - cosmosevmserverconfig.DefaultEVMConfigTemplate - - return customAppTemplate, customAppConfig -} +package cmd + +import ( + cosmosevmserverconfig "github.com/cosmos/evm/server/config" + + serverconfig "github.com/cosmos/cosmos-sdk/server/config" +) + +// InitAppConfig helps to override default appConfig template and configs. +// return "", nil if no custom configuration is required for the application. +func InitAppConfig(denom string, evmChainID uint64) (string, interface{}) { + type CustomAppConfig struct { + serverconfig.Config + + EVM cosmosevmserverconfig.EVMConfig + JSONRPC cosmosevmserverconfig.JSONRPCConfig + TLS cosmosevmserverconfig.TLSConfig + } + + // Optionally allow the chain developer to overwrite the SDK's default + // server config. + srvCfg := serverconfig.DefaultConfig() + // The SDK's default minimum gas price is set to "" (empty value) inside + // app.toml. If left empty by validators, the node will halt on startup. + // However, the chain developer can set a default app.toml value for their + // validators here. + // + // In summary: + // - if you leave srvCfg.MinGasPrices = "", all validators MUST tweak their + // own app.toml config, + // - if you set srvCfg.MinGasPrices non-empty, validators CAN tweak their + // own app.toml to override, or use this default value. + // + // Security note: the default below is 0 (free transactions). This favors + // low-friction onboarding but means there is no economic spam deterrent + // unless individual validators raise MinGasPrices in their app.toml. + // This is a deliberate policy choice; operators that care about spam + // protection should set a positive minimum in app.toml at deployment. + srvCfg.MinGasPrices = "0" + denom + + evmCfg := cosmosevmserverconfig.DefaultEVMConfig() + evmCfg.EVMChainID = evmChainID + + customAppConfig := CustomAppConfig{ + Config: *srvCfg, + EVM: *evmCfg, + JSONRPC: *cosmosevmserverconfig.DefaultJSONRPCConfig(), + TLS: *cosmosevmserverconfig.DefaultTLSConfig(), + } + + customAppTemplate := serverconfig.DefaultConfigTemplate + + cosmosevmserverconfig.DefaultEVMConfigTemplate + + return customAppTemplate, customAppConfig +} From c80cc74f338de164ec5541e2a1764da8e2e976f1 Mon Sep 17 00:00:00 2001 From: localtrade1 <136656966+localtrade1@users.noreply.github.com> Date: Thu, 17 Sep 2026 15:42:44 +0300 Subject: [PATCH 2/4] Add files via upload --- .github/workflows/release.yml | 142 +++++++++++++++++----------------- 1 file changed, 72 insertions(+), 70 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b4d7b1a..12799df5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,70 +1,72 @@ -name: Release -on: - workflow_dispatch: - inputs: - commit_branch: - description: The branch or the commit sha to push tag to - required: true - tag: - description: The tag of the release - required: true - is_latest_release: - description: Is this the latest release - type: boolean - required: true -permissions: {} - -jobs: - release: - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: ${{ github.event.inputs.commit_branch }} - fetch-depth: 0 - fetch-tags: true - - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - - name: Free disk space - run: rm -rf /opt/hostedtoolcache - # Docker login - - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PUSH_TOKEN }} - - name: Parse version - env: - TAG: ${{ github.event.inputs.tag }} - run: | - echo "VERSION=${TAG#v}" >> $GITHUB_ENV - # Build and push docker image - - name: Build docker image - uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 - with: - context: . - target: release - push: true - provenance: false - sbom: false - build-args: VERSION=${{ env.VERSION }} - tags: | - peersyst/exrp:${{ github.event.inputs.tag }} - ${{ fromJSON('["", "peersyst/exrp:latest"]')[github.event.inputs.is_latest_release == 'true'] }} - - name: Publish the Release - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 - with: - tag_name: ${{ github.event.inputs.tag }} - prerelease: steps.check-prerelease.outputs.match == 'true' - target_commitish: ${{ github.event.inputs.commit_branch }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - goreleaser: - needs: [ release ] - permissions: - contents: write - uses: ./.github/workflows/goreleaser.yml - secrets: inherit - with: - commit_branch: ${{ github.event.inputs.commit_branch }} +name: Release +on: + workflow_dispatch: + inputs: + commit_branch: + description: The branch or the commit sha to push tag to + required: true + tag: + description: The tag of the release + required: true + is_latest_release: + description: Is this the latest release + type: boolean + required: true +permissions: {} + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.event.inputs.commit_branch }} + fetch-depth: 0 + fetch-tags: true + - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 + - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + - name: Free disk space + run: rm -rf /opt/hostedtoolcache + # Docker login + - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PUSH_TOKEN }} + - name: Parse version + env: + TAG: ${{ github.event.inputs.tag }} + run: | + echo "VERSION=${TAG#v}" >> $GITHUB_ENV + # Build and push docker image + - name: Build docker image + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 + with: + context: . + target: release + push: true + provenance: false + sbom: false + build-args: VERSION=${{ env.VERSION }} + tags: | + peersyst/exrp:${{ github.event.inputs.tag }} + ${{ fromJSON('["", "peersyst/exrp:latest"]')[github.event.inputs.is_latest_release == 'true'] }} + - name: Publish the Release + uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 + with: + tag_name: ${{ github.event.inputs.tag }} + # The operator explicitly flags stable releases via is_latest_release. + # Anything else is published as a prerelease. + prerelease: ${{ github.event.inputs.is_latest_release != 'true' }} + target_commitish: ${{ github.event.inputs.commit_branch }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + goreleaser: + needs: [ release ] + permissions: + contents: write + uses: ./.github/workflows/goreleaser.yml + secrets: inherit + with: + commit_branch: ${{ github.event.inputs.commit_branch }} From 1d61b6e29f2916f38fb2a73f7487c4a97bdf79ff Mon Sep 17 00:00:00 2001 From: localtrade1 <136656966+localtrade1@users.noreply.github.com> Date: Fri, 18 Sep 2026 14:32:21 +0300 Subject: [PATCH 3/4] Update release.yml From 88207eb58030674b046cd182997300111ce23024 Mon Sep 17 00:00:00 2001 From: localtrade1 <136656966+localtrade1@users.noreply.github.com> Date: Fri, 18 Sep 2026 14:32:34 +0300 Subject: [PATCH 4/4] Update config.go