Skip to content

Fix documented security risk around potential risk to inject messages into other user's thread #78

@kristofer-tdy

Description

@kristofer-tdy

The reference implementation contains a TODO that clearly and correctly identifies a security problem. I don't think that any reference implementation, specifically not one that takes so much care to secure the infrastructure in Azure like this one, should have a known unfixed security problem. It's time to fix it and implement a state store to connect the user's and the conversation with a threadId in Azure AI Foundry.

In file ChatController.cs, you'll find this:

    // TODO: [security] Do not trust client to provide threadId. Instead map current user to their active threadid in your application's own state store.
    // Without this security control in place, a user can inject messages into another user's thread.
    [HttpPost("{threadId}")]
    public async Task<IActionResult> Completions([FromRoute] string threadId, [FromBody] string prompt)
    {
        if (string.IsNullOrWhiteSpace(prompt))
            throw new ArgumentException("Prompt cannot be null, empty, or whitespace.", nameof(prompt));

        _logger.LogDebug("Prompt received {Prompt}", prompt);
        var _config = _options.CurrentValue;

        PersistentThreadMessage message = await _client.Messages.CreateMessageAsync(
            threadId,
            MessageRole.User,
            prompt);

        ThreadRun run = await _client.Runs.CreateRunAsync(threadId, _config.AIAgentId);

        while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress || run.Status == RunStatus.RequiresAction)
        {
            await Task.Delay(TimeSpan.FromMilliseconds(500));
            run = (await _client.Runs.GetRunAsync(threadId, run.Id)).Value;
        }

        Pageable<PersistentThreadMessage> messages = _client.Messages.GetMessages(
            threadId: threadId, order: ListSortOrder.Ascending);

        var fullText =
            messages
                .Where(m => m.Role == MessageRole.Agent)
                .SelectMany(m => m.ContentItems.OfType<MessageTextContent>())
                .Last().Text;

        return Ok(new { data = fullText });
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions