← Back to list

Don’t replace your tech leads with AI

The case for humans — why you should not replace your senior developers with AI.

Conrad in Stackademic · 2025-12-12 15:17 · 20 claps · 5.9 min read
#software-development #startup #programming #leadership #artificial-intelligence
Open on Medium ↗
Wiki topics: AI · AI · General STP · Startups & Venture BIZ · Business Strategy 💻 · Programming

Don’t replace your tech leads with AI

The case for humans — why you should not replace your senior developers with AI.

TL;DR:

Recently I was let go from my first ever startup that I co-founded and worked at for the last five years. With new management in place my value as a tech lead was perceived no longer — same goes for my co-founder. For legal reasons we had to check the code the junior developers pushed after we left and we found two critical security vulnerabilities that allow anyone to charge any customer’s credit card and take over accounts with a throwaway email address. These are textbook examples for junior mistakes that should have been caught in code review — but there were no seniors left to catch them.

We obviously informed the company prior to releasing this. They apparently fixed one of the issues, hid the other one and didn’t reply to our inquiry.

Since ChatGPT was launched, the market for junior developers has collapsed. While the search for senior developers experienced a recovery back to pre-LLM levels, graduates continue struggling to find work.

Canaries in the Coal Mine? Standford Study from August, 2025

Canaries in the Coal Mine? Standford Study from August, 2025

That being said, our startup hired two entry level positions in 2024 as we set up the team for a new product. Over six months, we developed a new product and shipped a beta in January 2025. I really enjoyed working with the team and the developers, who wrote much of the code for the new product, while my co-founder and I focused on code review for the new and maintenance of the old product.

2025 began with the appointment of a new CEO, as tension developed between an investor and the previous one. The new CEO had a lot of enthusiasm, but didn’t work in tech or in a startup or as a CEO before. After four months and some shenanigans that warrant an additional article it was clear we had to leave the company.

The investor didn’t see much value in our positions, so we had to go in May of this year. Typical for a startup we wore many hats including but not limited to:

  • Team Lead
  • Product Owner (wrote the tickets, managed the backlog but also the assignments)
  • Frontend & Backend development
  • Hardware engineering (the product had an IoT component)
  • QA (mostly manual, but also some automated tests)
  • DevOps & IT infrastructure (AWS for the application, but also Google Workspace etc.)
  • Customer support and onboarding

And a bunch more. Nobody replaced these. Or at least not a person.

I’m neither an AI advocate nor a critic — it’s a tool like a hammer, useful or harmful depending on how it’s wielded, with advantages and disadvantages. Hiring can be a daunting task, so I can sympathise with the desire to replace or at least bridge the position using AI. In this case however there were no open positions and there still aren’t any six months later, so they didn’t even try to find someone.

After I left, I discovered Claude Code which writes a lot of code for me now. Prototyping is easier and faster, as well as writing repetitive and tedious code. Obviously one thing that I always do is to check the code that was generated. Sometimes I fix things myself, sometimes I ask the program to change the code to fit my requirements. It is very much a hands-on process, to see why, you only need to take a look at example after example after example.

By now, you can probably guess what happened next. Due to legal requirements, we were ordered to review the code changes made after our leaving. We found two major security flaws.

Let me be clear: these are textbook junior mistakes — the exact kind that senior developers should catch in code review before anything reaches production. I’m not at all blaming the developers who wrote the code. When you’re a junior, you’re supposed to make these mistakes, get feedback from a senior or teammate, fix them, and learn. That’s how you grow.

But we’re not on the team anymore. So maybe this article can serve as the feedback they didn’t get.

Budget and time were always tight, so the system already had built-in weaknesses:

  • The API including spec file are both public (“too expensive” to invest the 4 hours in setting up the proxy).
  • There was no security audit (also too expensive).
  • All users are admins (avoid complexity and save development time).
  • Some endpoints had permission checks, but no consistency or process.
  • Application has a free tier, so getting a bearer token is easy using a disposable email.

These were pragmatic trade-offs, though not all of them made sense even at the time — we told the CEO as much.

You might think I’m exaggerating when I say the newly built-in ones are “massive flaws.” Let me show you I am not:

  1. As a newly registered user, I can create a Stripe checkout session and charge it to ANY customer’s stored credit card.
  2. As that same user, I can invite myself to ANY customer’s account. Since all users are admins, I can remove the legitimate users and take complete control of their account.

A “newly registered user” means exactly what it sounds like: a throwaway email address and a password. No credit card, no name, no verification. That’s all it takes to steal money and to take over the entire system.

The first exploit

When we first built the stripe functionality we accidentally exposed the stripe private key in the frontend. A security researcher caught it and notified us automatically. I revoked the key to avoid further harm, but as this happened during our handover process, the juniors then built the new checkout system after we already left.

Spec file for the new stripe endpoints

Spec file for the new stripe endpoints

When they built the new endpoints to replace the old frontend functionality, they didn’t implement any permission checks. This is exactly the kind of mistake we would have caught in code review — but we weren’t there anymore.

Creating a fraudulent checkout session requires just three things: a payment method type (pick one from the stripe docs), line items (available via the public product_list endpoint), and a customer ID. That’s it. The system never checks whether you have any relationship to that customer.

My colleague created a quick video showing how easy this is — no special tools, no technical expertise required. Just the customer ID.

[embed]

So the only thing standing between an attacker and this exploit is the customer ID. As there is no throttling (deemed too expensive to implement) or preventive measure, you could just guess it. If you ever were with the customer (say as an ex-employee) or were invited to join the customers account, you have this. We didn’t try to hide this in any way, as this was not supposed to be a security feature.

The consequences are severe: attackers can make purchases on behalf of any customer, and there’s no way to distinguish legitimate transactions from fraudulent ones.

The second exploit

The second exploit is just as critical — it allows complete account takeover. And it’s even simpler. Get a bearer token, authenticate, and POST an invite to any customer ID.

Once you’ve invited yourself, switch to the frontend and remove all the legitimate staff members. Done — the account is yours.

The root cause is identical to the first exploit: no verification that you have any relationship to the customer ID you’re targeting.

[embed]

The customer id in the video was obviously deleted prior to the release of this article and belonged to a test account that we created in advance. This was the production system nevertheless.

So what’s the takeaway? Use AI — but use it properly.

I don’t envy new graduates learning to code right now. Building intuition for what works, what doesn’t, and what’s secure has never been easy. But how do you develop that intuition when AI writes the code for you? If you’ve never struggled through implementations yourself, how do you even know what to prompt for? In this case a simple please add a permission check would have probably been enough.

I feel old writing about kids just learning to code

I feel old writing about kids just learning to code

For the non-technical decision makers reading this: please don’t stop hiring juniors. They need opportunities to learn and grow. But don’t underestimate the value of senior developers who seem to “just” attend meetings and review code. Those expensive developers are the ones who catch catastrophic mistakes before they reach production. Without them, you’re not saving money — you’re one step away from ruin.


메타데이터
post_id
88d38c7d63ea
slug
dont-replace-your-tech-leads-with-ai-88d38c7d63ea
url
https://blog.stackademic.com/dont-replace-your-tech-leads-with-ai-88d38c7d63ea
canonical_url
https://blog.stackademic.com/dont-replace-your-tech-leads-with-ai-88d38c7d63ea
author_url
https://medium.com/@creyd
status
ok
fetched_at
2026-07-14 06:26:04