Last active
January 28, 2026 16:07
-
-
Save kevinpostal/f6bc00e364adc1419e29025abbd94e49 to your computer and use it in GitHub Desktop.
AI Automation Detection POC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AI Detection β OnBlur Ground Truth</title> | |
| <style> | |
| :root { | |
| --bg-primary: #0e1117; | |
| --bg-secondary: #161b22; | |
| --text-primary: #e6edf3; | |
| --text-secondary: #8b949e; | |
| --accent: #58a6ff; | |
| --human-color: #238636; | |
| --ai-color: #f85149; | |
| --uncertain-color: #d29922; | |
| --border-radius: 8px; | |
| --spacing-sm: 8px; | |
| --spacing-md: 12px; | |
| --spacing-lg: 16px; | |
| } | |
| * { margin:0;padding:0;box-sizing:border-box; } | |
| body { font-family:'SF Mono','Monaco','Inconsolata',monospace;background:var(--bg-primary);color:var(--text-primary);line-height:1.5;padding:var(--spacing-lg);max-width:1200px;margin:0 auto;} | |
| .container { display:flex;flex-direction:column;gap:var(--spacing-lg);} | |
| header { border-bottom:1px solid var(--bg-secondary);padding-bottom:var(--spacing-lg);} | |
| h1 { font-size:1.5rem;margin-bottom:var(--spacing-sm);color:var(--accent);} | |
| .subtitle { color:var(--text-secondary);font-size:0.9rem;} | |
| .controls { display:flex;gap:var(--spacing-md);align-items:center;flex-wrap:wrap;} | |
| button { background:var(--accent);color:white;border:none;padding:10px 20px;border-radius:var(--border-radius);cursor:pointer;font-family:inherit;font-size:0.9rem;font-weight:500;transition:all 0.2s ease;display:flex;align-items:center;gap:8px;} | |
| button:hover { opacity:0.9; transform:translateY(-1px);} | |
| button:active { transform:translateY(0);} | |
| button:disabled { opacity:0.5; cursor:not-allowed; transform:none;} | |
| .clear-btn { background:var(--bg-secondary); border:1px solid var(--text-secondary);} | |
| .status-indicator { height:10px;width:10px;border-radius:50%;background:var(--text-secondary);display:inline-block;margin-right:8px;} | |
| .status-indicator.active { background:var(--accent);animation:pulse 2s infinite;} | |
| @keyframes pulse {0%,100%{opacity:1;}50%{opacity:0.5;}} | |
| .results-grid { display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--spacing-lg);} | |
| .card { background:var(--bg-secondary);border-radius:var(--border-radius);padding:var(--spacing-lg);border:1px solid transparent;} | |
| .card-title { font-size:1rem;margin-bottom:var(--spacing-md);color:var(--text-secondary);display:flex;align-items:center;gap:8px;} | |
| .log-container { grid-column:1 / -1;} | |
| pre { background:rgba(0,0,0,0.3);padding:var(--spacing-lg);border-radius:var(--border-radius);white-space:pre-wrap;overflow:auto;max-height:400px;font-size:0.85rem;tab-size:2;} | |
| pre::-webkit-scrollbar { width:8px;height:8px;} | |
| pre::-webkit-scrollbar-track { background:var(--bg-primary);} | |
| pre::-webkit-scrollbar-thumb { background:var(--text-secondary);border-radius:4px;} | |
| .result-item { margin-bottom:var(--spacing-md);padding:var(--spacing-md);background:rgba(0,0,0,0.2);border-radius:6px;} | |
| .result-value { color:var(--accent);font-weight:500;} | |
| .classification-display { font-size:2rem;font-weight:bold;text-align:center;padding:var(--spacing-lg);border-radius:var(--border-radius);background:linear-gradient(135deg,var(--bg-primary) 0%,var(--bg-secondary) 100%);margin:var(--spacing-md) 0;} | |
| .classification-display.human { color:var(--human-color); background:linear-gradient(135deg, rgba(35,134,54,0.1) 0%, rgba(35,134,54,0.05) 100%); border:2px solid var(--human-color);} | |
| .classification-display.ai { color:var(--ai-color); background:linear-gradient(135deg, rgba(248,81,73,0.1) 0%, rgba(248,81,73,0.05) 100%); border:2px solid var(--ai-color);} | |
| .signal-list { list-style:none;} | |
| .signal-list li { padding:var(--spacing-sm) 0;border-bottom:1px solid rgba(255,255,255,0.1); display:flex;justify-content:space-between;align-items:center;} | |
| .signal-list li:last-child { border-bottom:none;} | |
| .signal-status { font-weight:500;padding:2px 8px;border-radius:4px;font-size:0.85rem;} | |
| .signal-status.positive { color:var(--human-color); background:rgba(35,134,54,0.1);} | |
| .signal-status.negative { color:var(--ai-color); background:rgba(248,81,73,0.1);} | |
| .signal-status.neutral { color:var(--text-secondary); background:rgba(139,148,158,0.1);} | |
| .confidence-meter { height:8px;background:rgba(255,255,255,0.1);border-radius:4px;margin:var(--spacing-sm) 0;overflow:hidden;} | |
| .confidence-fill { height:100%;border-radius:4px;transition:width 0.5s ease;} | |
| .confidence-fill.high { background:var(--human-color);} | |
| .confidence-fill.medium { background:var(--uncertain-color);} | |
| .confidence-fill.low { background:var(--ai-color);} | |
| footer { margin-top:var(--spacing-lg);padding-top:var(--spacing-lg);border-top:1px solid var(--bg-secondary);color:var(--text-secondary);font-size:0.8rem;text-align:center;} | |
| @media(max-width:768px){body{padding:var(--spacing-md);} | |
| .results-grid{grid-template-columns:1fr;} | |
| .controls{flex-direction:column;align-items:stretch;} | |
| button{width:100%;}} | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <header> | |
| <h1>π΅οΈ AI Detection - Blur-Based Ground Truth</h1> | |
| <p class="subtitle">Blur Detection = Human | No Blur = AI | Secondary Analysis for Info Only</p> | |
| </header> | |
| <div class="controls"> | |
| <button id="runBtn"><span class="status-indicator" id="statusIndicator"></span>Run Detection</button> | |
| <button id="clearBtn" class="clear-btn">Clear Log</button> | |
| </div> | |
| <div class="results-grid"> | |
| <div class="card" id="primaryCard"> | |
| <div class="card-title">π― Primary Detection (Blur)</div> | |
| <div id="primaryResults"><p>Blur detection is ground truth for human.</p></div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-title">π¬ Secondary Analysis (Diagnostics)</div> | |
| <div id="secondaryResults"><p>Always runs for info only.</p></div> | |
| </div> | |
| <div class="card log-container"> | |
| <div class="card-title">π Detection Log</div> | |
| <pre id="log">Ready. Click "Run Detection".</pre> | |
| </div> | |
| </div> | |
| <div class="card" id="resultCard"> | |
| <div class="card-title">π Final Classification</div> | |
| <div id="finalResults"><p>Results appear here.</p></div> | |
| </div> | |
| <footer> | |
| <p>Detection System v3.1 | Blur = Human, No Blur = AI</p> | |
| </footer> | |
| </div> | |
| <script src="https://cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@4/dist/fp.min.js"></script> | |
| <script> | |
| class HumanAIDetector { | |
| constructor(){ | |
| this.elements={runBtn:document.getElementById('runBtn'),clearBtn:document.getElementById('clearBtn'),log:document.getElementById('log'),statusIndicator:document.getElementById('statusIndicator'),primaryResults:document.getElementById('primaryResults'),secondaryResults:document.getElementById('secondaryResults'),finalResults:document.getElementById('finalResults'),resultCard:document.getElementById('resultCard')}; | |
| this.config={ | |
| uriSchemes:["mailto","vscode","slack","spotify","steam","zoommtg","discord","whatsapp","skype","teams","telegram","signal","linkedin","twitter","facebook","instagram","tiktok","snapchat","meet","calendar","outlook","onedrive","dropbox","github","gitlab","bitbucket","notion","obsidian","figma","zoom","webex","msteams","viber","wechat","line","moodle","jira","confluence","gmail","yahoo","yandex","protonmail","applemusic","itunes","photos","maps","camera","calculator"], | |
| probeDelay:400, | |
| cooldownDelay:200, | |
| jitterSamples:20, | |
| audioSamples:256 | |
| }; | |
| this.state={isRunning:false,blurDetected:false,blurCount:0}; | |
| this.init(); | |
| } | |
| init(){ | |
| this.elements.runBtn.addEventListener('click',()=>this.runDetection()); | |
| this.elements.clearBtn.addEventListener('click',()=>this.clearLog()); | |
| this.log('π§ System initialized.','info'); | |
| } | |
| log(msg,type='info'){ | |
| const ts=new Date().toLocaleTimeString(); | |
| const symbols={'info':'βΉοΈ','success':'β ','warning':'β οΈ','error':'β','detection':'π','human':'π€','ai':'π€'}; | |
| const sym=symbols[type]||'π'; | |
| this.elements.log.innerHTML+=`${sym} [${ts}] ${msg}\n`; | |
| this.elements.log.scrollTop=this.elements.log.scrollHeight; | |
| } | |
| clearLog(){ | |
| this.elements.log.textContent='Log cleared.\n'; | |
| this.elements.primaryResults.innerHTML='<p>Blur detection is ground truth for human.</p>'; | |
| this.elements.secondaryResults.innerHTML='<p>Always runs for info only.</p>'; | |
| this.elements.finalResults.innerHTML='<p>Results appear here.</p>'; | |
| this.elements.resultCard.className='card'; | |
| this.log('π Log cleared.','info'); | |
| } | |
| setRunning(r){ | |
| this.state.isRunning=r; | |
| this.elements.runBtn.disabled=r; | |
| this.elements.statusIndicator.classList.toggle('active',r); | |
| this.elements.runBtn.textContent=r?'Running Detection...':'Run Detection'; | |
| } | |
| async runDetection(){ | |
| if(this.state.isRunning) return; | |
| this.setRunning(true); | |
| this.log('π Starting detection...','detection'); | |
| this.state.blurDetected=false; | |
| this.state.blurCount=0; | |
| try{ | |
| const blurResults=await this.runBlurDetection(); | |
| this.state.blurDetected=blurResults.blurDetected; | |
| const sandboxResults=await this.runSandboxAnalysis(); | |
| const fingerprint=await this.runFingerprintAnalysis(); | |
| if(this.state.blurDetected){ | |
| this.displayHumanResult(blurResults); | |
| }else{ | |
| this.displayAIResult(blurResults); | |
| } | |
| }catch(e){this.log(`β Detection failed: ${e.message}`,'error');} | |
| finally{this.setRunning(false);} | |
| } | |
| async runBlurDetection(){ | |
| this.log('π― PRIMARY TEST: Checking blur...','detection'); | |
| const results=[]; | |
| let blurDetected=false; | |
| for(const scheme of this.config.uriSchemes){ | |
| const result=await this.testSchemeForBlur(scheme); | |
| results.push(result); | |
| if(result.blurred){blurDetected=true;this.state.blurCount++;this.log(`${scheme}: BLUR DETECTED`,'human');break;} | |
| else{this.log(`${scheme}: No blur detected`,'info');} | |
| await this.sleep(this.config.cooldownDelay); | |
| } | |
| this.displayBlurResults(results); | |
| return {blurDetected,results,blurCount:this.state.blurCount}; | |
| } | |
| async testSchemeForBlur(scheme){ | |
| return new Promise(resolve=>{ | |
| let blurred=false; | |
| const timeoutId=setTimeout(()=>{ | |
| window.removeEventListener('blur',onBlur); | |
| resolve({scheme,blurred}); | |
| },this.config.probeDelay); | |
| const onBlur=()=>{ | |
| blurred=true; | |
| clearTimeout(timeoutId); | |
| window.removeEventListener('blur',onBlur); | |
| resolve({scheme,blurred}); | |
| }; | |
| window.addEventListener('blur',onBlur,{once:false}); | |
| try{const original=location.href;location.href=`${scheme}://test`;setTimeout(()=>location.href=original,10);} | |
| catch{try{const iframe=document.createElement('iframe');iframe.style.display='none';iframe.src=`${scheme}://test`;document.body.appendChild(iframe);setTimeout(()=>iframe.remove(),100);} | |
| catch{const a=document.createElement('a');a.href=`${scheme}://test`;a.style.display='none';document.body.appendChild(a);a.click();setTimeout(()=>a.remove(),100);}}}); | |
| } | |
| displayBlurResults(results){ | |
| let html='<ul class="signal-list">'; | |
| let humanFound=false; | |
| results.forEach((r,i)=>{ | |
| const status=r.blurred?'positive':'neutral'; | |
| const icon=r.blurred?'β ':'β'; | |
| const text=r.blurred?'Human detected':'No blur'; | |
| html+=`<li><span>${icon} ${r.scheme}://</span><span class="signal-status ${status}">${text}</span></li>`; | |
| if(r.blurred) humanFound=true; | |
| if(humanFound && i<results.length-1){ | |
| for(let j=i+1;j<results.length;j++){html+=`<li><span>βοΈ ${results[j].scheme}://</span><span class="signal-status neutral">Skipped</span></li>`;} | |
| return; | |
| }}); | |
| html+='</ul>'; | |
| this.elements.primaryResults.innerHTML=html; | |
| } | |
| async runSandboxAnalysis(){ | |
| this.log('π¬ SECONDARY: Analyzing sandbox/automation signs...','detection'); | |
| const [jitter,audio,gl,perf]=await Promise.all([this.measureEventLoopJitter(),this.measureAudioEntropy(),this.getWebGLRenderer(),this.analyzePerformanceAPI()]); | |
| const results={jitter,audio,gl,perf}; | |
| this.displaySandboxResults(results); | |
| return results; | |
| } | |
| async measureEventLoopJitter(){try{const s=[];for(let i=0;i<this.config.jitterSamples;i++){const start=performance.now();await new Promise(r=>setTimeout(r,0));s.push(performance.now()-start);}const mean=s.reduce((a,b)=>a+b,0)/s.length;const variance=s.reduce((a,b)=>a+Math.pow(b-mean,2),0)/s.length;return{variance,samples:s.length,max:Math.max(...s)};}catch{return null;}} | |
| async measureAudioEntropy(){try{if(!window.AudioContext&&!window.webkitAudioContext)return null;const ctx=new (window.AudioContext||window.webkitAudioContext)();const osc=ctx.createOscillator();const gain=ctx.createGain();osc.connect(gain);gain.connect(ctx.destination);osc.frequency.setValueAtTime(440,ctx.currentTime);gain.gain.setValueAtTime(0.1,ctx.currentTime);osc.start();osc.stop(ctx.currentTime+0.05);return new Promise(r=>{osc.onended=()=>r({available:true,entropy:Math.random()});setTimeout(()=>r({available:false}),100);});}catch{return {available:false};}} | |
| getWebGLRenderer(){try{const c=document.createElement('canvas');const gl=c.getContext('webgl')||c.getContext('experimental-webgl');if(!gl)return null;return{renderer:gl.getParameter(gl.RENDERER),vendor:gl.getParameter(gl.VENDOR),version:gl.getParameter(gl.VERSION)};}catch{return null;}} | |
| analyzePerformanceAPI(){try{const p=performance;return{memory:p.memory||null,timing:p.timing?{loadTime:p.timing.loadEventEnd-p.timing.navigationStart,domReadyTime:p.timing.domContentLoadedEventEnd-p.timing.navigationStart}:null};}catch{return null;}} | |
| displaySandboxResults(r){let html='<div class="result-item">';if(r.jitter){const s=r.jitter.variance<0.00001?'negative':'positive';html+=`<div><strong>Event Loop Jitter:</strong> <span class="signal-status ${s}">${r.jitter.variance.toExponential(3)}</span></div>`;}if(r.audio){const s=r.audio.available?'positive':'negative';html+=`<div><strong>Audio Context:</strong> <span class="signal-status ${s}">${r.audio.available?'Available':'Unavailable'}</span></div>`;}if(r.gl){const isSoft=/swiftshader|llvmpipe|software/i.test(r.gl.renderer);html+=`<div><strong>WebGL Renderer:</strong> <span class="signal-status ${isSoft?'negative':'positive'}">${r.gl.renderer}</span></div>`;}html+='</div>';this.elements.secondaryResults.innerHTML=html;} | |
| async runFingerprintAnalysis(){this.log('π Running fingerprint analysis...','detection');try{const fp=await FingerprintJS.load();return await fp.get();}catch(e){this.log(`β οΈ Fingerprint failed: ${e.message}`,'warning');return null;}} | |
| displayHumanResult(blurResults){ | |
| this.elements.finalResults.innerHTML=`<div class="classification-display human">π€ HUMAN DETECTED (${blurResults.blurCount} blur event${blurResults.blurCount>1?'s':''})</div>`; | |
| this.elements.resultCard.className='card human'; | |
| this.log('π FINAL RESULT: HUMAN','success'); | |
| } | |
| displayAIResult(blurResults){ | |
| this.elements.finalResults.innerHTML=`<div class="classification-display ai">π€ AI DETECTED (No blur events)</div>`; | |
| this.elements.resultCard.className='card ai'; | |
| this.log('β οΈ FINAL RESULT: AI (no blur detected)','ai'); | |
| } | |
| sleep(ms){return new Promise(r=>setTimeout(r,ms));} | |
| } | |
| document.addEventListener('DOMContentLoaded',()=>{window.detector=new HumanAIDetector();}); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment