|
|
||
|---|---|---|
| .github | ||
| docs | ||
| packages | ||
| .editorconfig | ||
| .eslintrc.json | ||
| .gitignore | ||
| .prettierrc.json | ||
| CHANGELOG.md | ||
| CI_CD_SETUP.md | ||
| CONTRIBUTING.md | ||
| eslint.config.js | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
| SECURITY.md | ||
| TEST_SUMMARY.md | ||
| tsconfig.json | ||
| turbo.json | ||
VibeCheck
Open-source client-side liveness detection. No biometric data sent to servers.
🎯 Purpose
VibeCheck is a privacy-first liveness detection system designed to filter automated bot registrations while respecting user privacy. All biometric processing happens client-side in the browser - no video, images, or biometric data is ever transmitted to servers.
✨ Features
- 🔒 Privacy-First: All processing happens in your browser using MediaPipe
- 🎯 Bot Filter: Detects blinks, head movement, and depth cues to verify real humans
- 🌐 Open-Source: Fully auditable code - verify our privacy claims yourself
- 📦 Easy Integration: Drop-in React component + standalone core library
- 🚀 Fast & Lightweight: Client-side processing, no server round-trips
- 🎨 Customizable: Full control over UI, instructions, and flow
🚀 Quick Start
Installation
# React component (recommended)
npm install @lilithftw/vibecheck-react
# Or just the core library
npm install @lilithftw/vibecheck-core
Basic Usage
import { VibeCheck } from '@lilithftw/vibecheck-react';
function RegistrationPage() {
return (
<div>
<h1>Create Account</h1>
<VibeCheck
onSuccess={(result) => {
console.log('User verified!', result);
// Proceed with registration
}}
onFailure={(error) => {
console.error('Verification failed:', error);
}}
/>
</div>
);
}
🔒 Privacy Guarantees
What Happens Client-Side (In Browser)
- ✅ Video stream captured from webcam
- ✅ MediaPipe processes facial landmarks locally
- ✅ Blink detection, head movement analysis, depth estimation
- ✅ Result computed:
{ isLive: boolean, confidence: number, timestamp: number }
What Gets Sent to Server
- ✅ Only boolean result (
isLive: true/false) - ✅ Only confidence score (0-1 number)
- ✅ Only timestamp
What NEVER Leaves Your Browser
- ❌ No video frames
- ❌ No images/photos
- ❌ No facial landmarks or biometric data
- ❌ No identifying information beyond pass/fail
Verify this yourself: Our code is open-source and auditable.
🌐 Browser Support
| Browser | Version | Status |
|---|---|---|
| Chrome / Edge | 80+ | Fully supported |
| Firefox | 80+ | Fully supported |
| Safari | 15+ | Supported (WebGL2) |
| Chrome Android | 80+ | Fully supported |
| Safari iOS | 15+ | Supported (WebGL2) |
Requires: WebRTC, WebAssembly, WebGL 2.0. See the full Browser Support matrix.
📚 Documentation
- Architecture Overview
- Privacy Documentation
- API Reference
- Integration Guide
- Changelog
- Security Policy
🧪 Demo
Try it yourself: https://vibecheck.lilithftw.com (coming soon)
🏗️ Architecture
Standalone Service Design
VibeCheck runs as a standalone microservice, not embedded in your application codebase. This architecture provides:
- Reusability: One VibeCheck instance serves multiple applications
- Scalability: Independent scaling and deployment
- Clean Separation: Bot detection is infrastructure, not application logic
- Service Registry: Automatic discovery via
@lilith/service-registry
┌─────────────────────────────────────────────────────────────┐
│ User Browser │
│ (Client-Side) │
├─────────────────────────────────────────────────────────────┤
│ 1. Webcam │ ← getUserMedia() │
│ 2. MediaPipe WASM │ ← Face landmark detection │
│ 3. Analysis │ ← Blinks, head turn, depth │
│ 4. Sign Results │ ← HMAC signature with nonce │
└────────┬────────────────────────────────────────────────────┘
│ HTTPS (signed results only)
▼
┌─────────────────────────────────────────────────────────────┐
│ VibeCheck Service (Standalone) │
│ Port 4100 (HTTP API) │
├─────────────────────────────────────────────────────────────┤
│ POST /sessions │ ← Create session + nonce │
│ POST /sessions/:id/verify │ ← Verify signed results │
│ GET /sessions/:id/status │ ← Check verification status │
│ GET /health │ ← Health check │
│ GET /wasm-hash │ ← WASM integrity hash │
├─────────────────────────────────────────────────────────────┤
│ PostgreSQL (25451) │ ← Session storage, replay │
│ │ attack prevention │
└────────┬────────────────────────────────────────────────────┘
│ HTTP (session verification)
▼
┌─────────────────────────────────────────────────────────────┐
│ Your Application Backend │
│ (SSO, Authentication, Registration) │
├─────────────────────────────────────────────────────────────┤
│ • Query session status │ ← GET /sessions/:id/status │
│ • Verify before register │ ← Ensure verified = true │
│ • Store verification flag │ ← User.livenessVerified │
└─────────────────────────────────────────────────────────────┘
Security Architecture
Multi-layered defense prevents automated bot registrations:
- Timing-based behavioral analysis - Blink patterns, head movement timing
- WebAssembly code obfuscation - Detection logic compiled to WASM
- Code integrity verification - Server verifies WASM binary hash
- Challenge-response with nonces - Server generates random nonce per session
- Replay prevention - Each nonce is single-use, sessions expire in 5 minutes
Trade-offs: Blocks 95%+ of automated bots. Can be bypassed by determined attackers with reverse-engineering skills (hours/days of effort). Supplement with email/phone verification for production.
📦 Packages
This monorepo contains:
- @lilithftw/vibecheck-core: Core liveness detection logic (MediaPipe + crypto signing)
- @lilithftw/vibecheck-react: React component with UI
- api: NestJS verification service (session management, nonce verification)
- demo: Interactive demo application
🚀 Deployment
Standalone Service
The recommended deployment is as a standalone service that multiple applications can call over HTTP.
Service Configuration (example for Lilith Platform):
# deployments/shared-services/vibecheck.yaml
deployment:
id: vibecheck
type: shared
name: VibeCheck Service
services:
- id: api
type: api
port: 4100
entrypoint: ~/Code/@applications/vibecheck/packages/api
healthCheck:
type: http
path: /health
dependencies:
- postgresql
- id: postgresql
type: postgresql
port: 25451
description: Session storage, replay attack prevention
Environment Variables:
# VibeCheck API Service
PORT=4100
DATABASE_POSTGRES_HOST=localhost
DATABASE_POSTGRES_PORT=25451
DATABASE_POSTGRES_USER=vibecheck
DATABASE_POSTGRES_PASSWORD=secure_password
DATABASE_POSTGRES_NAME=vibecheck
NODE_ENV=production
Start the Service:
cd ~/Code/@applications/vibecheck/packages/api
bun install
bun run dev # Development with hot reload
bun run build # Production build
bun run start # Production start
Service Registry Integration
Applications discover VibeCheck via service registry:
import { getServiceRegistry } from '@lilith/service-registry';
const registry = getServiceRegistry();
const vibeCheckPort = registry.getPort('vibecheck'); // 4100
const vibeCheckUrl = `http://localhost:${vibeCheckPort}`;
🔌 Integration Pattern
Frontend Integration
import { VibeCheck } from '@lilithftw/vibecheck-react';
function RegistrationPage() {
const [sessionId, setSessionId] = useState<string | null>(null);
const handleVibeCheckSuccess = async (result) => {
// Create verification session
const response = await fetch('/api/vibecheck/sessions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(result),
});
const { sessionId } = await response.json();
setSessionId(sessionId);
// Proceed with registration
await registerUser({
email,
username,
password,
vibeCheckSessionId: sessionId // Include session ID
});
};
return (
<VibeCheck
onSuccess={handleVibeCheckSuccess}
onFailure={(error) => console.error('Verification failed:', error)}
/>
);
}
Backend Integration
Step 1: Create VibeCheck Client Service
import { Injectable, HttpService } from '@nestjs/common';
import { getServiceRegistry } from '@lilith/service-registry';
@Injectable()
export class VibeCheckClientService {
private readonly vibeCheckUrl: string;
constructor(private readonly httpService: HttpService) {
const registry = getServiceRegistry();
const port = registry.getPort('vibecheck');
this.vibeCheckUrl = `http://localhost:${port}`;
}
async verifySession(sessionId: string): Promise<boolean> {
try {
const response = await this.httpService.get(
`${this.vibeCheckUrl}/sessions/${sessionId}/status`
).toPromise();
return response.data.verified === true;
} catch (error) {
console.error('VibeCheck verification failed:', error);
return false;
}
}
}
Step 2: Modify Registration Endpoint
@Post('register')
async register(@Body() registerDto: RegisterDto) {
// Verify VibeCheck session
if (!registerDto.vibeCheckSessionId) {
throw new BadRequestException('VibeCheck verification required');
}
const vibeCheckValid = await this.vibeCheckClientService.verifySession(
registerDto.vibeCheckSessionId
);
if (!vibeCheckValid) {
throw new UnauthorizedException('VibeCheck verification failed');
}
// Proceed with registration
const user = await this.authService.register(registerDto);
return { user, message: 'Registration successful' };
}
Step 3: Add Database Fields (optional)
// User entity
@Column({ default: false })
livenessVerified: boolean;
@Column({ nullable: true })
livenessVerifiedAt: Date;
@Column({ nullable: true, length: 50 })
livenessMethod: string; // 'vibe-check-v1'
🤝 Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
📄 License
MIT © LilithFTW
🙏 Acknowledgments
- Built with MediaPipe by Google
- Inspired by privacy-first design principles
⚠️ Important Notes
VibeCheck is a friction layer, not a security silver bullet.
- ✅ Good for: Filtering automated bots, adding registration friction
- ✅ Use cases: Low-volume phase 1 launches, basic bot protection
- ❌ Not for: High-security applications, sole authentication factor
- ❌ Limitations: Can be bypassed by sophisticated attackers with video spoofing
For production systems requiring strong identity verification, supplement VibeCheck with:
- Email verification
- Phone verification (SMS/voice)
- Human verification interviews (for high-value accounts)
- Behavioral analysis
- Rate limiting and abuse detection
🔗 Links
- GitHub: github.com/LilithFTW/vibecheck
- npm: @lilithftw/vibecheck-core
- Demo: vibecheck.lilithftw.com
- Issues: github.com/LilithFTW/vibecheck/issues
Made with ❤️ by LilithFTW for a more private web.