{
 "slug": "client-side-face-liveness-fails-fatal-flaws",
 "topic_id": "TOPIC-028",
 "cluster": "Privileged Identity & Help-Desk Takeover",
 "tier": "Tier B",
 "title": "Why browser-based face liveness cannot be trusted",
 "summary": "A liveness check that runs in the browser asks the client to report on itself. The client is the thing under attack, and the answer it returns is a boolean an attacker controls.",
 "lede": "The camera is a device driver. The detection runs in JavaScript. The result is a field in an HTTP request. At no point does the server observe anything an attacker cannot manufacture.",
 "date": "2024-12-30",
 "category": "Developer",
 "author_id": "tobias-lindqvist-rao",
 "tags": [
  "liveness detection",
  "biometrics",
  "deepfake",
  "virtual camera",
  "client-side security",
  "identity verification"
 ],
 "image_title": "Browser Face Liveness Failure",
 "schema": "Article",
 "key_takeaways": [
  "Client-side liveness violates the basic rule that a security decision cannot be delegated to the party being evaluated.",
  "Virtual camera drivers inject synthetic video at the operating-system level, below anything a browser can observe.",
  "Hardware authenticators avoid the problem by keeping the biometric local and having the server verify a signature instead of a claim."
 ],
 "body": [
  {
   "type": "h2",
   "text": "Three places the attack lands"
  },
  {
   "type": "diagram",
   "kind": "flow",
   "alt": "Three layers, three independent attacks",
   "caption": "An attacker only needs the cheapest one.",
   "nodes": [
    {
     "label": "Video source",
     "note": "virtual camera driver",
     "bad": true
    },
    {
     "label": "Detection logic",
     "note": "patch the page",
     "bad": true
    },
    {
     "label": "Reported result",
     "note": "forge the request",
     "bad": true
    },
    {
     "label": "Server believes a boolean",
     "note": "",
     "bad": true
    }
   ]
  },
  {
   "type": "p",
   "html": "A browser liveness check has three layers, and each can be attacked independently. An attacker only needs the cheapest one."
  },
  {
   "type": "table",
   "head": [
    "Layer",
    "Attack",
    "Cost"
   ],
   "rows": [
    [
     "The video source",
     "Virtual camera driver presenting synthetic video as a real device",
     "Free software, minutes to set up"
    ],
    [
     "The detection logic",
     "Patch the page, hook the library, alter the DOM",
     "Trivial — the code is delivered to the attacker"
    ],
    [
     "The reported result",
     "Replay or forge the request carrying the boolean",
     "Trivial — it is an HTTP request"
    ]
   ]
  },
  {
   "type": "p",
   "html": "The third row is the one that ends the discussion. Whatever sophistication the detection has, its output is a value in a request the client composes."
  },
  {
   "type": "h2",
   "text": "Why virtual cameras defeat the premise"
  },
  {
   "type": "p",
   "html": "Browsers request video from the operating system's media stack. A virtual camera driver registers as a capture device and supplies frames from a file, a stream or a real-time synthesis pipeline."
  },
  {
   "type": "p",
   "html": "From the browser's position this is indistinguishable from a physical camera, because at the API level it <em>is</em> a camera. The frames arrive through the same interface with the same metadata."
  },
  {
   "type": "p",
   "html": "This is not an exotic capability. Virtual camera software is standard in streaming and video production, which means the tooling is mature, free and entirely legitimate in its primary use."
  },
  {
   "type": "h2",
   "text": "Server-side analysis is better and still bounded"
  },
  {
   "type": "p",
   "html": "Sending frames to the server and analysing them there removes the patched-detector and forged-boolean problems. It is a real improvement and several vendors do it well."
  },
  {
   "type": "p",
   "html": "What it does not remove is the injected source. The server now analyses video it received; it still has no way to establish that the video came from a physical sensor pointed at a person rather than from a driver."
  },
  {
   "type": "p",
   "html": "The result is a probabilistic contest — detection quality versus synthesis quality — where the synthesis side improves continuously and the detector must generalise to techniques that did not exist when it was trained. That contest has a structural shape that favours the attacker over time."
  },
  {
   "type": "h2",
   "text": "The alternative: verify a signature, not a claim"
  },
  {
   "type": "p",
   "html": "Platform authenticators invert the trust relationship. The biometric never leaves the device and is never transmitted or evaluated by the server."
  },
  {
   "type": "code",
   "text": "# Client-side liveness\nclient  → server:  { \"live\": true, \"confidence\": 0.97 }\n# Server must decide whether to believe a claim from an\n# untrusted client about an untrusted input.\n\n# Platform authenticator\nserver  → client:  challenge (bound to the action)\n# Secure element requires a local user-verification gesture,\n# then signs. The private key never leaves the hardware.\nclient  → server:  signature + authenticator data (UV flag set)\n# Server verifies the signature against a registered public key."
  },
  {
   "type": "p",
   "html": "The server is no longer reasoning about video. It is checking a signature produced by hardware it enrolled, which either verifies or does not."
  },
  {
   "type": "h2",
   "text": "What this design does not claim"
  },
  {
   "type": "p",
   "html": "Three honest limits."
  },
  {
   "type": "ol",
   "items": [
    "<strong style=\"font-weight:600\">It does not prove who the person is.</strong> It proves possession of an enrolled authenticator plus a successful local user-verification gesture. Binding that authenticator to a real, identified human is a separate enrolment problem.",
    "<strong style=\"font-weight:600\">It does not prevent coercion.</strong> Someone forced to unlock their device produces a valid signature. No remote mechanism solves this.",
    "<strong style=\"font-weight:600\">It does not prevent enrolled-device sharing.</strong> A person who hands their unlocked device to someone else has defeated it. Attestation about authenticator type helps at the margin; it does not solve it."
   ]
  },
  {
   "type": "p",
   "html": "These are the sort of limits that a client-side liveness vendor also has, usually without stating them."
  },
  {
   "type": "h2",
   "text": "Where identity verification still belongs"
  },
  {
   "type": "p",
   "html": "Document and biometric verification has a genuine role at enrolment: establishing, once, that this authenticator belongs to this identified person. That is a high-stakes, low-frequency event where the cost of a thorough check is justified."
  },
  {
   "type": "p",
   "html": "The mistake is using the same mechanism for repeated authorisation, where it is high-frequency, low-margin and facing an attacker who can iterate. Verify identity carefully at enrolment; verify possession cryptographically thereafter."
  },
  {
   "type": "h2",
   "text": "What the alternative does and does not claim"
  },
  {
   "type": "table",
   "caption": "Three honest limits of platform authenticators",
   "head": [
    "Limit",
    "Detail"
   ],
   "rows": [
    [
     "Does not prove identity",
     "It proves possession of an enrolled credential plus a local verification gesture"
    ],
    [
     "Does not prevent coercion",
     "Someone forced to unlock produces a valid signature"
    ],
    [
     "Does not prevent device sharing",
     "Handing over an unlocked device defeats it"
    ]
   ]
  },
  {
   "type": "p",
   "html": "These are the kinds of limits a client-side liveness vendor also has, usually without stating them. The difference is that the server is checking a signature rather than believing a claim about video."
  },
  {
   "type": "h2",
   "text": "Objections and honest limits"
  },
  {
   "type": "p",
   "html": "<strong style=\"font-weight:600\">“Server-side analysis fixes it.”</strong> It removes the patched-detector and forged-boolean problems, which is a real improvement. It cannot establish that the frames came from a physical sensor rather than a driver."
  },
  {
   "type": "p",
   "html": "<strong style=\"font-weight:600\">“So drop identity verification entirely?”</strong> No. Use it at enrolment, where a thorough one-time check is justified. Do not use it as the repeated authorisation mechanism against an attacker who can iterate."
  }
 ],
 "faq": [
  {
   "q": "Is server-side liveness analysis good enough?",
   "a": "It is substantially better than client-side and remains a probabilistic contest against improving synthesis. It cannot establish that the frames came from a physical sensor."
  },
  {
   "q": "Does a platform authenticator prove identity?",
   "a": "No. It proves possession of an enrolled credential plus a local user-verification gesture. Binding that credential to a real person happens at enrolment."
  },
  {
   "q": "What about coerced authentication?",
   "a": "A person forced to unlock their device produces a valid signature. No remote authentication mechanism addresses coercion; it is a physical-security problem."
  },
  {
   "q": "Should we drop identity verification entirely?",
   "a": "No. Use it at enrolment, where a thorough one-time check is justified. Do not use it as the repeated authorisation mechanism."
  },
  {
   "q": "Is server-side liveness good enough?",
   "a": "It is substantially better than client-side and remains a probabilistic contest against improving synthesis. It cannot establish that frames came from a physical sensor."
  },
  {
   "q": "Should identity verification be dropped?",
   "a": "No. Use it at enrolment where a thorough one-time check is justified, not as the repeated authorisation mechanism."
  }
 ],
 "sources": [
  {
   "t": "W3C Web Authentication: An API for accessing Public Key Credentials Level 3",
   "u": "https://www.w3.org/TR/webauthn-3/"
  },
  {
   "t": "NIST SP 800-63B — Authentication and authenticator management",
   "u": "https://pages.nist.gov/800-63-4/sp800-63b.html"
  },
  {
   "t": "NIST FRVT / FATE presentation attack detection evaluations",
   "u": "https://pages.nist.gov/frvt/html/frvt_pad.html"
  },
  {
   "t": "FIDO Alliance specifications",
   "u": "https://fidoalliance.org/specifications/"
  }
 ],
 "related": [
  {
   "slug": "fido2-aaguid-attestation-enterprises-restrict-authorization-corporate",
   "title": "AAGUID attestation and hardware policy",
   "category": "Developer"
  },
  {
   "slug": "scattered-spider-help-desk-mfa-reset-prevention",
   "title": "Making help-desk MFA resets social-engineering-proof",
   "category": "AEO"
  },
  {
   "slug": "failure-sms-voice-otp-mathematical-postmortem-telecom",
   "title": "The failure of SMS and voice OTP",
   "category": "Developer"
  }
 ],
 "image": "https://cdn.twc.sh/images/igcache/Browser%20Face%20Liveness%20Failure/1500_900/blog.jpg",
 "wordcount": 978,
 "url": "/blog/client-side-face-liveness-fails-fatal-flaws.html",
 "reading_time": "4 min read",
 "meta_description": "A liveness check running in the browser asks the client to report on itself. The client is under attack and the answer is a boolean.",
 "hub": {
  "slug": "topics/privileged-identity",
  "title": "Privileged identity and account recovery"
 },
 "answer": "Because it asks the client to report on itself, and the client is the thing under attack. The camera is a driver, the detection is JavaScript, and the result is a field in an HTTP request. At no point does the server observe anything an attacker cannot manufacture.",
 "answer_q": "Why can't a browser liveness check be trusted?",
 "glossary": [
  {
   "term": "Virtual camera",
   "def": "A software driver registering as a capture device, supplying synthetic frames through the same API as a real camera."
  },
  {
   "term": "Presentation attack",
   "def": "Defeating a biometric check by presenting synthetic or borrowed evidence to the sensor."
  },
  {
   "term": "Injection attack",
   "def": "Supplying synthetic frames below the application layer, so the capture path never sees a real sensor."
  }
 ],
 "checklist": {
  "title": "Where each mechanism belongs",
  "id": "where",
  "desc": "Four rules.",
  "steps": [
   {
    "name": "Identity verification at enrolment.",
    "text": "Once, thoroughly, high stakes."
   },
   {
    "name": "Cryptographic possession thereafter.",
    "text": "Repeated, cheap, unforgeable."
   },
   {
    "name": "Never trust a client-reported liveness boolean.",
    "text": "It is a field in a request the client composed."
   },
   {
    "name": "If you must analyse video, do it server-side.",
    "text": "And know it cannot establish sensor provenance."
   }
  ]
 },
 "cta": {
  "title": "Where this fits in Manav",
  "html": "Manav requires a fresh assertion bound to the specific action, from a credential under the person's sole control and verified against a published key.",
  "href": "../docs.html",
  "label": "See step-up gating"
 }
}