Tags: duckduckgo/content-scope-scripts
Tags
Duck.ai data clearing: report the real error and always reply (#3070)
[Web-compat] Pass key detection messaging (#2948) * Fix extensionless relative import in web-compat.js '../utils' resolves ambiguously under strict Node ESM because both src/utils.js and the src/utils/ directory exist side by side. This surfaces as ERR_UNSUPPORTED_DIR_IMPORT as soon as any test imports web-compat.js directly (previously nothing did). Use the explicit .js extension, matching every other relative import in this file. * web-compat: detect WebAuthn passkey usage for pixelling Adds a new, disabled-by-default sub-setting ('passkeyDetection') to the webCompat feature that observes navigator.credentials.get()/ .create() calls made with a 'publicKey' option (i.e. WebAuthn/passkey ceremonies) and notifies the native layer via a new 'passkeyUsed' message when one completes successfully. This is a much lighter touch than AutofillPasskeys (autofill-passkeys.js): it never mediates, delays, or replaces the credential ceremony. The real CredentialsContainer method is always invoked with the original arguments/receiver and its return value is returned to the page completely unchanged; we only attach a side-channel observer to that promise to detect a successful public-key outcome. wrapMethod's toString()/name/length masking means the wrapped function remains indistinguishable from the native one to any site-side introspection. See https://app.asana.com/1/137249556945/project/1202552961248957/task/1216590640816429 * web-compat: add unit tests for passkey detection Covers: pass-through behaviour (return value/rejection reach the page unchanged), notification firing only for get()/create() calls that carry a publicKey option and resolve to a public-key credential, no notification on rejection/null/non-WebAuthn calls, the setting being a true no-op when disabled, and safe no-ops when CredentialsContainer or navigator.credentials are absent. * web-compat: log passkey detection state * web-compat: log intercepted passkey calls * web-compat: keep wrapped passkey methods indistinguishable from native wrapMethod's wrapToString only masks toString(), so the anonymous wrapper's own name/length leaked through: navigator.credentials.get.name became '' instead of 'get'. Verified in real Chromium against a virtual authenticator - the wrapped ceremony behaves identically, but the identity mismatch is exactly the tamper signal this feature must avoid, since sites fingerprinting the credentials API can read it. Restores name/length from the original descriptor (same approach as api-manipulation's maskMethodReplacement) and adds a regression test. Also logs the error name when a ceremony does not complete, so platform-side failures (e.g. a credential manager error) are visible in debug builds. Only the error name is logged, never page-supplied options or error messages. * web-compat: report passkey ceremony failures Extend the passkeyUsed notification with a required success boolean. Successful public-key ceremonies send success=true; rejected ceremonies send success=false. Error details remain local to debug logs and no page-supplied data is sent to native. Messaging failures are swallowed so the detached observer can never create an unhandled rejection or affect the page's original promise. * WIP: mirror passkey outcomes through webEvents for PoC webCompat.passkeyUsed is the message we want, but no native handler declares it, so the client's router drops those notifications with no log and no error (notifications carry no id, so it doesn't even get a method-not-found response). That makes the signal impossible to observe on device without a client change. webEvents.webEvent is already routed and logged by the Event Hub, so this also fires the same outcome there, purely to make the end-to-end flow observable with no client change: EventHub: received webEvent type=passkeyUsed ... Verified in real Chromium against a virtual authenticator: a successful create() and a rejected get() each emit both the passkeyUsed notification and the mirrored webEvent. Additive and self-contained so it can be dropped once passkeyUsed is handled natively. Not intended to ship as-is. * Revert "WIP: mirror passkey outcomes through webEvents for PoC" This reverts commit 4444229. * Document Android passkey message contract Explicitly documents the native integration point as webCompat.passkeyUsed with required parameters: - type: get | create - success: boolean No Android implementation is included; the client team can implement the handler against this generated contract. * web-compat: add sanitized error name to failed passkey messages Extends the webCompat.passkeyUsed contract with an optional 'error' field, present only when success=false. It carries the rejected ceremony's DOMException name, restricted to a bounded allowlist (NotAllowedError, SecurityError, NotSupportedError, InvalidStateError, ConstraintError, AbortError, UnknownError, EncodingError, NotReadableError, TypeError); anything else - including non-Error rejections - is reported as 'Other'. The error message is never sent. This lets the native side populate the enumerated 'error' parameter on the autofill_passkey_*_failed pixels, and in particular distinguishes a platform/credential-manager failure (NotReadableError) from an ordinary user-level outcome (NotAllowedError). * web-compat: drop passkey debug logging These logs were scaffolding for bringing the messaging up end to end. The passkeyUsed notification now carries the operation, outcome, and sanitized error name, so the per-init state log, the per-call intercept log, and the failure log are all redundant. * Harden stacked passkey wrappers on Windows Both webCompat.passkeyDetection and the Windows autofillPasskeys feature can wrap CredentialsContainer.prototype.get. Keep identity masking opt-in, but share it between those two wrappers so whichever layer is page-visible retains the replaced method's name, length, and toString. Generic wrapMethod behavior remains unchanged for all other features. Add composition tests covering the actual Windows wrapper order, non-conditional pass-through, conditional selection, and two masked wrapper layers. Also replace the page-tamperable error allowlist Array.includes call with a switch and handle throwing name getters. All call order, receiver, argument, promise, and notification semantics remain unchanged. * Split passkey detection into passkeyUsed and passkeyFailed Success and failure are now separate webCompat notifications so native handlers can dispatch on method name instead of a success boolean. * Mask name and length in wrapMethod for stacked wrappers wrapMethod already faked toString; name/length are now restored on every layer so Windows autofillPasskeys and webCompat passkey detection stay consistent regardless of parallel init order. * Make maskMethodIdentity internal and stabilise passkey tests wrapMethod is now the only caller, so the helper no longer needs to be exported. The Windows conditional test passes an explicit rpId instead of relying on an ambient location global. * Regenerate web-compat message types after merging main --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Duck.ai data clearing: remove image blobs on Apple platforms (#3058) * Duck.ai data clearing: delete records individually so image blobs are removed * Limit per-record delete to iOS and macOS * Add deleteRecordsIndividually kill switch, enabled by default
PreviousNext

