Skip to content

Commit 2c01a2e

Browse files
authored
Validate content type header parameter (veraison#176)
Signed-off-by: qmuntal <[email protected]>
1 parent e7ac36d commit 2c01a2e

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

headers.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"math/big"
7+
"strings"
78

89
"github.com/fxamacker/cbor/v2"
910
)
@@ -471,9 +472,24 @@ func validateHeaderParameters(h map[any]any, protected bool) error {
471472
return fmt.Errorf("header parameter: crit: %w", err)
472473
}
473474
case HeaderLabelContentType:
474-
if !canTstr(value) && !canUint(value) {
475+
is_tstr := canTstr(value)
476+
if !is_tstr && !canUint(value) {
475477
return errors.New("header parameter: content type: require tstr / uint type")
476478
}
479+
if is_tstr {
480+
v := value.(string)
481+
if len(v) == 0 {
482+
return errors.New("header parameter: content type: require non-empty string")
483+
}
484+
if v[0] == ' ' || v[len(v)-1] == ' ' {
485+
return errors.New("header parameter: content type: require no leading/trailing whitespace")
486+
}
487+
// Basic check that the content type is of form type/subtype.
488+
// We don't check the precise definition though (RFC 6838 Section 4.2).
489+
if strings.Count(v, "/") != 1 {
490+
return errors.New("header parameter: content type: require text of form type/subtype")
491+
}
492+
}
477493
case HeaderLabelKeyID:
478494
if !canBstr(value) {
479495
return errors.New("header parameter: kid: require bstr type")

headers_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,41 @@ func TestProtectedHeader_MarshalCBOR(t *testing.T) {
210210
},
211211
wantErr: "protected header: header parameter: Countersignature version 2: not allowed",
212212
},
213+
{
214+
name: "content type empty",
215+
h: ProtectedHeader{
216+
HeaderLabelContentType: "",
217+
},
218+
wantErr: "protected header: header parameter: content type: require non-empty string",
219+
},
220+
{
221+
name: "content type leading space",
222+
h: ProtectedHeader{
223+
HeaderLabelContentType: " a/b",
224+
},
225+
wantErr: "protected header: header parameter: content type: require no leading/trailing whitespace",
226+
},
227+
{
228+
name: "content type trailing space",
229+
h: ProtectedHeader{
230+
HeaderLabelContentType: "a/b ",
231+
},
232+
wantErr: "protected header: header parameter: content type: require no leading/trailing whitespace",
233+
},
234+
{
235+
name: "content type no slash",
236+
h: ProtectedHeader{
237+
HeaderLabelContentType: "ab",
238+
},
239+
wantErr: "protected header: header parameter: content type: require text of form type/subtype",
240+
},
241+
{
242+
name: "content type too many slashes",
243+
h: ProtectedHeader{
244+
HeaderLabelContentType: "a/b/c",
245+
},
246+
wantErr: "protected header: header parameter: content type: require text of form type/subtype",
247+
},
213248
}
214249
for _, tt := range tests {
215250
t.Run(tt.name, func(t *testing.T) {

0 commit comments

Comments
 (0)