Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/pkg/envutil/envutil.go
2610 views
1
// SPDX-FileCopyrightText: Copyright The Lima Authors
2
// SPDX-License-Identifier: Apache-2.0
3
4
package envutil
5
6
import (
7
"fmt"
8
"os"
9
"regexp"
10
"slices"
11
"strings"
12
13
"github.com/sirupsen/logrus"
14
)
15
16
// defaultBlockList contains environment variables that should not be propagated by default.
17
var defaultBlockList = []string{
18
"BASH*",
19
"DISPLAY",
20
"DYLD_*",
21
"EUID",
22
"FPATH",
23
"GID",
24
"GROUP",
25
"HOME",
26
"HOSTNAME",
27
"LD_*",
28
"LOGNAME",
29
"OLDPWD",
30
"PATH",
31
"PWD",
32
"SHELL",
33
"SHLVL",
34
"SSH_*",
35
"TERM",
36
"TERMINFO",
37
"TMPDIR",
38
"UID",
39
"USER",
40
"XAUTHORITY",
41
"XDG_*",
42
"ZDOTDIR",
43
"ZSH*",
44
"_*", // Variables starting with underscore are typically internal
45
}
46
47
func validatePattern(pattern string) error {
48
invalidChar := regexp.MustCompile(`([^a-zA-Z0-9_*])`)
49
if matches := invalidChar.FindStringSubmatch(pattern); matches != nil {
50
invalidCharacter := matches[1]
51
pos := strings.Index(pattern, invalidCharacter)
52
return fmt.Errorf("pattern %q contains invalid character %q at position %d",
53
pattern, invalidCharacter, pos)
54
}
55
return nil
56
}
57
58
// getBlockList returns the list of environment variable patterns to be blocked.
59
func getBlockList() []string {
60
blockEnv := os.Getenv("LIMA_SHELLENV_BLOCK")
61
if blockEnv == "" {
62
return defaultBlockList
63
}
64
65
shouldAppend := strings.HasPrefix(blockEnv, "+")
66
patterns := parseEnvList(strings.TrimPrefix(blockEnv, "+"))
67
68
for _, pattern := range patterns {
69
if err := validatePattern(pattern); err != nil {
70
logrus.Fatalf("Invalid LIMA_SHELLENV_BLOCK pattern: %v", err)
71
}
72
}
73
74
if shouldAppend {
75
return slices.Concat(defaultBlockList, patterns)
76
}
77
return patterns
78
}
79
80
// getAllowList returns the list of environment variable patterns to be allowed.
81
func getAllowList() []string {
82
allowEnv := os.Getenv("LIMA_SHELLENV_ALLOW")
83
if allowEnv == "" {
84
return nil
85
}
86
87
patterns := parseEnvList(allowEnv)
88
89
for _, pattern := range patterns {
90
if err := validatePattern(pattern); err != nil {
91
logrus.Fatalf("Invalid LIMA_SHELLENV_ALLOW pattern: %v", err)
92
}
93
}
94
95
return patterns
96
}
97
98
func parseEnvList(envList string) []string {
99
parts := strings.Split(envList, ",")
100
result := make([]string, 0, len(parts))
101
for _, part := range parts {
102
if trimmed := strings.TrimSpace(part); trimmed != "" {
103
result = append(result, trimmed)
104
}
105
}
106
107
return result
108
}
109
110
func matchesPattern(name, pattern string) bool {
111
if pattern == name {
112
return true
113
}
114
115
regexPattern := strings.ReplaceAll(pattern, "*", ".*")
116
regexPattern = "^" + regexPattern + "$"
117
118
match, err := regexp.MatchString(regexPattern, name)
119
if err != nil {
120
return false
121
}
122
return match
123
}
124
125
func matchesAnyPattern(name string, patterns []string) bool {
126
return slices.ContainsFunc(patterns, func(pattern string) bool {
127
return matchesPattern(name, pattern)
128
})
129
}
130
131
// FilterEnvironment filters environment variables based on configuration from environment variables.
132
// It returns a slice of environment variables that are not blocked by the current configuration.
133
// The filtering is controlled by LIMA_SHELLENV_BLOCK and LIMA_SHELLENV_ALLOW environment variables.
134
func FilterEnvironment() []string {
135
return filterEnvironmentWithLists(
136
os.Environ(),
137
getAllowList(),
138
getBlockList(),
139
)
140
}
141
142
func filterEnvironmentWithLists(env, allowList, blockList []string) []string {
143
var filtered []string
144
145
for _, envVar := range env {
146
parts := strings.SplitN(envVar, "=", 2)
147
if len(parts) != 2 {
148
continue
149
}
150
151
name := parts[0]
152
153
if len(allowList) > 0 && matchesAnyPattern(name, allowList) {
154
filtered = append(filtered, envVar)
155
continue
156
}
157
158
if matchesAnyPattern(name, blockList) {
159
logrus.Debugf("Blocked env variable %q", name)
160
continue
161
}
162
163
filtered = append(filtered, envVar)
164
}
165
166
return filtered
167
}
168
169
// GetDefaultBlockList returns a copy of the default block list.
170
func GetDefaultBlockList() []string {
171
return slices.Clone(defaultBlockList)
172
}
173
174