Beyond AI Guardrails and Refusals: Why LMS Platforms must own their Anti-Cheat Engines

Beyond AI Guardrails and Refusals: Why LMS Platforms must own their Anti-Cheat Engines

The OER Observatory aggregates and displays OER-related news and content from third-party sources worldwide. This content is not produced by UNESCO or the OER Dynamic Coalition. All rights and responsibility for the original content remain with the respective authors and publishers. The inclusion of third-party content in the Observatory does not imply endorsement by UNESCO or the OER Dynamic Coalition. Users can access the original source through the link provided with each item.

Beyond AI Guardrails and Refusals: Why LMS Platforms must own their Anti-Cheat Engines I have recently come to know that all the major frontier AI models like Gemini, Claude, ChatGPT etc. are no longer helping students "cheat" on various online learning platforms or LMSs like Coursera, Udemy, AWS Academy etc. This behavior is generally observed on these AI chatbots as polite refusals for solving screenshot-based assessment or exam questions from the aforementioned platforms. Leading AI platforms (OpenAI's ChatGPT, Anthropic's Claude, Google's Gemini) have tightened their policies around academic integrity. When users upload screenshots of assignments, online assessment (OA) questions, or exam papers, these models frequently refuse to generate direct solutions. What Are AI Guardrails and How Do They Work? This refusal behavior is managed using guardrails. In technical terms, an AI Guardrail is a programmable, infrastructure-level security and quality control mechanism that sits independently of an LLM's underlying model weights. In simple words a guardrail is the boundary line drawn by engineers defining what the AI is not allowed to do. In modern production LLM architecture, guardrails are classified by where they sit in the execution pipeline. Input Guardrails act as an API gateway filter. Incoming user text or image assets pass through lightweight classifiers, regex pattern matchers, or OCR engines to inspect the payload. Context Guardrails inject hard rules, boundary conditions, and negative constraints directly into the context window passed to the LLM (e.g., "System: You are an educational tutor. Never provide direct code solutions for exam questions."). Model-Level Guardrails are implemented during fine-tuning and Reinforcement Learning from Human Feedback (RLHF) loops, safety vectors inside the model recognize refusal triggers automatically when processing a request. Tools & Execution Guardrails are applied between the LLM output layer and external backend tools (APIs, databases, code execution sandboxes). When an agent requests a function call (like running generated code), these guardrails validate permission scopes and function arguments before execution occurs. Output Guardrails as the name suggest are applied after the LLM generates a response, but before it returns to the user interface. A secondary model or static filter reviews the drafted text/code. If toxic content, data leakage, or explicit solution leakage is detected, it drops the draft and returns a generic refusal message. While guardrails are the rules, Refusals are the actions performed while enforcing these rules. They are the actual output generated when a guardrail gets triggered. It's the polite decline the student sees in the chatbox (e.g., "I cannot assist with active exam questions..."). While this is a commendable push toward authentic learning, it creates a false sense of security for EdTech platforms. Students quickly figure out the basic crops, prompt tweaks, or rephrasing that can easily bypass these checks. Because AI guardrails sit on the vendor's servers, they can only analyze the text or image sent to them. They have zero visibility into the student's actual environment. They don't know if the student has 5 other browser tabs open, an extension running, or a secondary screen attached. That is why LMS platforms must build native, client-side anti-cheat engines instead of praying that an LLM refuses to answer. For the past few months I have been building JS-Mentor -- an open-source project that started as a simple web app and quickly evolved into a full-fledged, AI & ML-powered Learning Management System. As I was building the platform, I came across the question: How do we actually protect assessment integrity when third-party AI tools keep helping students take shortcuts ? Anatomy of Anti-Cheat Proctoring Engine The anti-cheat proctoring enforcement featured in JS-Mentor is a distributed system that relies on several different layers of the application to function correctly. Here is the exact breakdown: 1. src/hooks/useAntiCheat.js (The Core Engine) This custom hook handles all the global browser-level tracking: - Focus & Visibility tracking: ( visibilitychange ,blur ,pagehide ) - Hardware tracking: ( window.screen.isExtended ) - Viewport Layout tracking: (The dynamic ratio checks for docked Sidebars and DevTools) - Zero-Tolerance Console Trap: Overriding window.console to detecteval and Call Stack signatures to prevent JavaScript injection. - Global Keyboard/Menu Blocks: Disabling F12, DevTools shortcuts, and the right-click Context Menu globally. 2. src/components/common/ExerciseCompiler.js (The Code Editor Shield) Because we use the Monaco Editor and it has its own internal event system that overrides standard browser behavior, specific anti-cheat logic had to be injected directly into the editor lifecycle here: - Keystroke Dynamics (Macro Prevention): The logic that tracks timeDiff < 25ms and triggers the simulatedundo action is attached to Monaco'sonDidChangeModelContent event. - Strict Paste Blocking: Intercepting Ctrl+V /Cmd+V is bound to Monaco'sonKeyDown , and a capture-phase DOMpaste listener is attached directly to the editor's DOM node. - Editor Context Menu: Disabling the editor-specific right-click menu ( contextmenu: false in Monaco options). 3. src/pages/FinalExamPage.js (The Orchestrator & Enforcer) The hook just reports violations; the page component actually enforces the penalty: - Forced Fullscreen: The document.documentElement.requestFullscreen() call is triggered here when the "Begin Examination" button is clicked. - Penalty Enforcement: The onThresholdExceeded callback is implemented here, which actively locks the UI, sets thecheated state, and pushes the failed score/violation to the database vialogProgress . Additionally we disable the Source Maps in production. GENERATE_SOURCEMAP=false is enforced during the production build. This is critical because it ensures the useAntiCheat.js file is minified and unreadable in the browser's "Sources" tab, preventing anyone from easily reverse-engineering the detection logic. Handling Evasion Techniques and Edge Cases The Browser AI Sidebar Problem While web developers typically focus on client-side extensions or embedded web app chatbots, major browser vendors have quietly reshaped the digital workspace by embedding Large Language Models directly into the browser frame. These native assistants, called Browser AI Sidebars, run in parallel to web pages within the browser UI, giving users immediate access to summaries, page explanations and instant code solutions without having to leave their active tab. This shift gained momentum in 2023, kickstarted by Microsoft's launch of the Copilot sidebar in Edge (March 2023), followed quickly by Opera One's Aria (May 2023), Brave's Leo (November 2023), and Google Chrome's recently integrated Gemini side panel. These AI assistants operate outside the Document Object Model (DOM) of individual web applications, creating a hidden, unique challenge to online assessment integrity -- they can read and engage with live test questions without generating standard web-app security events. When analyzing how such native AI tools interact with a web page, the physical layout and rendering mode of the browser sidebar play a huge role. From a frontend security perspective, browser AI sidebars generally fall into three distinct UI rendering types: Docked, Overlay/Drawer, and Floating/Detached. 1. Docked or Pinned Sidebars Docked sidebars lock directly into the browser interface on the left or right side of the screen. When toggled open, this panel resizes the actual rendering viewport of the web application, forcing the main page content to contract horizontally. Native browser features like Microsoft Edge's Copilot Sidebar, Brave Leo, Opera Aria, and Chrome's Gemini side panel follow this design. From a security and detection standpoint, because opening a docked panel shrinks the rendering canvas, it fires a window resize event and changes the page's viewport aspect ratio (width / height). This allows developers to detect sidebar activity through client-side layout monitoring without needing to rely on tab-switching events. 2. Overlay or Slide-Over Drawers Overlay drawers slide out from the side or top of the screen as a high z-index layer, hovering directly over the web application without altering the underlying viewport dimensions. You frequently see this approach in custom web extension drawers -- such as Harpa AI, Merlin, or Monica -- as well as slide-up AI panels on mobile browsers. Because the viewport dimensions remain unchanged and the primary application window retains active focus, standard resize or blur listeners will not fire. Detecting an overlay requires more advanced techniques, such as intercepting layout occlusion, performing element visibility checks, or deploying DOM mutation observers. 3. Floating Widgets and OS Overlays Floating overlays function as completely independent, draggable bubbles or small windows that sit anywhere on top of the browser screen. Common examples include the ChatGPT and Claude desktop overlays, as well as floating action buttons injected by various browser extensions. These operate entirely outside the browser DOM context or run as secondary desktop windows. As a result, they leave no trace on client-side event listeners and will not trigger resize , visibilitychange , or blur events unless the user explicitly clicks away from the browser window. Multi-Monitor & Casting Exploitation A common way candidates attempt to bypass proctoring controls is by keeping the primary assessment window focused in full-screen mode while connecting a secondary monitor or casting their display to review documentation or consult AI tools. Malicious JavaScript Injection To cheat, one can open a detached DevTools window and attempt to inject custom JavaScript directly into the console. The goal is to manually overwrite certain state variables, forcefully unlock the compiler, or evaluate hidden window properties to extract the correct quiz answers without triggering standard DOM events. Under the Hood: The useAntiCheat Custom Proctoring Hook export const useAntiCheat = ({ enabled = true, resetKey = null, onViolation = () => {}, onThresholdExceeded = () => {}, cooldown = 1000, maxWarnings = 3, }) => { const [warningCount, setWarningCount] = useState(0); const [isSidebarBlocked, setIsSidebarBlocked] = useState(false); const [showWarningAlert, setShowWarningAlert] = useState(false); const lastHandledRef = useRef(0); const warningCountRef = useRef(0); // Keep refs updated to prevent closure stale state in event listeners const onViolationRef = useRef(onViolation); const onThresholdExceededRef = useRef(onThresholdExceeded); useEffect(() => { onViolationRef.current = onViolation; onThresholdExceededRef.current = onThresholdExceeded; }); // Sync warningCount ref useEffect(() => { warningCountRef.current = warningCount; }, [warningCount]); // Reset states when resetKey or enabled changes useEffect(() => { setWarningCount(0); setIsSidebarBlocked(false); setShowWarningAlert(false); lastHandledRef.current = 0; warningCountRef.current = 0; }, [resetKey, enabled]); useEffect(() => { if (!enabled) return; const handleSecurityEvent = (type, isCritical = false) => { const now = Date.now(); if (!isCritical && now - lastHandledRef.current < cooldown) return; lastHandledRef.current = now; const newCount = isCritical ? maxWarnings + 1 : warningCountRef.current + 1; setWarningCount(newCount); setShowWarningAlert(true); onViolationRef.current(type, newCount); if (newCount > maxWarnings) { onThresholdExceededRef.current(newCount); } }; // Multi-monitor Check if (window.screen && typeof window.screen.isExtended !== 'undefined') { if (window.screen.isExtended) { handleSecurityEvent('Multiple monitors detected'); } } // Intercept Console execution const originalConsole = { log: window.console.log, info: window.console.info, warn: window.console.warn, error: window.console.error, dir: window.console.dir, debug: window.console.debug, clear: window.console.clear }; const interceptConsole = (methodName) => { if (methodName === 'clear') return; window.console[methodName] = function(...args) { const err = new Error(); const stack = err.stack || ''; // Detect if executed from DevTools console or eval const isConsoleEval = stack.includes('') || stack.includes('eval') || stack.includes('at VM') || (stack && !stack.includes('.js') && !stack.includes('bundle') && !stack.includes('node_modules')); if (isConsoleEval) { handleSecurityEvent('Console execution', true); if (originalConsole.clear) { originalConsole.clear(); } return; } // Call original method if (originalConsole[methodName]) { originalConsole[methodName].apply(window.console, args); } }; }; Object.keys(originalConsole).forEach(interceptConsole); // initial values // Sidebar/DevTools Docked Check (Viewport ratio signatures) const baseWidthDiff = window.outerWidth - window.innerWidth; const baseHeightDiff = window.outerHeight - window.innerHeight; const checkSidebarOpen = () => { const widthRatio = window.innerWidth / window.outerWidth; const heightRatio = window.innerHeight / window.outerHeight; const widthDiff = window.outerWidth - window.innerWidth; const heightDiff = window.outerHeight - window.innerHeight; const widthDelta = widthDiff - baseWidthDiff; const heightDelta = heightDiff - baseHeightDiff; // Thresholds: // Docked to the side: widthRatio < 0.85 and absolute width difference > 150px // Docked to the bottom: heightRatio < 0.70 and absolute height difference > 250px const isSideDocked = widthRatio < 0.85 && widthDelta > 150; const isBottomDocked = heightRatio < 0.70 && heightDelta > 250; return isSideDocked || isBottomDocked; }; // Initial check const initialCheck = checkSidebarOpen(); if (initialCheck) { setIsSidebarBlocked(true); handleSecurityEvent('External panel/DevTools detected'); } let sidebarCurrentlyBlocked = initialCheck; // Visibility and Focus Change event handlers const handleVisibilityChange = () => { if (document.visibilityState === 'hidden') { handleSecurityEvent('Tab switch'); } }; const handleFullscreenChange = () => { if (!document.fullscreenElement) { handleSecurityEvent('Fullscreen exited'); } }; const handleBlur = () => { handleSecurityEvent('Window focus lost'); }; const handlePageHide = () => { handleSecurityEvent('Session hibernated or backgrounded'); }; const handleResize = () => { const isOpen = checkSidebarOpen(); setIsSidebarBlocked(isOpen); if (isOpen && !sidebarCurrentlyBlocked) { sidebarCurrentlyBlocked = true; handleSecurityEvent('External panel/DevTools detected'); } else if (!isOpen && sidebarCurrentlyBlocked) { sidebarCurrentlyBlocked = false; } }; // Keyboard and Context Menu prevention const handleKeyDown = (e) => { // Block F12 key if (e.key === 'F12') { e.preventDefault(); handleSecurityEvent('DevTools shortcut (F12)'); } // Block Ctrl+Shift+I, Ctrl+Shift+J, Ctrl+Shift+C, Ctrl+Shift+K if ((e.ctrlKey || e.metaKey) && e.shiftKey && ['I', 'J', 'C', 'K', 'i', 'j', 'c', 'k'].includes(e.key)) { e.preventDefault(); handleSecurityEvent('DevTools shortcut'); } // Block Ctrl+U (View Source) if ((e.ctrlKey || e.metaKey) && ['U', 'u'].includes(e.key)) { e.preventDefault(); handleSecurityEvent('View Source shortcut'); } }; const handleContextMenu = (e) => { e.preventDefault(); }; document.addEventListener('visibilitychange', handleVisibilityChange); document.addEventListener('fullscreenchange', handleFullscreenChange); window.addEventListener('blur', handleBlur); window.addEventListener('pagehide', handlePageHide); window.addEventListener('resize', handleResize); window.addEventListener('keydown', handleKeyDown, true); window.addEventListener('contextmenu', handleContextMenu, true); return () => { document.removeEventListener('visibilitychange', handleVisibilityChange); document.removeEventListener('fullscreenchange', handleFullscreenChange); window.removeEventListener('blur', handleBlur); window.removeEventListener('pagehide', handlePageHide); window.removeEventListener('resize', handleResize); window.removeEventListener('keydown', handleKeyDown, true); window.removeEventListener('contextmenu', handleContextMenu, true); // Restore original console methods Object.keys(originalConsole).forEach((methodName) => { window.console[methodName] = originalConsole[methodName]; }); }; }, [enabled, resetKey, cooldown, maxWarnings]); return { warningCount, setWarningCount, isSidebarBlocked, showWarningAlert, setShowWarningAlert, }; }; Core Security Mechanics & Edge Case Mitigation A. Forced Fullscreen & Exit Detection When beginning the final exam or opening an exercise, document.documentElement.requestFullscreen() is executed. This forces the browser to take over the user's entire physical screen, hiding other tabs and OS navigation bars. The engine also listens to the fullscreenchange event: const handleFullscreenChange = () => { if (!document.fullscreenElement) { handleSecurityEvent('Fullscreen exited'); } }; B. Focus & Visibility Monitoring The engine listens to core browser APIs to detect when a student navigates away from the workspace: visibilitychange (Page Visibility API): Captures when the tab is switched, minimized, or when the OS lock screen is activated.blur Event (Window Focus): Captures when the browser window loses focus, which occurs if the user clicks onto another screen, desktop application, or a browser dialog box (e.g., extension panels). C. Zero-Tolerance Console Interception To prevent students from running custom scripts or inspecting local variables, the engine overrides the global console methods (log , warn , error , etc.). - Signature Parsing: It inspects the call stack to detect evaluations originating from the DevTools console or an eval statement. - Zero-Tolerance Penalty: Unlike standard warnings, if console execution is detected, the engine triggers an immediate threshold violation (bypassing the 3-warning limit), instantly closing the workspace and marking the attempt as FAILED. const interceptConsole = (methodName) => { if (methodName === 'clear') return; window.console[methodName] = function(...args) { const err = new Error(); const stack = err.stack || ''; // Detect if executed from DevTools console or eval const isConsoleEval = stack.includes('') || stack.includes('eval') || stack.includes('at VM') || (stack && !stack.includes('.js') && !stack.includes('bundle') && !stack.includes('node_modules')); if (isConsoleEval) { handleSecurityEvent('Console execution', true); if (originalConsole.clear) { originalConsole.clear(); } return; } // Call original method if (originalConsole[methodName]) { originalConsole[methodName].apply(window.console, args); } }; }; D. DevTools Viewport Ratio Analysis Since native developer tools and browser sidebars do not trigger standard extension detectors, the engine evaluates coordinates and dimensions of the browser window frame vs. the document layout viewport. When the component mounts, the engine calculates the baseline difference between the inner document and the outer browser window: const baseWidthDiff = window.outerWidth - window.innerWidth; const baseHeightDiff = window.outerHeight - window.innerHeight; On resize events, the engine evaluates current ratios against the baseline delta to determine if the viewport has shrunk unnaturally: const widthRatio = window.innerWidth / window.outerWidth; const heightRatio = window.innerHeight / window.outerHeight; const widthDiff = window.outerWidth - window.innerWidth; const heightDiff = window.outerHeight - window.innerHeight; const widthDelta = widthDiff - baseWidthDiff; const heightDelta = heightDiff - baseHeightDiff; Redefining Evaluation: Why Proctoring Is Only Half the Battle If you're a developer, building such anti-cheat engines or client-side proctoring systems is great, and there is yet scope for making such engines more robust and resilient against cheating. But if you truly understand how this space works, you know at bottom it's a classic game of cat and mouse. No matter how many event listeners, viewport checks, or hardware APIs you put in place, students will eventually find new ways to bypass them. This isn't to say proctoring tools are obsolete -- far from it. Industry perspectives on digital integrity emphasize that robust proctoring engines play an indispensable frontline role in modern EdTech. They set clear operational boundaries, deter opportunistic cheating, preserve the value of certifications, and establish a foundational baseline of fairness for honest learners. However, relying solely on restrictive surveillance without evolving how we test creates an unsustainable arms race. Instead of stacking up endless proctoring constraints that ruin the student experience, we need to pair strong technical safeguards with redefined assessment design: - The Decline of Automated Policing: Recent reporting from Inside Higher Ed highlights how universities are increasingly moving away from automated third-party AI detectors due to high rates of false positives and unreliability. When platforms focus solely on catching cheats after the fact, honest students get caught in the crossfire while determined users bypass the rules anyway. - Institutional Shift to Authentic Tasks: Higher-ed leaders and institutional case studies -- such as multi-college initiatives examining AI integration and open-educational resources -- emphasize shifting away from static, easily spoofed assignments. Instead of asking for simple syntax regurgitation, institutions are adopting process-oriented evaluations like reflective code explanations, live oral defenses, and open-book contextual problem solving. - Process Dynamics over Final Outputs: Modern evaluation must measure how a student builds a solution rather than just inspecting the end binary result. In JS-Mentor, this philosophy directly guides our backend design. Telemetry from our client-side anti-cheat hook isn't just used to throw warning popups -- it feeds real-time behavioral data (such as keystroke dynamics, debugging iteration frequency, and code compilation times) directly into our machine learning risk model. The Future of Honest Learning The recent move by major AI providers to enforce academic integrity guardrails is a step in the right direction for promoting independent learning. But as developers, we cannot confuse third-party API refusals with true environment security. Vendor guardrails operate far away in remote data centers; they cannot see active viewports, secondary displays, or DOM paste actions in a student's workspace. Building an Anti-Cheat Proctoring Engine inside JS-Mentor taught me that protecting academic integrity requires owning the execution environment end-to-end. Client-side proctoring engines are a key part of the baseline deterrent -- locking the workspace, setting clear operational boundaries, and protecting a level playing field for honest learners. But client-side security is only half of the story. Technical evasion is a never-ending game of cat and mouse; piling on restrictive lockouts will never be a complete fix. The real way forward is to combine strong protection at the browser level with new process-oriented evaluation metrics. By evaluating how students solve problems -- measuring real-time iteration, cognitive friction, and behavioral dynamics -- we move beyond simple surveillance. Modern EdTech shouldn't aim to declare war on AI assistants, but rather to design intelligent learning systems that make authentic human effort the clearest, most rewarding path to success. References - Inside Higher Ed. How 5 Colleges Are Approaching AI (2026). 2. UCF Digital Learning. OER and Academic Integrity Case Study (2024). 3. Inside Higher Ed. AI Detectors Are Out, New Assessments Are In (2026) 4. EDULEGIT. Upholding Integrity in Digital Educational Spaces (2024) 5. Towards AI. LLM Guardrails and Safety in Production AI Systems (2026)