Skip to content

Conversation

@paulinek13
Copy link
Contributor

@paulinek13 paulinek13 commented Dec 22, 2025

Description

Resolves #343

This PR introduces WebSocketCopilotTarget, enabling sending prompts to Microsoft Copilot via WebSocket.
Implementation reference: powerpwn/copilot/copilot_connector/copilot_connector.py

Authentication is handled automatically via CopilotAuthenticator (also a new addition), which uses Playwright to automate browser login and obtain the required access tokens.

Tests and Documentation

✅ both WebSocketCopilotTarget and CopilotAuthenticator are documented
✅ unit tests are added for both


The following related items I'd like to address in separate PRs:

  • add support for image_path data type (WebSocketCopilotTarget)
  • ensure accounts with MFA enabled will also work (CopilotAuthenticator)

@paulinek13 paulinek13 changed the title [✏️ DRAFT] FEAT: add WebSocket-based prompt target for Microsoft Copilot [DRAFT] FEAT: add WebSocket-based prompt target for Microsoft Copilot Dec 22, 2025
- Rename _parse_message() to _parse_raw_message()
- Split on record separator (\x1e) and processes all frames, not just first
- Add FINAL_DATA_FRAME (type 3) enum value for completion signals
- Extract bot message parsing logic into lambda for reusability
- Fixes stop condition to handle FINAL_DATA_FRAME and remove flawed
  "is_user_input and PING" logic
…way because of `enterprise-prod-first-party-app-policy`

This reverts commit 276290f.
@paulinek13 paulinek13 marked this pull request as ready for review December 30, 2025 14:09
@paulinek13 paulinek13 changed the title [DRAFT] FEAT: add WebSocket-based prompt target for Microsoft Copilot FEAT: add WebSocket-based prompt target for Microsoft Copilot Dec 30, 2025
@paulinek13
Copy link
Contributor Author

This PR is finally ready for review. However, I still need to add a notebook for this target, which I'll do in the meantime 😃

@rlundeen2 rlundeen2 self-assigned this Jan 23, 2026
await ConsoleAttackResultPrinter().print_conversation_async(result=result)

# %%
from pyrit.memory import CentralMemory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we stopped including this

logger = logging.getLogger(__name__)


class CopilotAuthenticator(Authenticator):
Copy link
Contributor

@rlundeen2 rlundeen2 Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, but we can't run it through integration tests, which we'd want to make sure it's not broken. I'm okay with the authenticator piece not being testable, but I'd at least want a way to run WebSocketCopilotTarget.

Can we add another method for authenticating besides a headless browser so we can use it even with MFA, etc? E.g. an option where instead of username/password, you pass in auth headers? or alternatively a separate auth class that just takes cookies/headers that you set?

def __init__(
self,
*,
verbose: bool = False,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's get rid of this, log levels are set elsewhere (although we may have verbose hanging around)

super().__init__(
verbose=verbose,
max_requests_per_minute=max_requests_per_minute,
endpoint=self.WEBSOCKET_BASE_URL,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this as a default, but let's pass it in

return json.dumps(data, separators=(",", ":")) + "\x1e"

@staticmethod
def _parse_raw_message(message: str) -> list[tuple[CopilotMessageType, str]]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we rename to something like raw_websocket_message

Copy link
Contributor

@rlundeen2 rlundeen2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@paulinek13 this is super cool! Thanks for tackling!

Before merging, I'd like to test, which I'm not setup to do as is :) But if you take the auth token change where I can paste tokens or a raw request or something without a headless browser, then I can check usage.

But looks good! No major concerns

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FEAT Add Copilot Target

2 participants