Skip to content

Commit 0d83a67

Browse files
fix(api): sanitize LectureHall sources.
In similar fashion to b995a23, we want to sanitize these values because they are used to execute commands in the worker and can be abused by admins or lecturers to run arbitrary commands
1 parent b995a23 commit 0d83a67

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

model/lecture_hall.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package model
22

3-
import "gorm.io/gorm"
3+
import (
4+
"fmt"
5+
"net/netip"
6+
"net/url"
7+
8+
"gorm.io/gorm"
9+
)
410

511
type LectureHall struct {
612
gorm.Model
@@ -65,3 +71,29 @@ func (l *LectureHall) ToDTO() *LectureHallDTO {
6571
ExternalURL: l.ExternalURL,
6672
}
6773
}
74+
75+
// BeforeSave returns an error if either source is invalid.
76+
func (l *LectureHall) BeforeSave(*gorm.DB) error {
77+
_, err := netip.ParseAddr(l.CameraIP)
78+
if err != nil {
79+
return fmt.Errorf("invalid camera IP address: %s", l.CameraIP)
80+
}
81+
u, err := url.Parse(l.CombIP)
82+
if err != nil {
83+
return fmt.Errorf("invalid comb URL: %s", u)
84+
}
85+
l.CombIP = u.String() // save parsed (and urlencoded) URL to database
86+
87+
u, err = url.Parse(l.CamIP)
88+
if err != nil {
89+
return fmt.Errorf("invalid cam URL: %s", u)
90+
}
91+
l.CamIP = u.String()
92+
93+
u, err = url.Parse(l.PresIP)
94+
if err != nil {
95+
return fmt.Errorf("invalid pres URL: %s", u)
96+
}
97+
l.PresIP = u.String()
98+
return nil
99+
}

model/lecture_hall_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,57 @@
11
package model
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestBeforeSaveLectureHall(t *testing.T) {
11+
cases := []struct {
12+
l LectureHall
13+
expected LectureHall
14+
wantErr bool
15+
}{
16+
{
17+
l: LectureHall{
18+
CameraIP: "not an ip",
19+
},
20+
wantErr: true,
21+
},
22+
{
23+
l: LectureHall{
24+
CameraIP: "127.0.0.almostanip",
25+
},
26+
expected: LectureHall{
27+
CameraIP: "",
28+
},
29+
wantErr: true,
30+
},
31+
{
32+
l: LectureHall{
33+
CameraIP: "127.0.0.1",
34+
CamIP: "somehost/malicious\" && stuff",
35+
},
36+
expected: LectureHall{
37+
CameraIP: "127.0.0.1",
38+
CamIP: "somehost/malicious%22%20&&%20stuff",
39+
},
40+
wantErr: false,
41+
},
42+
}
43+
44+
for _, tc := range cases {
45+
t.Run(fmt.Sprintf("BeforeSave(%+v)", tc.l), func(t *testing.T) {
46+
err := tc.l.BeforeSave(nil)
47+
if err != nil && !tc.wantErr {
48+
t.Errorf("BeforeCreateLectureHall(%+v): got error %v, want no error", tc.l, err)
49+
} else if err == nil && tc.wantErr {
50+
t.Errorf("BeforeCreateLectureHall(%+v): got no error, want error", tc.l)
51+
}
52+
if err == nil {
53+
assert.Equal(t, tc.expected, tc.l)
54+
}
55+
})
56+
}
57+
}

0 commit comments

Comments
 (0)