Skip to content

Commit d9a050c

Browse files
committed
[TT-16337] prevent use of special characters in policyID
1 parent e9c7559 commit d9a050c

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

gateway/api.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"net/url"
4040
"os"
4141
"path/filepath"
42+
"regexp"
4243
"sort"
4344
"strconv"
4445
"strings"
@@ -80,6 +81,7 @@ const (
8081

8182
var (
8283
ErrRequestMalformed = errors.New("request malformed")
84+
validPolicyIDRegex = regexp.MustCompile(`^[a-zA-Z0-9.\-_~]+$`)
8385
)
8486

8587
// apiModifyKeySuccess represents when a Key modification was successful
@@ -1110,6 +1112,11 @@ func (gw *Gateway) handleAddOrUpdatePolicy(polID string, r *http.Request) (inter
11101112
return apiError("Request malformed"), http.StatusBadRequest
11111113
}
11121114

1115+
if newPol.ID != "" && !isValidPolicyID(newPol.ID) {
1116+
log.WithField("id", newPol.ID).Error("Policy ID contains invalid characters")
1117+
return apiError("Invalid Policy ID in body. Allowed characters: a-z, A-Z, 0-9, ., _, -"), http.StatusBadRequest
1118+
}
1119+
11131120
if polID != "" && newPol.ID != polID && r.Method == http.MethodPut {
11141121
log.Error("PUT operation on different IDs")
11151122
return apiError("Request ID does not match that in policy! For Update operations these must match."), http.StatusBadRequest
@@ -1555,6 +1562,12 @@ func (gw *Gateway) handleDeleteAPI(apiID string) (interface{}, int) {
15551562
func (gw *Gateway) polHandler(w http.ResponseWriter, r *http.Request) {
15561563
polID := mux.Vars(r)["polID"]
15571564

1565+
if polID != "" && !isValidPolicyID(polID) {
1566+
log.WithField("id", polID).Error("Policy ID contains invalid characters")
1567+
doJSONWrite(w, http.StatusBadRequest, apiError("Invalid Policy ID. Allowed characters: a-z, A-Z, 0-9, ., _, -"))
1568+
return
1569+
}
1570+
15581571
var obj interface{}
15591572
var code int
15601573

@@ -1589,6 +1602,13 @@ func (gw *Gateway) polHandler(w http.ResponseWriter, r *http.Request) {
15891602
doJSONWrite(w, code, obj)
15901603
}
15911604

1605+
func isValidPolicyID(id string) bool {
1606+
if id == "" {
1607+
return true
1608+
}
1609+
return validPolicyIDRegex.MatchString(id)
1610+
}
1611+
15921612
func (gw *Gateway) apiHandler(w http.ResponseWriter, r *http.Request) {
15931613
apiID := mux.Vars(r)["apiID"]
15941614

gateway/api_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,51 @@ func TestPolicyAPI(t *testing.T) {
173173
Code: http.StatusOK,
174174
})
175175
})
176+
177+
t.Run("fails if ID contains invalid characters", func(t *testing.T) {
178+
invalidURLID := "invalid@id"
179+
180+
ts.Run(t, test.TestCase{
181+
Path: "/tyk/policies/" + invalidURLID,
182+
Method: http.MethodGet,
183+
AdminAuth: true,
184+
Code: http.StatusBadRequest,
185+
BodyMatch: `Invalid Policy ID`,
186+
})
187+
188+
invalidBodyPol := user.Policy{
189+
ID: "invalid/id",
190+
Rate: 100,
191+
Per: 1,
192+
OrgID: "54de205930c55e15bd000001",
193+
AccessRights: make(map[string]user.AccessDefinition),
194+
MetaData: nil,
195+
Tags: nil,
196+
}
197+
198+
ts.Run(t, test.TestCase{
199+
Path: "/tyk/policies",
200+
Method: http.MethodPost,
201+
AdminAuth: true,
202+
Data: serializePolicy(t, invalidBodyPol),
203+
Code: http.StatusBadRequest,
204+
BodyMatch: `Invalid Policy ID in body`,
205+
})
206+
207+
validID := "valid-id"
208+
ts.Gw.policiesMu.Lock()
209+
ts.Gw.policiesByID[validID] = invalidBodyPol
210+
ts.Gw.policiesMu.Unlock()
211+
212+
ts.Run(t, test.TestCase{
213+
Path: "/tyk/policies/" + validID,
214+
Method: http.MethodPut,
215+
AdminAuth: true,
216+
Data: serializePolicy(t, invalidBodyPol),
217+
Code: http.StatusBadRequest,
218+
BodyMatch: `Invalid Policy ID in body`,
219+
})
220+
})
176221
}
177222

178223
func serializePolicy(t *testing.T, pol user.Policy) string {

0 commit comments

Comments
 (0)