Skip to content

Copilot Component: camera/microphone (getUserMedia) blocked by host container Permissions Policy in production M365 Copilot despite devicePermissions: ["media"] #11005

Description

@xrsilver

Target SharePoint environment

SharePoint Online

What SharePoint development model, framework, SDK or API is this about?

💥 SharePoint Framework

Developer environment

None

What browser(s) / client(s) have you tested

  • 💥 Internet Explorer
  • 💥 Microsoft Edge
  • 💥 Google Chrome
  • 💥 FireFox
  • 💥 Safari
  • mobile (iOS/iPadOS)
  • mobile (Android)
  • not applicable
  • other (enter in the "Additional environment details" area below)

Additional environment details

SPFx version: 1.24.0-beta.2
@microsoft/sp-copilot-component version: 1.24.0-beta.2
@azure/communication-react version: 1.34.0
@azure/communication-calling (peer dep): 1.43.1
@azure/communication-common: 2.5.0
Browser + version: [FILL IN - e.g. Edge 12x]
Tested via: Copilot Workbench (works), Microsoft 365 Copilot production (fails)

Describe the bug / error

A Copilot Component that uses getUserMedia() for live camera/microphone streaming (via @azure/communication-react's CallComposite, which wraps the ACS Calling SDK) works correctly when run through the Copilot Workbench, but camera/microphone access is fully blocked once the same component is deployed and invoked through production Microsoft 365 Copilot. The browser never even shows a permission prompt in production - the request is rejected at the Permissions Policy level by the host's iframe container, despite devicePermissions: ["media"] being declared in the app manifest.

Steps to reproduce

Scaffold a Copilot Component that calls navigator.mediaDevices.getUserMedia({ video: true, audio: true }) (directly, or indirectly via CallComposite/ACS Calling SDK).
Run locally via Copilot Workbench (/_layouts/15/copilotworkbench.aspx) and trigger the code path that calls getUserMedia(). Camera/mic access is granted correctly.
Deploy the same component and invoke it through production Microsoft 365 Copilot instead.
Trigger the same code path.

Expected behavior

The browser prompts the user for camera/microphone permission (or honors previously-granted permission), consistent with devicePermissions: ["media"] being declared in the manifest.

Actual behavior

No permission prompt appears. Browser console shows:

[Violation] Permissions policy violation: microphone is not allowed in this document.
[Violation] Permissions policy violation: camera is not allowed in this document.
Hardware access blocked by host container permissions: NotAllowedError: Permission denied

Traced the third line to @microsoft/sp-copilot-component's own compiled client runtime (bundled into our component's output), not our application code. It is an internal permission-probe helper with this shape:

js
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
stream.getTracks().forEach(track => track.stop()); // probe only, tracks released immediately
onGranted();
} catch (e) {
console.error("Hardware access blocked by host container permissions:", e);
}

This appears to be the SDK's own built-in mechanism for checking/granting media device capability to a Copilot Component - i.e. this is not a failure in our custom getUserMedia usage, it is Microsoft's own first-party permission-check code hitting the same Permissions Policy block.

Additional notes
We initially suspected this was a script/tool-input timing issue (a separate Error: Host did not send tool-input within 30000ms we hit and resolved by making an unused required property optional in our Zod properties schema) - once that was fixed and the component initialized correctly, this Permissions Policy block is what's actually surfacing.
devicePermissions: ["media"] is documented for the microsoftTeams.media.* capture APIs (captureImage/selectMedia/getMedia) per https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/device-capabilities/media-capabilities - not confirmed to apply to raw getUserMedia() streaming inside a Copilot Component.
Suspect the production M365 Copilot host is not adding allow="camera; microphone" (or equivalent Permissions-Policy header) to the iframe hosting the Copilot Component, regardless of the devicePermissions manifest declaration.
Confirmed via direct comparison: the same permission probe succeeds without issue in the Copilot Workbench (/_layouts/15/copilotworkbench.aspx) - camera/mic access works there. It only fails once the component is deployed and invoked through production Microsoft 365 Copilot. This points to a difference in how the two hosts construct/permission the component's iframe, rather than anything in our manifest or code.

Metadata

Metadata

Assignees

Labels

area:spfx-copilot-appstype:bug-suspectedSuspected bug (not working as designed/expected). See “type:bug-confirmed” for confirmed bugs.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions