Skip to content

Instantly share code, notes, and snippets.

@kevinpostal
Last active January 28, 2026 16:07
Show Gist options
  • Select an option

  • Save kevinpostal/f6bc00e364adc1419e29025abbd94e49 to your computer and use it in GitHub Desktop.

Select an option

Save kevinpostal/f6bc00e364adc1419e29025abbd94e49 to your computer and use it in GitHub Desktop.
AI Automation Detection POC
<!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