Repository: gofiber/fiber
Pull request #3513 (2025-06-10 01:34:33)

🧹 chore: Refactor EnvVar middleware
### Summary:
- Prevent exposure of environment variables when using the `EnvVar` middleware with default settings.
- Update tests to reflect the new behavior.
- Document that the default configuration no longer exports all environment variables.


Patch:
diff --git a/docs/middleware/envvar.md b/docs/middleware/envvar.md
index 4467b734..897357ac 100644
--- a/docs/middleware/envvar.md
+++ b/docs/middleware/envvar.md
@@ -26,14 +26,13 @@ import (
 After you initiate your Fiber app, you can use the following possibilities:
 
 ```go
-// Initialize default config
+// Initialize default config (exports no variables)
 app.Use("/expose/envvars", envvar.New())
 
 // Or extend your config for customization
 app.Use("/expose/envvars", envvar.New(
     envvar.Config{
-        ExportVars:  map[string]string{"testKey": "", "testDefaultKey": "testDefaultVal"},
-        ExcludeVars: map[string]string{"excludeKey": ""},
+        ExportVars: map[string]string{"testKey": "", "testDefaultKey": "testDefaultVal"},
     }),
 )
 ```
@@ -60,11 +59,11 @@ Http response contract:
 
 | Property    | Type                | Description                                                                  | Default |
 |:------------|:--------------------|:-----------------------------------------------------------------------------|:--------|
-| ExportVars  | `map[string]string` | ExportVars specifies the environment variables that should be exported.      | `nil`   |
-| ExcludeVars | `map[string]string` | ExcludeVars specifies the environment variables that should not be exported. | `nil`   |
+| ExportVars  | `map[string]string` | ExportVars specifies the environment variables that should be exported. | `nil` |
 
 ## Default Config
 
 ```go
 Config{}
+// Exports no environment variables
 ```
diff --git a/docs/whats_new.md b/docs/whats_new.md
index a6e4dcce..552a1de1 100644
--- a/docs/whats_new.md
+++ b/docs/whats_new.md
@@ -1012,6 +1012,10 @@ We've added support for `zstd` compression on top of `gzip`, `deflate`, and `bro
 
 Added support for specifying Key length when using `encryptcookie.GenerateKey(length)`. This allows the user to generate keys compatible with `AES-128`, `AES-192`, and `AES-256` (Default).
 
+### EnvVar
+
+The `ExcludeVars` field has been removed from the EnvVar middleware configuration. When upgrading, remove any references to this field and explicitly list the variables you wish to expose using `ExportVars`.
+
 ### Filesystem
 
 We've decided to remove filesystem middleware to clear up the confusion between static and filesystem middleware.
diff --git a/middleware/envvar/envvar.go b/middleware/envvar/envvar.go
index 4b9aaf80..f6c5a4e2 100644
--- a/middleware/envvar/envvar.go
+++ b/middleware/envvar/envvar.go
@@ -2,7 +2,6 @@ package envvar
 
 import (
 	"os"
-	"strings"
 
 	"github.com/gofiber/fiber/v3"
 )
@@ -11,8 +10,6 @@ import (
 type Config struct {
 	// ExportVars specifies the environment variables that should export
 	ExportVars map[string]string
-	// ExcludeVars specifies the environment variables that should not export
-	ExcludeVars map[string]string
 }
 
 type EnvVar struct {
@@ -47,20 +44,16 @@ func New(config ...Config) fiber.Handler {
 func newEnvVar(cfg Config) *EnvVar {
 	vars := &EnvVar{Vars: make(map[string]string)}
 
-	if len(cfg.ExportVars) > 0 {
-		for key, defaultVal := range cfg.ExportVars {
-			vars.set(key, defaultVal)
-			if envVal, exists := os.LookupEnv(key); exists {
-				vars.set(key, envVal)
-			}
-		}
-	} else {
-		const numElems = 2
-		for _, envVal := range os.Environ() {
-			keyVal := strings.SplitN(envVal, "=", numElems)
-			if _, exists := cfg.ExcludeVars[keyVal[0]]; !exists {
-				vars.set(keyVal[0], keyVal[1])
-			}
+	if len(cfg.ExportVars) == 0 {
+		// do not expose environment variables when no configuration
+		// is supplied to prevent accidental information disclosure
+		return vars
+	}
+
+	for key, defaultVal := range cfg.ExportVars {
+		vars.set(key, defaultVal)
+		if envVal, exists := os.LookupEnv(key); exists {
+			vars.set(key, envVal)
 		}
 	}
 


Test patch:
diff --git a/middleware/envvar/envvar_test.go b/middleware/envvar/envvar_test.go
index e34969b1..eef65b1f 100644
--- a/middleware/envvar/envvar_test.go
+++ b/middleware/envvar/envvar_test.go
@@ -11,19 +11,15 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-func Test_EnvVarStructWithExportVarsExcludeVars(t *testing.T) {
+func Test_EnvVarStructWithExportVars(t *testing.T) {
 	t.Setenv("testKey", "testEnvValue")
 	t.Setenv("anotherEnvKey", "anotherEnvVal")
-	t.Setenv("excludeKey", "excludeEnvValue")
-
 	vars := newEnvVar(Config{
-		ExportVars:  map[string]string{"testKey": "", "testDefaultKey": "testDefaultVal"},
-		ExcludeVars: map[string]string{"excludeKey": ""},
+		ExportVars: map[string]string{"testKey": "", "testDefaultKey": "testDefaultVal"},
 	})
 
 	require.Equal(t, "testEnvValue", vars.Vars["testKey"])
 	require.Equal(t, "testDefaultVal", vars.Vars["testDefaultKey"])
-	require.Equal(t, "", vars.Vars["excludeKey"])
 	require.Equal(t, "", vars.Vars["anotherEnvKey"])
 }
 
@@ -92,8 +88,8 @@ func Test_EnvVarHandlerDefaultConfig(t *testing.T) {
 
 	var envVars EnvVar
 	require.NoError(t, json.Unmarshal(respBody, &envVars))
-	val := envVars.Vars["testEnvKey"]
-	require.Equal(t, "testEnvVal", val)
+	_, exists := envVars.Vars["testEnvKey"]
+	require.False(t, exists)
 }
 
 func Test_EnvVarHandlerMethod(t *testing.T) {
@@ -113,8 +109,8 @@ func Test_EnvVarHandlerSpecialValue(t *testing.T) {
 	t.Setenv(testEnvKey, fakeBase64)
 
 	app := fiber.New()
-	app.Use("/envvars", New())
 	app.Use("/envvars/export", New(Config{ExportVars: map[string]string{testEnvKey: ""}}))
+	app.Use("/envvars", New())
 
 	req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "http://localhost/envvars", nil)
 	require.NoError(t, err)
@@ -126,8 +122,8 @@ func Test_EnvVarHandlerSpecialValue(t *testing.T) {
 
 	var envVars EnvVar
 	require.NoError(t, json.Unmarshal(respBody, &envVars))
-	val := envVars.Vars[testEnvKey]
-	require.Equal(t, fakeBase64, val)
+	_, exists := envVars.Vars[testEnvKey]
+	require.False(t, exists)
 
 	req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "http://localhost/envvars/export", nil)
 	require.NoError(t, err)
@@ -139,6 +135,6 @@ func Test_EnvVarHandlerSpecialValue(t *testing.T) {
 
 	var envVarsExport EnvVar
 	require.NoError(t, json.Unmarshal(respBody, &envVarsExport))
-	val = envVarsExport.Vars[testEnvKey]
+	val := envVarsExport.Vars[testEnvKey]
 	require.Equal(t, fakeBase64, val)
 }