Exam Proctoring: Browser Lockdown & Crash Recovery
Students cheat. That's the reality of remote assessment. When a student takes a high-stakes exam from their bedroom on a spotty 3G connection, you cannot trust the browser, the network, or the operating system.
For EduAssess, a multi-tenant examination platform serving universities, I needed to solve three specific problems:
- The Alt-Tab problem: Students switching windows to search for answers.
- The Crash problem: Browsers freezing mid-exam, causing legitimate complaints and data loss.
- The Network Drop problem: Internet connections failing while the timer keeps ticking.
Here is how I engineered the solution.
Layer 1: Browser Lockdown
The first line of defense is aggressive OS-level interception within the web client. While a determined attacker with dev tools can bypass client-side checks, this catches 95% of casual cheating.
The exam session operates in a strict, forced-fullscreen environment:
beforeunloadevent prevents accidental tab closure with a confirmation dialog.visibilitychangeAPI detects tab focus loss. Any switch to another tab or application fires a violation event.- Keyboard listeners intercept
Alt-Tab,Ctrl+W,F11, and right-click context menus. - Clipboard operations (copy/paste) are completely blocked.
Violation severity engine: Instead of blindly failing a student for a single misclick, the system grades violations:
- Level 1 (Warning): Brief focus loss (< 2 seconds).
- Level 2 (Alert): Sustained focus loss, screen resize, or dev tools shortcut detected.
- Level 3 (Auto-submit): Repeated Level 2 violations or detection of remote screen sharing.
Every violation is timestamped, categorized, and pushed via WebSocket to the live proctor's dashboard.
Layer 2: Dual-Persistence Crash Recovery
If the browser crashes at question 49 of 50, and the student loses all their work, the platform has failed. We cannot rely on the server having the latest state if the network was lagging.
The solution is the Dual-Persistence Pattern:
javascriptfunction onAnswerChange(questionId, answer) { // 1. Write to local IndexedDB immediately (survives crashes) localDB.put('answers', { questionId, answer, timestamp: Date.now() }); // 2. Queue for server sync syncQueue.push({ endpoint: `/api/v2/session/${sessionId}/answer`, payload: { questionId, answer } }); }
The critical insight: Write locally first, sync to the server second.
The student's keystrokes are written to IndexedDB in real-time. This operation takes <5ms and never fails due to network issues.
When a student re-opens the exam after a crash:
- The client requests the last known state from
GET /api/v2/session/{id}. - The client compares the server state with the local
IndexedDBrecords. - It resolves conflicts using the timestamp — the most recent answer always wins.
- The student resumes exactly where they left off.
Layer 3: Offline-First Network Resilience
In environments with unstable infrastructure, exams must continue even when the internet drops.
A background sync worker monitors navigator.onLine.
- When the connection is lost, the sync queue simply pauses. The student can continue answering questions, completely unaware of the outage, as everything saves to
IndexedDB. - When connectivity returns, the sync worker replays all queued writes sequentially.
The Heartbeat Mechanism:
To ensure proctors know who is actually online, the client sends a POST /sync/heartbeat every 30 seconds.
- The response isn't just an HTTP 200; it contains remote commands.
- If the exam timer expires on the server, the heartbeat response returns
FORCE_SUBMIT, triggering the client to lock the UI and flush all remaining answers. - If a student's heartbeat stops for >2 minutes, their status on the proctor dashboard turns red ("Disconnected").
Layer 4: AI Webcam Monitoring
For visual proctoring, sending raw video feeds of 500 concurrent students to the server is prohibitively expensive and unnecessary.
Instead, I pushed the compute to the edge:
- A lightweight
TensorFlow.jsface detection model runs locally in the student's browser. - It processes video frames at 1 FPS to detect anomalies: no face detected, multiple faces, or face turned away from the screen.
- Only when an anomaly is detected does the client capture a JPEG snapshot and
POST /proctoring/snapshotto the server. - The proctor dashboard surfaces these snapshots in a live, filterable violation feed.
The Result
This isn't an enterprise desktop agent like Respondus — it's a lightweight, web-first approach. But by shifting persistence to the edge (IndexedDB) and compute to the client (TF.js), EduAssess delivers a highly resilient, cheat-resistant exam environment that works on budget hardware over 3G connections.
It solves the actual problems of remote assessment without the draconian cost of full video streaming.