Skip to content

Commit e8e5ba6

Browse files
committed
Disallow unknown fields
Signed-off-by: David Gageot <david.gageot@docker.com>
1 parent 388ae8b commit e8e5ba6

2 files changed

Lines changed: 64 additions & 0 deletions

File tree

pkg/session/session.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package session
22

33
import (
4+
"bytes"
5+
"encoding/json"
46
"log/slog"
57
"os"
68
"slices"
@@ -217,6 +219,21 @@ type EvalCriteria struct {
217219
Setup string `json:"setup,omitempty"` // Optional sh script to run in the container before docker agent run --exec
218220
}
219221

222+
// UnmarshalJSON implements custom JSON unmarshaling for EvalCriteria that
223+
// rejects unknown fields. This ensures eval JSON files don't contain typos
224+
// or unsupported fields that would be silently ignored.
225+
func (e *EvalCriteria) UnmarshalJSON(data []byte) error {
226+
type evalCriteria EvalCriteria // alias to avoid infinite recursion
227+
var v evalCriteria
228+
dec := json.NewDecoder(bytes.NewReader(data))
229+
dec.DisallowUnknownFields()
230+
if err := dec.Decode(&v); err != nil {
231+
return err
232+
}
233+
*e = EvalCriteria(v)
234+
return nil
235+
}
236+
220237
// deepCopyMessage returns a deep copy of a session Message.
221238
// It copies the inner chat.Message's slice and pointer fields so that the
222239
// returned value shares no mutable state with the original.

pkg/session/session_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package session
22

33
import (
4+
"encoding/json"
45
"strings"
56
"testing"
67

@@ -292,6 +293,52 @@ func TestGetLastUserMessages(t *testing.T) {
292293
})
293294
}
294295

296+
func TestEvalCriteriaUnmarshalJSON(t *testing.T) {
297+
t.Parallel()
298+
299+
tests := []struct {
300+
name string
301+
input string
302+
want EvalCriteria
303+
wantErr bool
304+
}{
305+
{
306+
name: "valid fields",
307+
input: `{"relevance":["is correct"],"size":"M","setup":"echo hello","working_dir":"mydir"}`,
308+
want: EvalCriteria{
309+
Relevance: []string{"is correct"},
310+
Size: "M",
311+
Setup: "echo hello",
312+
WorkingDir: "mydir",
313+
},
314+
},
315+
{
316+
name: "empty object",
317+
input: `{}`,
318+
want: EvalCriteria{},
319+
},
320+
{
321+
name: "unknown field rejected",
322+
input: `{"relevance":[],"unknown_field":"value"}`,
323+
wantErr: true,
324+
},
325+
}
326+
327+
for _, tt := range tests {
328+
t.Run(tt.name, func(t *testing.T) {
329+
t.Parallel()
330+
var got EvalCriteria
331+
err := json.Unmarshal([]byte(tt.input), &got)
332+
if tt.wantErr {
333+
require.Error(t, err)
334+
return
335+
}
336+
require.NoError(t, err)
337+
assert.Equal(t, tt.want, got)
338+
})
339+
}
340+
}
341+
295342
func TestTransferTaskPromptExcludesParents(t *testing.T) {
296343
t.Parallel()
297344

0 commit comments

Comments
 (0)