Skip to content

Commit 10fb76f

Browse files
committed
fix: nil pointer dereference in ReportTask
1 parent 38755e2 commit 10fb76f

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

coderd/mcp/mcp.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,17 @@ func (s *Server) RegisterTools(client *codersdk.Client) error {
7979
return xerrors.Errorf("failed to initialize tool dependencies: %w", err)
8080
}
8181

82-
// Register all available tools
82+
// Register all available tools, but exclude tools that require dependencies not available in the
83+
// remote MCP context
8384
for _, tool := range toolsdk.All {
85+
// Skip ReportTask tool in MCP context since we don't have a task reporter configured
86+
// This prevents the nil pointer dereference panic
87+
if tool.Name == toolsdk.ToolNameReportTask {
88+
continue
89+
}
90+
8491
s.mcpServer.AddTools(mcpFromSDK(tool, toolDeps))
8592
}
86-
8793
return nil
8894
}
8995

codersdk/toolsdk/toolsdk.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ ONLY report an "idle" or "failure" state if you have FULLY completed the task.
253253
if len(args.Summary) > 160 {
254254
return codersdk.Response{}, xerrors.New("summary must be less than 160 characters")
255255
}
256+
// Check if task reporting is available to prevent nil pointer dereference
257+
if deps.report == nil {
258+
return codersdk.Response{}, xerrors.New("task reporting not available. Please ensure a task reporter is configured.")
259+
}
256260
err := deps.report(args)
257261
if err != nil {
258262
return codersdk.Response{}, err

codersdk/toolsdk/toolsdk_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,3 +686,64 @@ func TestMain(m *testing.M) {
686686

687687
os.Exit(code)
688688
}
689+
690+
func TestReportTaskNilPointerDeref(t *testing.T) {
691+
t.Parallel()
692+
693+
// Create deps without a task reporter (simulating MCP server scenario)
694+
client, _ := coderdtest.NewWithDatabase(t, nil) // Use a proper test client
695+
deps, err := toolsdk.NewDeps(client)
696+
require.NoError(t, err)
697+
698+
// Prepare test arguments
699+
args := toolsdk.ReportTaskArgs{
700+
Summary: "Test task",
701+
Link: "https://example.com",
702+
State: string(codersdk.WorkspaceAppStatusStateWorking),
703+
}
704+
705+
// This should panic with nil pointer dereference if the bug is present
706+
ctx := t.Context()
707+
708+
// Attempt to call the handler - this should cause the panic described in the issue
709+
_, err = toolsdk.ReportTask.Handler(ctx, deps, args)
710+
711+
// We expect an error, not a panic
712+
require.Error(t, err)
713+
require.Contains(t, err.Error(), "task reporting not available")
714+
}
715+
716+
func TestReportTaskWithReporter(t *testing.T) {
717+
t.Parallel()
718+
719+
// Create deps with a task reporter
720+
client, _ := coderdtest.NewWithDatabase(t, nil) // Use a proper test client
721+
722+
called := false
723+
reporter := func(args toolsdk.ReportTaskArgs) error {
724+
called = true
725+
require.Equal(t, "Test task", args.Summary)
726+
require.Equal(t, "https://example.com", args.Link)
727+
require.Equal(t, string(codersdk.WorkspaceAppStatusStateWorking), args.State)
728+
return nil
729+
}
730+
731+
deps, err := toolsdk.NewDeps(client, toolsdk.WithTaskReporter(reporter))
732+
require.NoError(t, err)
733+
734+
// Prepare test arguments
735+
args := toolsdk.ReportTaskArgs{
736+
Summary: "Test task",
737+
Link: "https://example.com",
738+
State: string(codersdk.WorkspaceAppStatusStateWorking),
739+
}
740+
741+
// This should work correctly
742+
ctx := t.Context()
743+
result, err := toolsdk.ReportTask.Handler(ctx, deps, args)
744+
require.NoError(t, err)
745+
require.True(t, called)
746+
747+
// Verify response
748+
require.Equal(t, "Thanks for reporting!", result.Message)
749+
}

0 commit comments

Comments
 (0)