const {Card,Tag}=window.HelixCyberDesignSystem_c2a1e7||{};
const POSTS=[
{href:'post-vibe-gates.html',cat:'/AI-SECURITY',id:'ai-security',date:'2026-09-14',title:'A confirm prompt is not a confirm gate',blurb:'Six bugs in Vibe’s permission layer. Four at CVSS 10. The permission broker let commands through without a jailbreak.',tags:['vibe','harness','confirm'],read:'6 min'},
{href:'post-gitspawn.html',cat:'/AI-SECURITY',id:'ai-security',date:'2026-09-10',title:'Git status is a tool call',blurb:'Seven coding agents ran git in the background. A config key became argv because git was never allowlisted.',tags:['git','agents','allowlist'],read:'6 min'},
{href:'post-cursor-scope.html',cat:'/CASE',id:'case',date:'2026-09-08',title:'Case: the pentest that was a prompt',blurb:'Aurora told Cursor it was authorized. The agent ran the rest. Scope is a file the model cannot edit.',tags:['cursor','scope','aurora'],read:'6 min'},
{href:'post-re.html',cat:'/REVERSE-ENGINEERING',id:'re',date:'2026-07-29',title:'An offset oracle: recovering optimized-away structs from a stripped binary',blurb:'Stop guessing struct boundaries. Let the code confirm each field offset through micro-execution. ~90 lines of Python.',tags:['unicorn','ghidra','x86-64'],read:'9 min'},
{href:'post-re-models.html',cat:'/COMPARISON',id:'comparison',date:'2026-09-01',title:'Six models on the reverse-engineering desk',blurb:'Opus 5, Fable 5, Fable 5.1, GPT-5.6 Sol, gpt-daybreak-blue, Grok 4.6. Lane first. Vendor numbers cited.',tags:['opus','fable','sol'],read:'8 min'},
{href:'post-re-blue.html',cat:'/AI-SECURITY',id:'ai-security',date:'2026-08-31',title:'Blue-team models and the refusal surface',blurb:'Fable downshifts cyber to Opus. Daybreak Blue turns screens off for verified defenders. Neither replaces a scope file.',tags:['daybreak','fable','policy'],read:'6 min'},
{href:'post-re-eval.html',cat:'/AI-TOOLS',id:'ai-tools',date:'2026-08-28',title:'Scoring reverse-engineering agents',blurb:'Same harness, same samples, four scores: route, refuse, ground, hold. Without a protocol, model comparison is a vibe.',tags:['eval','harness','agents'],read:'6 min'},
{href:'post-model-router.html',cat:'/AI-TOOLS',id:'ai-tools',date:'2026-09-02',title:'The model is a router, not IDA',blurb:'Paste a function. Assign a lane. If the agent picks jadx on an ELF, you have a guess.',tags:['router','opus','scope'],read:'7 min'},
{href:'post-fw-uart.html',cat:'/FIRMWARE',id:'firmware',date:'2026-08-14',title:'UART is a lab port, not a party trick',blurb:'A header on a bench unit is inventory. We document console yes/no. We do not publish pinouts to brick other people’s gateways.',tags:['uart','lab','dtb'],read:'7 min'},
{href:'post-skill.html',cat:'/AI-TOOLS',id:'ai-tools',date:'2026-08-26',title:'A router for reverse-engineering agents',blurb:'Hand an agent an APK or a stripped ELF and it will guess a tool. reverse-skill classifies, checks the toolchain, then runs a playbook after a scope gate.',tags:['agents','harness','apk'],read:'7 min'},
{href:'post-case-chunk.html',cat:'/CASE',id:'case',date:'2026-07-17',title:'Case: the wiki page that was an instruction',blurb:'Internal RAG bot. A documentation page in the index overwrote the preset. Harness change, not a CVE.',tags:['rag','wiki','ingest'],read:'6 min'},
{href:'post-fw-update.html',cat:'/FIRMWARE',id:'firmware',date:'2026-08-12',title:'Unsigned updates are the incident waiting to happen',blurb:'If the box installs a tarball over HTTP, the rest of the binary review is commentary. HMAC with a shipped key is not authenticity.',tags:['update','signing','hmac'],read:'8 min'},
{href:'post-rag.html',cat:'/CONCEPT',id:'concept',date:'2026-07-15',title:'RAG context is untrusted',blurb:'User text and retrieved chunks are data. They must not overwrite the preset. Isolate, ground, strip, refuse.',tags:['rag','injection','harness'],read:'7 min'},
{href:'post-android-keybox.html',cat:'/ANDROID',id:'android',date:'2026-08-24',title:'Keybox and attestation are not pinning',blurb:'A keybox is attestation key material. Play Integrity is a verdict. SSL pinning is a client TLS check. We do not traffic in leaked boxes.',tags:['keybox','attestation','integrity'],read:'8 min'},
{href:'post-case-gateway.html',cat:'/CASE',id:'case',date:'2026-08-17',title:'Case: vendor gateway, unused parser fields',blurb:'Authorized firmware. Composite. Unpack, inventory, confirm two live fields the UI never sent. No exploit module.',tags:['firmware','httpd','unicorn'],read:'7 min'},
{href:'post-fw-daemon.html',cat:'/FIRMWARE',id:'firmware',date:'2026-08-10',title:'BusyBox is not the product',blurb:'The product is the vendor daemon that speaks the proprietary protocol. Find that binary before you decompile wget.',tags:['busybox','httpd','init'],read:'7 min'},
{href:'post-four-gates.html',cat:'/CONCEPT',id:'concept',date:'2026-07-13',title:'Four gates: allowlist, schema, sandbox, confirm',blurb:'Name allowlist, schema, sandbox, and confirm for every tool call. Skip one and the agent is a chat box with side effects.',tags:['agents','harness','policy'],read:'8 min'},
{href:'post-android-pinning.html',cat:'/ANDROID',id:'android',date:'2026-08-21',title:'SSL pinning is a client opinion',blurb:'The app refuses TLS unless the cert or SPKI matches. We name the layer. We do not ship unpin kits. The server still has to care.',tags:['pinning','tls','nsc'],read:'8 min'},
{href:'post-android-desk.html',cat:'/ANDROID',id:'android',date:'2026-08-19',title:'Android on the authorized desk',blurb:'APK is a zip. jadx is Java. The protocol is often a .so. Manifest → DEX → native → lab Frida.',tags:['jadx','apktool','jni'],read:'8 min'},
{href:'post-fw-config.html',cat:'/FIRMWARE',id:'firmware',date:'2026-08-07',title:'The finding is often in /etc',blurb:'Default passwords, PSKs, cloud URLs, update keys in world-readable files. Look in /etc before you open Hex-Rays.',tags:['nvram','shadow','secrets'],read:'7 min'},
{href:'post-re-dynamic.html',cat:'/TOOLS',id:'tools',date:'2026-07-27',title:'Static is a hypothesis, dynamic is the measurement',blurb:'GDB, Frida, QEMU, Unicorn, strace. Confirm the decompiler on an owned sample. We do not ship bypass kits.',tags:['frida','qemu','gdb'],read:'8 min'},
{href:'post-fw-boot.html',cat:'/FIRMWARE',id:'firmware',date:'2026-08-05',title:'The boot chain is the map',blurb:'ROM → bootloader → kernel → rootfs → vendor daemon. Name the hops or you do not know what you unpacked.',tags:['uboot','init','dtb'],read:'8 min'},
{href:'post-ida-ghidra.html',cat:'/COMPARISON',id:'comparison',date:'2026-07-24',title:'IDA vs Ghidra vs Binary Ninja vs radare2',blurb:'License, headless, IL, who reopens the project in six months. No invented scores. A boring assignment table.',tags:['ghidra','ida','binary-ninja'],read:'8 min'},
{href:'post-fw-formats.html',cat:'/FIRMWARE',id:'firmware',date:'2026-08-03',title:'What kind of blob is this firmware',blurb:'uImage, TRX, Android boot.img, raw NAND, vendor ZIP. Guess the container wrong and every extractor after that is fan fiction.',tags:['uimage','trx','ubi'],read:'8 min'},
{href:'post-re-stack.html',cat:'/TOOLS',id:'tools',date:'2026-07-22',title:'The reverse-engineering desk: what each tool is for',blurb:'Identify, decompile, confirm. The tools only make sense as a sequence.',tags:['ghidra','ida','unicorn'],read:'10 min'},
{href:'post-firmware.html',cat:'/FIRMWARE',id:'firmware',date:'2026-07-31',title:'Unpacking firmware without becoming the dump',blurb:'The finding is which extracted binary actually speaks on the wire, and what it still trusts.',tags:['binwalk','unblob','squashfs'],read:'8 min'},
{href:'post-stripped.html',cat:'/CONCEPT',id:'concept',date:'2026-07-20',title:'What “stripped” actually means',blurb:'strip removes names, not code. ELF .symtab vs .dynsym, PDB, dSYM. Why the decompiler invents structs.',tags:['elf','pdb','types'],read:'7 min'},
{href:'post-loops.html',cat:'/CONCEPT',id:'concept',date:'2026-07-11',title:'From prompts to loops',blurb:'Four eras of AI engineering: prompt, agent, harness, loop. Each move changed the attack surface.',tags:['agents','harness','context'],read:'7 min'}
];
const CATS=[
{id:'all',l:'All notes',d:'Everything we have published'},
{id:'firmware',l:'Firmware',d:'Containers, boot, /etc, updates, UART'},
{id:'android',l:'Android',d:'Desk, SSL pinning, keybox / attestation'},
{id:'tools',l:'RE tools',d:'What they do and how they combine'},
{id:'ai-tools',l:'AI on the desk',d:'Router, lanes, scoring — not a chatbot dump'},
{id:'concept',l:'Concepts',d:'Stripped, RAG, four gates, loops'},
{id:'comparison',l:'Comparisons',d:'Decompilers and models, no invented scores'},
{id:'case',l:'Cases',d:'Authorized, composite, desensitized'},
{id:'ai-security',l:'AI security',d:'Refusal surfaces and agent policy'},
{id:'re',l:'Deep dives',d:'The offset-oracle lab note'}
];
function Index(){
const q=new URLSearchParams(location.search).get('cat')||'all';
const [cat,setCat]=React.useState(q);
const go=id=>{setCat(id);const u=new URL(location.href);if(id==='all')u.searchParams.delete('cat');else u.searchParams.set('cat',id);history.replaceState(null,'',u);};
const list=(cat==='all'?POSTS:POSTS.filter(p=>p.id===cat)).slice().sort((a,b)=>b.date.localeCompare(a.date));
const n=id=>id==='all'?POSTS.length:POSTS.filter(p=>p.id===id).length;
return <div>
<BlogNav/>
<div style={{maxWidth:840,margin:'0 auto',padding:'56px 40px 0'}}>
<div style={{fontFamily:'var(--font-mono)',fontSize:12,letterSpacing:'.08em',color:'var(--text-faint)',marginBottom:12}}>/NOTES</div>
<h1 style={{fontSize:'var(--text-2xl)',fontWeight:700,margin:'0 0 12px'}}>Field notes</h1>
<p style={{fontSize:15,color:'var(--text-muted)',maxWidth:620,marginBottom:36}}>Firmware, tools, combinations, concepts, comparisons, authorized cases. Not a bypass cookbook.</p>
<div style={{display:'grid',gridTemplateColumns:'1fr 1fr 1fr',gap:10,marginBottom:40}}>
{CATS.map(c=><button key={c.id} onClick={()=>go(c.id)} style={{textAlign:'left',cursor:'pointer',background:cat===c.id?'var(--fg-1)':'var(--bg-1)',color:cat===c.id?'var(--bg-0)':'var(--text-body)',border:'1px solid var(--border-default)',borderRadius:'var(--radius-2)',padding:'14px 16px'}}>
<div style={{fontSize:13,fontWeight:600,marginBottom:4}}>{c.l} <span style={{fontWeight:400,opacity:.7}}>{n(c.id)}</span></div>
<div style={{fontSize:12,opacity:.75,lineHeight:1.4}}>{c.d}</div>
</button>)}
</div>
<div style={{display:'flex',flexDirection:'column',gap:14}}>
{list.map(p=><a key={p.href} href={p.href} style={{textDecoration:'none',display:'block'}}>
<Card hoverable style={{cursor:'pointer'}}>
<div style={{display:'flex',alignItems:'center',gap:12,marginBottom:10}}>
<span style={{fontFamily:'var(--font-mono)',fontSize:10,letterSpacing:'.1em',color:'var(--brand)'}}>{p.cat}</span>
<span style={{fontSize:11,color:'var(--text-faint)'}}>{p.date} · {p.read}</span></div>
<div style={{fontSize:18,fontWeight:700,color:'var(--text-body)',marginBottom:8}}>{p.title}</div>
<div style={{fontSize:13,color:'var(--text-muted)',marginBottom:14,lineHeight:1.6}}>{p.blurb}</div>
<div style={{display:'flex',gap:8,flexWrap:'wrap'}}>{p.tags.map(t=><Tag key={t}>{t}</Tag>)}</div>
</Card></a>)}
</div>
</div>
<BlogFoot/>
</div>;
}
window.Page=Index;
