Skip to content

Commit b3a9dc0

Browse files
authored
Merge pull request #9 from guillaumerose/security1
Refuse to change hosts with suffixes not in the allowed list
2 parents 377f6a8 + 1cce8dc commit b3a9dc0

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

pkg/hosts/hosts.go

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,51 @@ package hosts
22

33
import (
44
"fmt"
5+
"regexp"
56
"sort"
67
"strings"
78

89
"github.com/goodhosts/hostsfile"
910
)
1011

12+
const (
13+
// source https://github.com/kubernetes/apimachinery/blob/603e04655e9f537eb01238cdbce4891f832a4f27/pkg/util/validation/validation.go#L208
14+
dns1123SubdomainRegexp = `[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*`
15+
clusterDomain = ".crc.testing"
16+
appsDomain = ".apps-crc.testing"
17+
)
18+
19+
var (
20+
clusterRegexp = regexp.MustCompile("^" + dns1123SubdomainRegexp + regexp.QuoteMeta(clusterDomain) + "$")
21+
appRegexp = regexp.MustCompile("^" + dns1123SubdomainRegexp + regexp.QuoteMeta(appsDomain) + "$")
22+
)
23+
1124
type Hosts struct {
12-
File *hostsfile.Hosts
25+
File *hostsfile.Hosts
26+
HostFilter func(string) bool
1327
}
1428

1529
func New() (*Hosts, error) {
1630
file, err := hostsfile.NewHosts()
1731
if err != nil {
1832
return nil, err
1933
}
34+
2035
return &Hosts{
21-
File: &file,
36+
File: &file,
37+
HostFilter: defaultFilter,
2238
}, nil
2339
}
2440

41+
func defaultFilter(s string) bool {
42+
return clusterRegexp.MatchString(s) || appRegexp.MatchString(s)
43+
}
44+
2545
func (h *Hosts) Add(ip string, hosts []string) error {
46+
if err := h.verifyHosts(hosts); err != nil {
47+
return err
48+
}
49+
2650
if err := h.checkIsWritable(); err != nil {
2751
return err
2852
}
@@ -46,6 +70,10 @@ func (h *Hosts) Add(ip string, hosts []string) error {
4670
}
4771

4872
func (h *Hosts) Remove(hosts []string) error {
73+
if err := h.verifyHosts(hosts); err != nil {
74+
return err
75+
}
76+
4977
if err := h.checkIsWritable(); err != nil {
5078
return err
5179
}
@@ -69,6 +97,10 @@ func (h *Hosts) Remove(hosts []string) error {
6997
}
7098

7199
func (h *Hosts) Clean(rawSuffixes []string) error {
100+
if err := h.verifyHosts(rawSuffixes); err != nil {
101+
return err
102+
}
103+
72104
if err := h.checkIsWritable(); err != nil {
73105
return err
74106
}
@@ -109,5 +141,18 @@ func (h *Hosts) checkIsWritable() error {
109141
}
110142

111143
func (h *Hosts) Contains(ip, host string) bool {
144+
if err := h.verifyHosts([]string{host}); err != nil {
145+
return false
146+
}
147+
112148
return h.File.Has(ip, host)
113149
}
150+
151+
func (h *Hosts) verifyHosts(hosts []string) error {
152+
for _, host := range hosts {
153+
if !h.HostFilter(host) {
154+
return fmt.Errorf("input %s rejected", host)
155+
}
156+
}
157+
return nil
158+
}

pkg/hosts/hosts_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,37 @@ func TestContains(t *testing.T) {
7878
assert.False(t, host.Contains("127.0.0.1", "entry1.suffix2"))
7979
}
8080

81+
func TestSuffixFilter(t *testing.T) {
82+
dir, err := ioutil.TempDir("", "hosts")
83+
assert.NoError(t, err)
84+
defer os.RemoveAll(dir)
85+
86+
hostsFile := filepath.Join(dir, "hosts")
87+
assert.NoError(t, ioutil.WriteFile(hostsFile, []byte(`127.0.0.1 localhost`), 0600))
88+
89+
file, err := hostsfile.NewCustomHosts(hostsFile)
90+
assert.NoError(t, err)
91+
host := Hosts{
92+
File: &file,
93+
HostFilter: defaultFilter,
94+
}
95+
96+
assert.NoError(t, host.Add("127.0.0.1", []string{"entry1.crc.testing"}))
97+
assert.NoError(t, host.Add("127.0.0.1", []string{"entry2.nested.crc.testing"}))
98+
assert.Error(t, host.Add("127.0.0.1", []string{"evildomain #apps.crc.testing"}))
99+
assert.Error(t, host.Add("127.0.0.1", []string{"host.poison"}))
100+
assert.Error(t, host.Add("127.0.0.1", []string{"CAPITAL.crc.testing"}))
101+
assert.Error(t, host.Remove([]string{"localhost"}))
102+
}
103+
81104
func hosts(t *testing.T, hostsFile string) Hosts {
82105
file, err := hostsfile.NewCustomHosts(hostsFile)
83106
assert.NoError(t, err)
84107
return Hosts{
85108
File: &file,
109+
HostFilter: func(s string) bool {
110+
return true
111+
},
86112
}
87113
}
88114

0 commit comments

Comments
 (0)