Question and scope
You own a dashboard that embeds meet.example for calls, video.example for playback, and several ad frames. The meeting frame needs microphone and camera; the video frame needs fullscreen; ads need none of these features. The page is HTTPS, the frame origins are known, and the browser must still ask the user for media consent when policy allows it.
The scope is browser-side policy composition and diagnosis. Authentication, CSP, and server authorization remain separate controls. Assume the response header is set by the dashboard server and every cross-origin frame has an explicit allow attribute.
What the interviewer is testing
The interviewer wants you to separate three gates: the response policy, the frame delegation, and the user's runtime permission. A header allowlist alone does not grant a cross-origin frame access, and an allow attribute cannot widen a header that denies the feature.
They also test whether you avoid wildcard convenience. A strong answer starts from () for sensitive features, names exact origins, handles nested navigation, and describes what the UI does when an API is unavailable. A weak answer writes *, waits for a permission prompt, and calls the feature secure.
Questions to clarify before answering
- Which exact origins can the meeting and video frames navigate to? A navigation to a different origin may require that destination in the frame policy, or the feature must be denied after navigation.
- Does the meeting frame open nested frames? If so, define whether delegation may continue and test the nested origin instead of assuming the first frame's grant is inherited forever.
- Which browsers and embedded webviews are supported? A policy syntax can be correct while an older runtime exposes a different failure surface.
- Is a camera or microphone call mandatory? If it is optional, the UI can offer a text-only path when policy or user permission is denied.
A 30-second answer framework
“I would default camera and microphone to () and grant them only to the meeting origin in the response policy. I would grant fullscreen only to the video origin. Each cross-origin iframe would repeat the intended feature in its allow attribute, because the header and frame policy are both required. The frame would detect policy denial separately from user denial, render a fallback, and never treat a permission prompt as authorization. I would test same-origin, cross-origin, navigation, nested-frame, missing-header, and browser-fallback cases before rollout.”
Step-by-step deep answer
Step 1: Start with a deny-by-default inventory
List every policy-controlled feature used by the page and its owning origin. Do not infer permissions from the product name “meeting.” Camera and microphone are two independent features. Fullscreen is another. Ads are an explicit zero-access class.
Use an explicit header such as:
Permissions-Policy: camera=(self "https://meet.example"), microphone=(self "https://meet.example"), fullscreen=(self "https://video.example")The exact origin list prevents an unrelated frame from receiving a grant. If the dashboard itself must not access a feature, remove self and grant only the required frame origin, then verify the parent policy still permits delegation.
Step 2: Delegate at each iframe boundary
The meeting frame receives only its two features, and the video frame receives only fullscreen:
<iframe src="https://meet.example/room" allow="camera; microphone"></iframe>
<iframe src="https://video.example/player" allow="fullscreen"></iframe>
<iframe src="https://ad.example/slot" allow=""></iframe>For a cross-origin frame, omitting allow blocks the feature even when the response header lists the origin. Conversely, adding allow="camera" to an ad does not override camera=() or an origin not present in the header.
Step 3: Treat policy and user consent as different states
Permissions-Policy decides whether the document may use a feature. The Permissions API and the media prompt represent user-granted permission. A blocked feature may fail before a prompt appears. The frame should map “policy denied,” “user denied,” “unsupported,” and “device busy” to different telemetry and recovery text.
Do not make the client-side check the security boundary. The embedding page controls delegation, while the application still authenticates the call and authorizes room membership on the server.
Step 4: Handle navigation and nested frames explicitly
If the meeting frame can navigate to a support origin, include that destination in the allow policy only if it is trusted and needs the same feature. A frame's initial src origin and a later navigation origin are not interchangeable. For nested frames, verify the effective policy at every boundary and deny by default when ownership is unclear.
Step 5: Roll out with observable tests
Ship the header in report-only diagnostics or a small route cohort when the platform allows it, then compare policy violations, prompt outcomes, call completion, and fallback usage. Test a same-origin frame, an allowed cross-origin frame, an unlisted cross-origin frame, a missing allow attribute, a changed subdomain, and a frame navigation. Assert that ads never reach a prompt and that a denied meeting frame offers text chat.
High-quality sample answer
“I would write the policy from the threat model. Camera and microphone start as empty permissions, then the header lists only meet.example; fullscreen lists only video.example. The two cross-origin frames carry matching allow attributes, while the ad frame carries none. The browser still controls user consent, so the meeting code distinguishes a policy block from a user denial and offers a text-only fallback. I would not put authorization in this header: the server still checks the room and user.
Before enabling it globally, I would exercise the matrix: allowed and unlisted origins, same-site but cross-origin subdomains, omitted allow, frame navigation, nested frames, unsupported browsers, and a missing header. Telemetry records the feature, frame origin, policy result, user result, and fallback without recording media. Any unexpected prompt from an ad or any successful access after navigation to an untrusted origin stops the rollout.”
Common mistakes
- Using
*for camera and microphone → any eligible frame can request a powerful feature → start with()and add exact origins. - Adding only the HTTP header → a cross-origin iframe still needs container delegation → set a matching
allowattribute. - Adding only
allow→ the frame cannot widen the parent policy → check both the response and every frame boundary. - Treating a missing prompt as a browser bug → policy denial can happen before user consent → report policy, consent, support, and device states separately.
- Assuming subdomains are same-origin → same-site does not mean same-origin → list each origin and test navigation.
Follow-up questions and responses
Follow-up 1: Why is the feature blocked even though the header lists the meeting origin?
Check the iframe's allow attribute, the exact scheme and port, and whether the frame navigated. For a cross-origin frame, the header allowlist and container policy intersect; one missing grant blocks the feature.
Follow-up 2: Should you omit the header and rely on allow?
No. An explicit response policy gives the page owner a top-level boundary and prevents accidental grants when a new frame is added. Omitting it can leave a permissive default for some features, which makes a later third-party embed a policy regression.
Follow-up 3: The meeting frame navigates to a support domain. What changes?
Reassess the destination as a new origin. Grant camera or microphone there only after trust, authentication, and data handling are reviewed; otherwise the navigation should lose those capabilities and the UI should explain the fallback.
Follow-up 4: Can Permissions Policy replace server-side authorization?
No. It controls browser feature availability in a document. It does not prove the user's identity, room membership, or whether a request may join a call. Keep those checks on the server and treat the policy as a least-privilege browser boundary.