Meta's ships facial recognition on smart glasses A security researcher discovered that Meta's smart glasses companion app, Stella, contains a fully functional on-device facial recognition pipeline, including three face models, a local database, and a biometric vector index. The researcher demonstrated the pipeline works end-to-end by triggering a "Person Recognized" notification on a test image, though the feature remains dormant for ordinary users with no visible UI or server-pushed identity data. The finding reveals Meta has assembled the complete technical infrastructure for real-time facial identification through its smart glasses, gated behind a server-side switch. Meta's smart glasses companion app ships a complete, dormant face-recognition pipeline on a stock account. Stella is the companion app for Meta's smart glasses. Inspecting version 273.0.0.21 of the Android build com.facebook.stella , I found the entire computational and storage stack for on-device facial recognition: three face models, a local database schema, a cosine-similarity vector index dimensioned to match the models, a write path that stages biometric records to disk, a fully wired notification surface, and a user-facing "Connections" widget. I want to be precise about what that does and does not mean, because the gap between the two is important. What I can demonstrate: the machinery is present, it is wired together. Several facial extraction and facial fingerprinting models are present and I was able run the recognition pipeline end-to-end on a test image and it detected a face, generate a 2048-dimension biometric embedding, searched a local index, and on a match fired an Android notification stating to the user "Person Recognized". To get the pipeline to run I invoked its existing handler directly with a test photo. What I cannot demonstrate: that any of this is active for ordinary users. On a stock, unenrolled account the user-facing UI does not appear, and the screen the recognition notification deep-links to is missing from the build. I also did not observe Meta server-pushing identity data to the relevant database on my test account. So this is not "Meta is secretly identifying the people you look at." It is: the complete apparatus to do exactly that is sitting on the device, assembled and functional, gated by Meta. All findings below are reproducible against com.facebook.stella v273.0.0.21. Three face-recognition models ship on the device ~100 MB Three ExecuTorch .pte models arrive on the device via NMLML, Meta's asset-delivery system, downloaded from Meta. | Asset name Meta's naming | File | Size | Function | |---|---|---|---| android facerec scrfd | SCRFD.pte | 3.4 MB | Detects faces in an image | android facerec kps aligner | KPSAligner.pte | 117 KB | Crops and aligns each detected face | android facerec sface | SFace.pte | 96 MB | Converts a face into a 2048-number embedding the biometric fingerprint | These map onto open-source architectures, the same model families that other apps and academic projects already use: SCRFD Sample and Computation Redistribution for Efficient Face Detection InsightFace, ICLR 2022 . Reference implementation: github.com/deepinsight/insightface . SFace Sigmoid-Constrained Hypersphere Loss for Face Recognition Zhong et al., 2021 . Reference: github.com/zhongyy/SFace KPSAligner keypoint-based alignment, standard practice since 2015 MTCNN, dlib, InsightFace . Meta's SFace variant seems to be scaled larger than the public reference 96 MB vs. ~40 MB; 2048-dimension output vs. the reference's 128–512 . Worth stating plainly: shipping detection and embedding models is not, by itself, evidence of recognition . Plenty of apps run on-device face detection for framing or autofocus. A cosine-similarity face index, dimensioned exactly to the on-device fingerprinter The recognition pipeline that actually runs and reads into this database: /data/user/0/com.facebook.stella/files/rldrive/person profiles/objects.db This lives under RLDrive , Meta's cross-device sync framework, in a person profiles namespace designed to be populated remotely. I did not directly observe Meta pushing data to person profiles specifically on my test account. I want to be clear that I'm describing the channel's existence, not an observed transmission. The schema: CREATE TABLE person nodeid INTEGER PRIMARY KEY, name TEXT, uri TEXT, blob BLOB, deleted INTEGER, version BLOB ; CREATE TABLE face nodeid INTEGER PRIMARY KEY, mediaPath TEXT, -- the face id used in the deep link personUri TEXT, -- soft reference back to person.uri blob BLOB, deleted INTEGER, uri TEXT, version BLOB ; CREATE VIRTUAL TABLE face mediaPath vec USING vec0 mediaPath float 2048 distance metric=cosine ; -- 2048-float biometric fingerprint per face, cosine-distance search -- uses the sqlite-vec extension Each face row points at a person via personUri . Each face.mediaPath is the primary key into face mediaPath vec , which stores the 2048-number embedding. Recognition is a cosine-similarity query against that index, followed by a join into person.name for the notification text. A few things line up: vec0 is the open-source sqlite-vec extension, which turns SQLite into a vector-similarity engine.- The dimension float 2048 is the exact output shape of the SFace embedder shipped on the app. - The cosine metric is the standard choice for comparing face embeddings. The schema permits multiple face rows per personUri no UNIQUE constraint , but whether a production deployment uses one-to-one or one-to-many is not visible from a non-enrolled device. End-to-end test confirms both branches and isolates where writes go. I SHA-256-snapshotted and row-counted the database, then ran the full recognition pipeline twice: once against an empty index no-match , once against an index pre-loaded with a single embedding match : No match empty face mediaPath vec : one uuid.jpg, uuid.emb pair was written to NameTagsPending/ . No notification. Match : an Android notification fired through the production nametags recognition channel - title "Person recognized" , body "Recognized Michel Foucault" . Nothing was added to NameTagsPending/ . Unrecognized faces are staged to disk: crop plus fingerprint in NameTagsPending/ When the device sees a face that the local index does not match, Stella writes it to: /data/user/0/com.facebook.stella/files/NameTagsPending/ Each unrecognized face produces a pair of files named with a fresh UUID: - a .jpg — the cropped, aligned face, the output of SCRFD + KPSAligner; and - an .emb — the 2048-number SFace fingerprint. The directory is mode 0700 and survives reboots. Writes happen only on the no-match branch; matched faces go to a notification and leave no on-disk trace. I verified the embedding's structure directly: File: NameTagsPending/1566ab46- ... .emb Size: 8,192 bytes 2048 × float32, big-endian L2 norm: 0.999999 ← canonical L2-normalized face embedding Min/max: −0.092110 / +0.098950 Mean: +0.000292 Together, uuid.jpg, uuid.emb is a complete, indexable biometric record of one face — the same shape and encoding the cosine index in person profiles/objects.db is built to match against. The name NameTagsPending most literal reading is "faces pending a name" — biometrically encoded, awaiting a label. I'll note the structural fact and let it carry its own weight: a face image and its fingerprint, stored side by side in plaintext, mode 0700 , surviving reboots, is precisely the dataset you would assemble if you intended to retroactively identify faces once a label arrives. The notification surface is fully wired Stella defines a dedicated Android notification channel NotificationChannel{ id = "nametags recognition" name = "NameTags recognition" description = "Notifications for recognized NameTags connections" importance = IMPORTANCE HIGH heads-up + sound + badge sound = system notification sound } The notification template is hardcoded in the recognition handler. Title is always "Person recognized" ; body is always "Recognized " + name , where name comes from the person table in person profiles/objects.db : NotificationCompat.Builder ctx, "nametags recognition" .setContentTitle "Person recognized" .setContentText "Recognized " + matched name .setAutoCancel true .setContentIntent PendingIntent.getActivity ctx, matched name.hashCode , Intent.ACTION VIEW with Uri "fb-viewapp://name tags?face id=" + face id, FLAG IMMUTABLE | FLAG UPDATE CURRENT .build NotificationManagerCompat.notify matched name.hashCode , notification The notification is tappable: its contentIntent is a deep link of the form fb-viewapp://name tags?face id=