VYPR
High severityNVD Advisory· Published Feb 18, 2022· Updated Apr 23, 2025

Use of Hard-coded Cryptographic Key in Netmaker

CVE-2022-23650

Description

Netmaker is a platform for creating and managing virtual overlay networks using WireGuard. Prior to versions 0.8.5, 0.9.4, and 010.0, there is a hard-coded cryptographic key in the code base which can be exploited to run admin commands on a remote server if the exploiter know the address and username of the admin. This effects the server (netmaker) component, and not clients. This has been patched in Netmaker v0.8.5, v0.9.4, and v0.10.0. There are currently no known workarounds.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/gravitl/netmakerGo
< 0.8.50.8.5
github.com/gravitl/netmakerGo
>= 0.9.0, < 0.9.40.9.4

Affected products

1

Patches

2
e9bce264719f

Merge pull request #777 from gravitl/hotfix_v0.9.4

https://github.com/gravitl/netmakerdcarnsFeb 16, 2022via ghsa
4 files changed · +67 2
  • logic/jwts.go+19 1 modified
    @@ -5,11 +5,29 @@ import (
     	"time"
     
     	"github.com/golang-jwt/jwt/v4"
    +	"github.com/gravitl/netmaker/logger"
     	"github.com/gravitl/netmaker/models"
     	"github.com/gravitl/netmaker/servercfg"
     )
     
    -var jwtSecretKey = []byte("(BytesOverTheWire)")
    +var jwtSecretKey []byte
    +
    +// SetJWTSecret - sets the jwt secret on server startup
    +func SetJWTSecret() {
    +	currentSecret, jwtErr := FetchJWTSecret()
    +	if jwtErr != nil {
    +		newString, err := GenerateRandomString(64)
    +		if err != nil {
    +			logger.FatalLog("something went wrong when generating the auth secret")
    +		}
    +		jwtSecretKey = []byte(newString) // 512 bit random password
    +		if err := StoreJWTSecret(string(jwtSecretKey)); err != nil {
    +			logger.FatalLog("something went wrong when configuring JWT authentication")
    +		}
    +	} else {
    +		jwtSecretKey = []byte(currentSecret)
    +	}
    +}
     
     // CreateJWT func will used to create the JWT while signing in and signing out
     func CreateJWT(macaddress string, network string) (response string, err error) {
    
  • logic/serverconf.go+29 0 modified
    @@ -43,3 +43,32 @@ func FetchPrivKey(serverID string) (string, error) {
     func RemovePrivKey(serverID string) error {
     	return database.DeleteRecord(database.SERVERCONF_TABLE_NAME, serverID)
     }
    +
    +// FetchJWTSecret - fetches jwt secret from db
    +func FetchJWTSecret() (string, error) {
    +	var dbData string
    +	var err error
    +	var fetchedData = serverData{}
    +	dbData, err = database.FetchRecord(database.SERVERCONF_TABLE_NAME, "nm-jwt-secret")
    +	if err != nil {
    +		return "", err
    +	}
    +	err = json.Unmarshal([]byte(dbData), &fetchedData)
    +	if err != nil {
    +		return "", err
    +	}
    +	return fetchedData.PrivateKey, nil
    +}
    +
    +// StoreJWTSecret - stores server jwt secret if needed
    +func StoreJWTSecret(privateKey string) error {
    +	var newData = serverData{}
    +	var err error
    +	var data []byte
    +	newData.PrivateKey = privateKey
    +	data, err = json.Marshal(&newData)
    +	if err != nil {
    +		return err
    +	}
    +	return database.Insert("nm-jwt-secret", string(data), database.SERVERCONF_TABLE_NAME)
    +}
    
  • logic/util.go+18 1 modified
    @@ -2,8 +2,10 @@
     package logic
     
     import (
    +	crand "crypto/rand"
     	"encoding/base64"
     	"encoding/json"
    +	"math/big"
     	"math/rand"
     	"strconv"
     	"strings"
    @@ -278,7 +280,7 @@ func GetPeersList(networkName string, excludeRelayed bool, relayedNodeAddr strin
     
     // RandomString - returns a random string in a charset
     func RandomString(length int) string {
    -	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    +	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"
     
     	var seededRand *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))
     
    @@ -289,6 +291,21 @@ func RandomString(length int) string {
     	return string(b)
     }
     
    +// GenerateRandomString - generates random string of n length
    +func GenerateRandomString(n int) (string, error) {
    +	const chars = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
    +	ret := make([]byte, n)
    +	for i := range ret {
    +		num, err := crand.Int(crand.Reader, big.NewInt(int64(len(chars))))
    +		if err != nil {
    +			return "", err
    +		}
    +		ret[i] = chars[num.Int64()]
    +	}
    +
    +	return string(ret), nil
    +}
    +
     // == Private Methods ==
     
     func getNetworkEgressAndNodes(networkName string) ([]models.Node, []models.Node, error) {
    
  • main.go+1 0 modified
    @@ -41,6 +41,7 @@ func initialize() { // Client Mode Prereq Check
     		logger.FatalLog("Error connecting to database")
     	}
     	logger.Log(0, "database successfully connected")
    +	logic.SetJWTSecret()
     
     	var authProvider = auth.InitializeAuthProvider()
     	if authProvider != "" {
    
3d4f44ecfe8b

Merge pull request #770 from gravitl/hotfix_v0.10.0_jwt_data

https://github.com/gravitl/netmakerdcarnsFeb 15, 2022via ghsa
3 files changed · +52 2
  • logic/jwts.go+22 1 modified
    @@ -2,14 +2,29 @@ package logic
     
     import (
     	"errors"
    +	"fmt"
     	"time"
     
     	"github.com/golang-jwt/jwt/v4"
    +	"github.com/gravitl/netmaker/logger"
     	"github.com/gravitl/netmaker/models"
     	"github.com/gravitl/netmaker/servercfg"
     )
     
    -var jwtSecretKey = []byte("(BytesOverTheWire)")
    +var jwtSecretKey []byte
    +
    +// SetJWTSecret - sets the jwt secret on server startup
    +func SetJWTSecret() {
    +	currentSecret, jwtErr := FetchJWTSecret()
    +	if jwtErr != nil {
    +		jwtSecretKey = []byte(RandomString(64)) // 512 bit random password
    +		if err := StoreJWTSecret(string(jwtSecretKey)); err != nil {
    +			logger.FatalLog("something went wrong when configuring JWT authentication")
    +		}
    +	} else {
    +		jwtSecretKey = []byte(currentSecret)
    +	}
    +}
     
     // CreateJWT func will used to create the JWT while signing in and signing out
     func CreateJWT(uuid string, macAddress string, network string) (response string, err error) {
    @@ -19,6 +34,9 @@ func CreateJWT(uuid string, macAddress string, network string) (response string,
     		Network:    network,
     		MacAddress: macAddress,
     		StandardClaims: jwt.StandardClaims{
    +			Issuer:    "Netmaker",
    +			Subject:   fmt.Sprintf("node|%s", uuid),
    +			IssuedAt:  time.Now().Unix(),
     			ExpiresAt: expirationTime.Unix(),
     		},
     	}
    @@ -39,6 +57,9 @@ func CreateUserJWT(username string, networks []string, isadmin bool) (response s
     		Networks: networks,
     		IsAdmin:  isadmin,
     		StandardClaims: jwt.StandardClaims{
    +			Issuer:    "Netmaker",
    +			IssuedAt:  time.Now().Unix(),
    +			Subject:   fmt.Sprintf("user|%s", username),
     			ExpiresAt: expirationTime.Unix(),
     		},
     	}
    
  • logic/serverconf.go+29 0 modified
    @@ -43,3 +43,32 @@ func FetchPrivKey(serverID string) (string, error) {
     func RemovePrivKey(serverID string) error {
     	return database.DeleteRecord(database.SERVERCONF_TABLE_NAME, serverID)
     }
    +
    +// FetchJWTSecret - fetches jwt secret from db
    +func FetchJWTSecret() (string, error) {
    +	var dbData string
    +	var err error
    +	var fetchedData = serverData{}
    +	dbData, err = database.FetchRecord(database.SERVERCONF_TABLE_NAME, "nm-jwt-secret")
    +	if err != nil {
    +		return "", err
    +	}
    +	err = json.Unmarshal([]byte(dbData), &fetchedData)
    +	if err != nil {
    +		return "", err
    +	}
    +	return fetchedData.PrivateKey, nil
    +}
    +
    +// StoreJWTSecret - stores server jwt secret if needed
    +func StoreJWTSecret(privateKey string) error {
    +	var newData = serverData{}
    +	var err error
    +	var data []byte
    +	newData.PrivateKey = privateKey
    +	data, err = json.Marshal(&newData)
    +	if err != nil {
    +		return err
    +	}
    +	return database.Insert("nm-jwt-secret", string(data), database.SERVERCONF_TABLE_NAME)
    +}
    
  • main.go+1 1 modified
    @@ -40,7 +40,6 @@ func main() {
     
     func initialize() { // Client Mode Prereq Check
     	var err error
    -
     	if servercfg.GetNodeID() == "" {
     		logger.FatalLog("error: must set NODE_ID, currently blank")
     	}
    @@ -49,6 +48,7 @@ func initialize() { // Client Mode Prereq Check
     		logger.FatalLog("Error connecting to database")
     	}
     	logger.Log(0, "database successfully connected")
    +	logic.SetJWTSecret()
     
     	err = logic.TimerCheckpoint()
     	if err != nil {
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.