Skip to content

[MTP Core Analysis] JSON-RPC request deserialization coerces invalid runIds to Guid.Empty #8423

@Evangelink

Description

@Evangelink

Summary

Both JSON-RPC deserializers accept any runId string and silently coerce invalid values to Guid.Empty instead of rejecting the request.

Evidence

  • src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/Json/Json.cs:486-511
    string runId = json.Bind<string>(jsonElement, JsonRpcStrings.RunId);
    _ = Guid.TryParse(runId, out Guid result);
    ...
    return new DiscoverRequestArgs(
        RunId: result,
        ...);
    and the same pattern for RunRequestArgs.
  • src/Platform/Microsoft.Testing.Platform/ServerMode/JsonRpc/SerializerUtilities.cs:588-610
    _ = Guid.TryParse(GetRequiredPropertyFromJson<string>(properties, JsonRpcStrings.RunId), out Guid runId);
    ...
    return new DiscoverRequestArgs(runId, tests, filter);
    and the same pattern for RunRequestArgs.
  • src/Platform/Microsoft.Testing.Platform/Hosts/ServerTestHost.cs:477-531
    uses args.RunId to create the per-request consumer and to emit completion/update messages back to the client.

Why this is a real issue

A malformed client payload such as {"runId":"not-a-guid"} is not rejected as an invalid request. Instead, MTP creates the request with Guid.Empty.

That means request correlation continues with a synthetic run id the client never asked for. Updates and completion notifications are then emitted under Guid.Empty, which makes protocol debugging harder and can collapse multiple malformed requests onto the same identifier.

Suggested resolution

Treat an unparseable runId as a protocol error and reject the request during deserialization (or at least during request validation) instead of converting it to Guid.Empty. Add tests for invalid runId values on both serializer implementations.

Related issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/mtpMicrosoft.Testing.Platform core library.type/automationCreated or maintained by an agentic workflow.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions