Check the JWT secret length (#15939)

<!-- Thanks for sending a PR! Before submitting:

1. If this is your first PR, check out our contribution guide here
https://docs.prylabs.network/docs/contribute/contribution-guidelines
You will then need to sign our Contributor License Agreement (CLA),
which will show up as a comment from a bot in this pull request after
you open it. We cannot review code without a signed CLA.
2. Please file an associated tracking issue if this pull request is
non-trivial and requires context for our team to understand. All
features and most bug fixes should have
an associated issue with a design discussed and decided upon. Small bug
   fixes and documentation improvements don't need issues.
3. New features and bug fixes must have tests. Documentation may need to
be updated. If you're unsure what to update, send the PR, and we'll
discuss
   in review.
4. Note that PRs updating dependencies and new Go versions are not
accepted.
   Please file an issue instead.
5. A changelog entry is required for user facing issues.
-->

**What type of PR is this?**
 Bug fix

**What does this PR do? Why is it needed?**

Previously, JWT secrets longer than 256 bits could cause client
compatibility issues. For example, Prysm would accept longer secrets
while Geth strictly requires exactly 32 bytes, causing Geth startup
failures when using the same secret file.

This change enforces the Engine API specification requirement that JWT
secrets must be exactly 256 bits (32 bytes), ensuring consistent
behavior across different client implementations.

**Which issues(s) does this PR fix?**

Fixes #

**Other notes for review**

**Acknowledgements**

- [x] I have read
[CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md).
- [x] I have included a uniquely named [changelog fragment
file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd).
- [x] I have added a description to this PR with sufficient context for
reviewers to understand this PR.

---------

Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
This commit is contained in:
Muzry
2025-11-22 05:51:03 +08:00
committed by GitHub
parent c093283b1b
commit 55e2001a0b
3 changed files with 18 additions and 4 deletions

View File

@@ -0,0 +1,2 @@
### Fixed
- Check the JWT secret length is exactly 256 bits (32 bytes) as per Engine API specification

View File

@@ -41,7 +41,7 @@ func FlagOptions(c *cli.Context) ([]execution.Option, error) {
//
// The secret must be stored as a hex-encoded string within a file in the filesystem.
// If the --jwt-secret flag is provided to Prysm, but the file cannot be read, or does not contain a hex-encoded
// key of at least 256 bits, the client should treat this as an error and abort the startup.
// key of 256 bits, the client should treat this as an error and abort the startup.
func parseJWTSecretFromFile(c *cli.Context) ([]byte, error) {
jwtSecretFile := c.String(flags.ExecutionJWTSecretFlag.Name)
if jwtSecretFile == "" {
@@ -59,8 +59,8 @@ func parseJWTSecretFromFile(c *cli.Context) ([]byte, error) {
if err != nil {
return nil, err
}
if len(secret) < 32 {
return nil, errors.New("provided JWT secret should be a hex string of at least 32 bytes")
if len(secret) != 32 {
return nil, errors.New("provided JWT secret should be a hex string of 32 bytes")
}
log.Infof("Finished reading JWT secret from %s", jwtSecretFile)
return secret, nil

View File

@@ -63,7 +63,19 @@ func Test_parseJWTSecretFromFile(t *testing.T) {
set.String(flags.ExecutionJWTSecretFlag.Name, fullPath, "")
ctx := cli.NewContext(&app, set, nil)
_, err := parseJWTSecretFromFile(ctx)
require.ErrorContains(t, "should be a hex string of at least 32 bytes", err)
require.ErrorContains(t, "should be a hex string of 32 bytes", err)
})
t.Run("more than 32 bytes", func(t *testing.T) {
app := cli.App{}
set := flag.NewFlagSet("test", 0)
fullPath := filepath.Join(t.TempDir(), "foohex")
secret := bytesutil.PadTo([]byte("foo"), 33)
hexData := fmt.Sprintf("%#x", secret)
require.NoError(t, file.WriteFile(fullPath, []byte(hexData)))
set.String(flags.ExecutionJWTSecretFlag.Name, fullPath, "")
ctx := cli.NewContext(&app, set, nil)
_, err := parseJWTSecretFromFile(ctx)
require.ErrorContains(t, "should be a hex string of 32 bytes", err)
})
t.Run("bad data", func(t *testing.T) {
app := cli.App{}