The Narrative
So I was re-theming my website again- listen listen I know- but I promise its cooler this time! I had found a retro frutiger aero theme that looked really smooth and figured I could meld the two theme’s I’d worked on.
Given that my website is an extended resume of sorts I thought a cool feature would be to change the original theme’s Gallery pane into a gallery for my repositories on GitHub.
I’m not strictly a web-dev and I was prioritizing being on the other side of my re-theme so I opened copilot (Claude Sonnet 4).
The Problem
This is what it generated.

That looks pretty good! What’s the code look like?
// Create repository card HTML
function createRepoCard(repo) {
const card = document.createElement('div');
card.className = 'repo-card';
const lastUpdated = new Date(repo.updated_at).toLocaleDateString();
const language = repo.language || 'Unknown';
card.innerHTML = `
<h3 class="repo-card-title">${repo.name}</h3>
<p class="repo-card-description">${repo.description || 'No description available'}</p>
<div class="repo-card-footer">
<span class="repo-language">${language}</span>
<span class="repo-updated">Updated ${lastUpdated}</span>
<a href="${repo.html_url}" target="_blank" rel="noopener noreferrer">View on GitHub</a>
</div>
`;
return card;
}… oh no. Yeah, .innerHTML is not something that we want to see.
Seeing this gave me an idea though. Can I exploit this? we see that the title and the description are taken from the repo and placed directly into the html block for the card. Lets try to hit this sink from either of those sources!
We’ll use the following payload.
<img src=x onerror=alert('XSS')>It appears that there is a mitigation in GitHub for funky repo names.

That’s a plus, but what about the description?

That’s something! Back on the page we see this worked.


The Fix
To fix we’ll implement DOMpurify, which will look like this for example:
// Create elements safely without innerHTML
const title = document.createElement('h3');
title.className = 'repo-card-title';
title.textContent = repo.name;instead of:
card.innerHTML = `
<h3 class="repo-card-title">${repo.name}</h3>
...Now our card looks like this!

Takeaway
Audit your vibe code I guess.
As a job searcher right now lost in the milieu of exclusively staff and principal level job listings (unless you want to work for Palantir or Anduril) as the word is that AI is eating any roles lower than senior level- but simultaneously as someone who’s integrated AI into their workflow; Obviously I see some contradiction here.
I’m honestly not sure how to tread the ground between reactionary “AI IS GOING TO BREAK EVERYTHING” and the hype-blind “AI is going to create a post-work society”.
What I want is for engineers and architects to think more critically about the nature of our integrations.
Forbes reports from a NANDA paper (I’ve requested access and am waiting to hear back. I’m skeptical of anything that isn’t abundantly public about these things):
Despite the rush to integrate powerful new models, about 5% of AI pilot programs achieve rapid revenue acceleration; the vast majority stall, delivering little to no measurable impact on P&L
That is a 95% failure rate. This should scream hype to anyone who was alive during the blockchain era.
AI is a wildly interesting too, something that has allowed me to make and research things with a genuinely exciting depth and speed.
Lets refrain from making AI the next tech hype joke in a few years.