From c6e064f4b1e0cf92661717e3ec5b72facbde909e Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Wed, 25 Jan 2023 23:45:31 -0600 Subject: [PATCH] Limit size on justifications (#177) This isn't a perfect solution because there's some error during JSON marshalling, but I don't think we should take the overhead of marshalling the JSON. Fixes GH-170 --- pkg/justification/processor.go | 26 +++++++++++++++++++++++--- pkg/justification/processor_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/pkg/justification/processor.go b/pkg/justification/processor.go index d70393d3..57016d1f 100644 --- a/pkg/justification/processor.go +++ b/pkg/justification/processor.go @@ -133,13 +133,16 @@ func (p *Processor) getPrimarySigner(ctx context.Context) (*signerWithID, error) } // TODO: Each category should have its own validator struct, with a shared interface. -func (p *Processor) runValidations(request *jvspb.CreateJustificationRequest) error { - if len(request.Justifications) < 1 { +func (p *Processor) runValidations(req *jvspb.CreateJustificationRequest) error { + if len(req.Justifications) < 1 { return fmt.Errorf("no justifications specified") } + var justificationsLength int var err *multierror.Error - for _, j := range request.Justifications { + for _, j := range req.Justifications { + justificationsLength += len(j.Category) + len(j.Value) + switch j.Category { case "explanation": if j.Value == "" { @@ -149,6 +152,23 @@ func (p *Processor) runValidations(request *jvspb.CreateJustificationRequest) er err = multierror.Append(err, fmt.Errorf("unexpected justification %v unrecognized", j)) } } + + // This isn't perfect, but it's the easiest place to get "close" to limiting + // the size. + if got, max := justificationsLength, 4_000; got > max { + err = multierror.Append(err, fmt.Errorf("justification size (%d bytes) must be less than %d bytes", + got, max)) + } + + var audiencesLength int + for _, v := range req.Audiences { + audiencesLength += len(v) + } + if got, max := audiencesLength, 1_000; got > max { + err = multierror.Append(err, fmt.Errorf("audiences size (%d bytes) must be less than %d bytes", + got, max)) + } + return err.ErrorOrNil() } diff --git a/pkg/justification/processor_test.go b/pkg/justification/processor_test.go index 1ca26c2c..83b168dd 100644 --- a/pkg/justification/processor_test.go +++ b/pkg/justification/processor_test.go @@ -22,6 +22,7 @@ import ( "crypto/x509" "encoding/pem" "reflect" + "strings" "testing" "time" @@ -127,6 +128,33 @@ func TestCreateToken(t *testing.T) { }, wantErr: "requested ttl (10h) cannot be greater than max tll (1h)", }, + { + name: "justifications_too_long", + request: &jvspb.CreateJustificationRequest{ + Justifications: []*jvspb.Justification{ + { + Category: "explanation", + Value: strings.Repeat("test", 4_000), + }, + }, + Ttl: durationpb.New(10 * time.Hour), + }, + wantErr: "must be less than 4000 bytes", + }, + { + name: "audiences_too_long", + request: &jvspb.CreateJustificationRequest{ + Justifications: []*jvspb.Justification{ + { + Category: "explanation", + Value: "test", + }, + }, + Audiences: []string{strings.Repeat("test", 1_000)}, + Ttl: durationpb.New(10 * time.Hour), + }, + wantErr: "must be less than 1000 bytes", + }, } for _, tc := range tests {