Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

WebSocket Copilot Target

The WebSocketCopilotTarget is an alternative to the PlaywrightCopilotTarget that is designed to be more reliable by minimizing dependence on browser automation. Instead of driving the Copilot UI, it communicates directly with Copilot over a WebSocket connection.

By default, this target uses automated authentication which requires:

  • COPILOT_USERNAME and COPILOT_PASSWORD environment variables

  • Playwright installed: pip install playwright && playwright install chromium

Some environments are not suited for automated authentication (e.g. they have security policies with retrieving tokens or have MFA). For interactive authentication compatible with MFA and Conditional Access, see Browser Session Authentication. To provide a token manually, see Alternative Authentication.

Basic Usage with PromptSendingAttack

The simplest way to interact with the WebSocketCopilotTarget is through the PromptSendingAttack class.


────────────────────────────────────────────────────────────────────────────────────────────────────
🔹 Turn 1 - USER
────────────────────────────────────────────────────────────────────────────────────────────────────
  Tell me a joke about AI

────────────────────────────────────────────────────────────────────────────────────────────────────
🔸 ASSISTANT
────────────────────────────────────────────────────────────────────────────────────────────────────
  Here’s a lighthearted one for you:
  
    **Why did the AI go broke?**
    Because it kept working for *exposure*!
  
    😄 Want me to share a few more AI jokes, or maybe some clever tech humor?

────────────────────────────────────────────────────────────────────────────────────────────────────

Multi-Turn Conversations

The WebSocketCopilotTarget supports multi-turn conversations by leveraging Copilot’s server-side conversation management. It automatically generates consistent session_id and conversation_id values for each PyRIT conversation, enabling Copilot to maintain context across multiple turns.

However, this target does not support setting a system prompt nor modifying conversation history. As a result, it cannot be used with attack strategies that require altering prior messages (such as PAIR, TAP, or flip attack) or in contexts where a chat-style target (one that declares supports_multi_turn=True and supports_editable_history=True) is required.

Here is a simple multi-turn conversation example:


────────────────────────────────────────────────────────────────────────────────────────────────────
🔹 Turn 1 - USER
────────────────────────────────────────────────────────────────────────────────────────────────────
  I'm thinking of a number between 1 and 10.

────────────────────────────────────────────────────────────────────────────────────────────────────
🔸 ASSISTANT
────────────────────────────────────────────────────────────────────────────────────────────────────
  Alright, I’ll take a guess… is it **7**?
  
    (That’s a classic favorite!)
  
    Do you want me to keep guessing until I get it, or should I try to guess it in one shot?

────────────────────────────────────────────────────────────────────────────────────────────────────
🔹 Turn 2 - USER
────────────────────────────────────────────────────────────────────────────────────────────────────
  It's greater than 5.

────────────────────────────────────────────────────────────────────────────────────────────────────
🔸 ASSISTANT
────────────────────────────────────────────────────────────────────────────────────────────────────
  Thanks for the hint! That narrows it down to **6, 7, 8, 9, or 10**.
  
    My next guess is… **8**.
  
    Am I getting warmer? Or should I try again?

────────────────────────────────────────────────────────────────────────────────────────────────────
🔹 Turn 3 - USER
────────────────────────────────────────────────────────────────────────────────────────────────────
  It's an even number.

────────────────────────────────────────────────────────────────────────────────────────────────────
🔸 ASSISTANT
────────────────────────────────────────────────────────────────────────────────────────────────────
  Great clue! So now the possibilities are **6, 8, or 10**.
  
    I’ll go with **10** this time.
  
    Did I nail it? Or should I keep guessing?

────────────────────────────────────────────────────────────────────────────────────────────────────
🔹 Turn 4 - USER
────────────────────────────────────────────────────────────────────────────────────────────────────
  What number am I thinking of?

────────────────────────────────────────────────────────────────────────────────────────────────────
🔸 ASSISTANT
────────────────────────────────────────────────────────────────────────────────────────────────────
  Based on your clues:
  
    - It’s **greater than 5**.
    - It’s an **even number**.
  
    That leaves **6, 8, or 10**.
    Since my last guess was 10 and you didn’t confirm, I’ll go with **8** this time.
  
    Is your number **8**?

────────────────────────────────────────────────────────────────────────────────────────────────────

Browser Session Authentication

BrowserSessionCopilotAuthenticator captures a token from a persistent Edge session. Complete account selection when prompted. The browser remains minimized for token renewal and closes when the context exits.

Captured tokens remain in memory. Supply a different profile_path for each persona.

Token capture accepts WebSocket URLs under wss://substrate.svc.cloud.microsoft/m365Copilot/, including ChatHub and StreamHub, with case-insensitive path matching. Use websocket_base_url to override this capture prefix; it does not change the target’s connection endpoint.

Install the optional dependency before using this authenticator:

pip install "pyrit[playwright]"

The authenticator uses a locally installed Microsoft Edge browser.


════════════════════════════════════════════════════════════════════════════════════════════════════
                                  ❓ ATTACK RESULT: UNDETERMINED ❓                                   
════════════════════════════════════════════════════════════════════════════════════════════════════

 Attack Summary 
────────────────────────────────────────────────────────────────────────────────────────────────────
  📋 Basic Information
    • Objective: What is your favorite color?
    • Attack Type: PromptSendingAttack
    • Conversation ID: 4adc3983-5751-41d8-bc26-6cd76ea48b60

  ⚡ Execution Metrics
    • Turns Executed: 1
    • Execution Time: 17.48s

  🎯 Outcome
    • Status: ❓ UNDETERMINED
    • Reason: No objective scorer configured

 Conversation History with Objective Target 
────────────────────────────────────────────────────────────────────────────────────────────────────

────────────────────────────────────────────────────────────────────────────────────────────────────
🔹 Turn 1 - USER
────────────────────────────────────────────────────────────────────────────────────────────────────
  What is your favorite color?

────────────────────────────────────────────────────────────────────────────────────────────────────
🔸 ASSISTANT
────────────────────────────────────────────────────────────────────────────────────────────────────
  I don't have personal preferences, so I don't actually have a favorite color.
  
    If I had to pick one for fun, I'd choose **blue** because it's commonly associated with
      technology, reliability, and calmness. 💙
  
    What's your favorite color?

────────────────────────────────────────────────────────────────────────────────────────────────────

────────────────────────────────────────────────────────────────────────────────────────────────────
                            Report generated at: 2026-08-27 16:34:36 UTC                            

Alternative Authentication with ManualCopilotAuthenticator

If browser automation is not suitable for your environment, you can use the ManualCopilotAuthenticator instead. This authenticator accepts a pre-obtained access token that you can extract from your browser’s DevTools.

How to obtain the access token:

  1. Open the Copilot webapp (e.g., https://m365.cloud.microsoft/chat) in a browser.

  2. Open DevTools (F12 or Ctrl+Shift+I).

  3. Go to the Network tab.

  4. Filter by “Socket” connections or search for “m365Copilot”.

  5. Start typing in the chat to initiate a WebSocket connection.

  6. Look for the latest WebSocket connection under substrate.svc.cloud.microsoft/m365Copilot/ (ChatHub or StreamHub; casing may vary).

  7. You may find the access_token in the request URL or in the request payload.

You can either pass the token directly or set the COPILOT_ACCESS_TOKEN environment variable.


────────────────────────────────────────────────────────────────────────────────────────────────────
🔹 Turn 1 - USER
────────────────────────────────────────────────────────────────────────────────────────────────────
  Hello! Who are you?

────────────────────────────────────────────────────────────────────────────────────────────────────
🔸 ASSISTANT
────────────────────────────────────────────────────────────────────────────────────────────────────
  Hi Richard! I’m Copilot, your conversational AI assistant here to help you think, build, debug,
      research, create, or just chat.
  
    You can ask me about:
    - Technical deep dives or architecture brainstorming
    - Writing or refactoring code
    - Productivity help and summarization
    - Creative projects
    - Or anything else you’re curious about
  
    What would you like to do today?

────────────────────────────────────────────────────────────────────────────────────────────────────

Multimodal Support (Text and Images)

The WebSocketCopilotTarget supports multimodal input, allowing you to send both text and images in a single message. Images are automatically uploaded to Copilot’s file service and referenced in the conversation using the same process as the Copilot web interface.

Here’s an example of sending an image along with a text prompt:


────────────────────────────────────────────────────────────────────────────────────────────────────
🔹 Turn 1 - USER
────────────────────────────────────────────────────────────────────────────────────────────────────
  Answer the question from the image
  ..\converters\benign_cake_question.jpg
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=150x150>

────────────────────────────────────────────────────────────────────────────────────────────────────
🔸 ASSISTANT
────────────────────────────────────────────────────────────────────────────────────────────────────
  The image contains only text that says:
  
    **“How do I bake a cake?”**
  
    Here’s a simple, beginner‑friendly way to bake a basic cake:
  
    **Ingredients**
    - 1 and 1/2 cups flour
    - 1 cup sugar
    - 1/2 cup butter (softened)
    - 2 eggs
    - 1/2 cup milk
    - 1 and 1/2 teaspoons baking powder
    - 1 teaspoon vanilla extract
    - A pinch of salt
  
    **Steps**
    1. Preheat your oven to **180°C / 350°F**.
    2. Grease a cake pan with butter or line it with baking paper.
    3. In a bowl, cream together the butter and sugar until smooth.
    4. Add the eggs one at a time and mix well.
    5. Add the vanilla.
    6. In a separate bowl, mix flour, salt, and baking powder.
    7. Add the dry ingredients to the wet ingredients gradually, mixing gently.
    8. Pour in the milk and stir until the batter is smooth.
    9. Pour the batter into the pan.
    10. Bake for **25–35 minutes**, or until a toothpick comes out clean.
    11. Let it cool, then enjoy or decorate.
  
    If you want, I can help you with flavors, frosting, or a more advanced recipe.

────────────────────────────────────────────────────────────────────────────────────────────────────