demo · v137
SPC Error Probe
The bug fixed in v137 surfaces in one specific path: calling credentials.create({ payment }) in a cross-origin iframe without a fresh user activation. Before v137, you got SecurityError — wrong name, breaks e instanceof NotAllowedError error handlers. After v137, the spec-aligned NotAllowedError.
probing…
| scenario | spec error name | pre-v137 | v137+ |
|---|---|---|---|
| same-origin, no activation | NotAllowedError | NotAllowedError | NotAllowedError |
| cross-origin iframe, with activation | resolves / NotAllowedError on decline | same | same |
| cross-origin iframe, no activation | NotAllowedError | SecurityError | NotAllowedError |
A. same-origin, no activation
Calls create({ payment }) immediately on click — no user gesture inside the call site, though the click itself is a gesture.
awaiting…
B. “cross-origin iframe”, no activation
A sandboxed iframe (opaque origin = treated as cross-origin) calls the same API on load with no activation — exactly the path the v137 rename fixes.
awaiting…
the code
// Inside a cross-origin iframe, no user activation:
try {
await navigator.credentials.create({
publicKey: { /* ... */ },
payment: { /* ... */ },
});
} catch (e) {
// Spec: NotAllowedError (matches every other user-gated WebAuthn flow).
// Pre-v137 Chrome: SecurityError -> breaks `e instanceof NotAllowedError`
// checks copied from non-payment WebAuthn code.
// Post-v137 Chrome: NotAllowedError.
reportTo(e.name);
}