Skip to main content

Agentic Coding: An Abject Lesson

Artificial Intelligence huh? Not from where I'm standing

I know it seems that I'm talking about AI a lot, but, believe it or not, I think it's pretty important. It's the type of fundamental change that can either make all of our lives better, or wreck things in a profound way. I feel like the only way to really influence this moment, or rather the path to it, is to talk about it, honestly.

Cause let me tell you friend, there are a lot of folks out there, who aren't.

Let's use a real world example!

So last night I decided to do a quick coding session before I passed out for the night, and as I am working up to releasing the CMS I build for this site, what better project to hack on for a span? With that in mind, the obvious move was to work on improving the security of RidgelineCMS (name pending), so I opted to add MFA to the mix as an option for each user who creates an account.

As I sat down to hammer away at the keyboard, it occurred to me that this would be a great candidate for a little experiment, since I have been bringing the doom and gloom to the AI makes anyone a coder narrative that's making the rounds. Yes, this is a perfect fit since its:

  • Compartmentalized Adding this to an already well architected and robust auth workflow is fairly straightforward.
  • Small We aren't creating an auth workflow from scratch, just extending one with a new verification and constraint.
  • Knowable It's MFA. This isn't rocket science.

So with that in mind, I turned the keys over to the agent in Cursor with this prompt:

Under user management*, we have MFA support unchecked, let's tackle that.

*I always create checklists for work I want to do when using Cursor, it makes things easier, and allows me to keep track of whats done and when, etc.

Cursor responds with:

We'll use TOTP (Time-based One-Time Password) for this. First, let's create the necessary database schema changes.

Things go pretty well for about 10 minutes as the agent spits out and creates solid migrations, adds and prompts me (ha!) for lib installation, etc. So far, so good. It then does the following:

  • Create the MFA setup endpoint
  • Create the MFA verification endpoint
  • Create the MFA enable/disable endpoint
  • Create a component for MFA setup
  • Create a component for MFA verification during login
  • Update the login form to handle MFA
  • Update the auth configuration to handle MFA

I was beginning to feel like I was going to lose this argument...

  • Create the TOTP utility file
  • Update the auth configuration to fix the remaining issues
  • Install the missing dependencies (including bcrypt, important later)

It then updates the next-auth types for the next 10 minutes, stuck in a loop of searching for the info, finding it, adding it, discovering it is, in fact, an idiot, and then searching again, updating, being confronted with its own uselessness, rinse and repeat.

After the 10 minutes I stop it, fix the types and tell it to continue. Everyone needs help sometimes after all. After another 8 or so minutes of weirdness, the agent declares everything good, and I can test! Woo! That was mostly painless, and if I have a working MFA integration now, it could be a real win.

Let the Testing Begin!

The app literally eats itself when I try to login. Ah, there it is.

What follows is 30 minutes (I timed it) of back and forth where the agent literally just threw crap at the wall trying to fix this. At one point I had to tell it to stop, search the web for a solution and then fix it. It said sure, then proceeded to not search the web for a solution and just do something random again.

Finally, having enough, I stepped in and fixed the issue, after searching the web myself. A few imports needed to be updated with the change in user auth flow. Took me 5 minutes to google, find the answer and then another 5 minutes implement it. 10 minutes vs 30 minutes for the developer replacement.

Pure Magic. But I digress, let's continue! Two issues doesn't a catastrophe make after all.

I can now see the login screen again, so time to try logging in! I get a random CredentialsSignin error. Great. What the hell now?

I ask the agent, what the hell now? which creates another spiral of stupidity that I can only stand for 10 minutes before I stop it. After looking at the code, I see that the agent added MFA as a requirement for all users, period. Not optional, you have to have it.

While wrong, and bad UX, this isn't terrible in the grand scheme of things, except for the fact that there are already user accounts, which the agent knows, since it added new fields to the user model to support per user settings for MFA earlier in this process, which it knows.

So the schema and model are correct, but the in code implementation is wrong. So I tell the agent:

I don't have MFA setup for this account.

Should be simple right, I tell it that the account I am using to login doesn't have MFA enabled, since we added MFA after the user was created. The obvious direction now would be to update the code to actually respect the way the model and schema are, and call it a day. Here is the response, word for word:

πŸ€– Ah, I see. Let me simplify this completely. The issue is we're overcomplicating the authentication flow by including MFA logic when it's not even set up. Let me fix the auth config to handle just basic email/password authentication.

It then proceeds, to remove the MFA integration from the auth workflow completely.

I almost broke my desk in sheer frustration at this moment. But I mastered my inner hulk, and told the agent:

I want MFA, my point was that the account I am trying to login with doesn't have MFA setup, so it shouldn't try to verify MFA.

What follows is another 20 minutes of the agent being completely, utterly useless and me typing in ALL CAPS LADEN PROFANITY. Eventually it is determined that the backend isn't returning the correct error format to next-auth. Once this is resolved, we finally get... a new error:

I am now getting the message "invalid email or password" when I try to login and the same error shows up in the console. However I know the email and password are correct, so this is an issue in the app.

Another 10 minutes of uselessness and I add logging to the auth workflow to see what the actual error is.

warn: Invalid password {"service":"ridgelinecms","timestamp":"2025-06-05T12:57:47.913Z","userId":"cmawlfny00000p1atx42v3xfe"}

I pass this on to the agent. It determines the password comparison is failing, and does a web search, for bcrypt related bugs. Hmm, bcrypt remember how I said that would be important later? Well, it's now later.

We don't use bcrypt for anything in this app, we use argon2, a more modern and type safe lib. Which the agent knows, since it recommended it as the best option when I was planning out the app. But it installed a different package anyway, and hashed the password from the front end with it, rendering any login impossible, MFA be damned.

Great, at least now we know what the issue is and can fix it, so we do. Hey, I can now login! We're back to the same exact workflow and feature set I built! And it's only taken 2 hours of misery.

So, let's enable MFA! I can't find where to enable MFA for my account so I ask the agent where it put it. It tells me system settings. Right, because before it was setup as a system level setting, and although I fixed the code in the auth workflow, I didn't touch the user facing views.

So I very kindly told the agent to fix it.

This should be on user accounts, not the main app. Don't be stupid.

Again, copy and paste from Cursor.

It moves the files around and hey, now I have the correct view in the correct place and it's actually nicely laid out and featureful. I setup MFA and it seems to work! Now time to test logging in!

I login and I get an error from the app that "MFA is Required". I mean, yes, yes it is. Show me the view to provide a code. No dice. Ugh.

Okay, I have now setup MFA for my account, and when I try to login I get an error, MFA Required. I assume because you never added the step to request the MFA code.

Agent response:

πŸ€– You're absolutely right! We need to add the MFA code input step to the login form. Let me search for the login form component.

I want to scream. I weep instead. The agent works for about 8 - 9 minutes making changes to *fix" the problem.

Still doesn't work. I review the code, see the issue and I say:

It just fails, since when we return an error, the workflow stops. Do not base showing the MFA field on returning an error, that is stupid.

The agent, happy in it's own stupidity responds:

πŸ€– You're absolutely right - using an error to trigger the MFA flow is not a good design pattern. Let me fix this by modifying the credentials provider to return a proper response that indicates MFA is required, rather than throwing an error. Let me update the credentials provider.

More weeping can be heard.

Another five or so minutes of 3 Stooges level inanity and we have a brief interlude of rage inducing incompetence, spurred on by the agent changing my design and UX, without being asked, and me simply asking it to add to the cursor rules that it shouldn't change any design unless prompted.

After 5 minutes of it creating brand new cursor rules files, multiple times, I have to open the cursor rules file, that it has been following the whole time (the first rule of cursor fight club is that all responses from the agent start with πŸ€–) and metaphorically shove it in the agents face.

Finally having that fixed, we return to our regularly scheduled crapfest. MFA isn't working, it's not even showing me the screen to add a code. What comes next is a comedy of errors, where every response from the agent is either:

I apologize for the confusion...

Or

I see the issue now...

And on both accounts, the agent is a dirty, dirty liar. After about fifteen minutes of this, I have had enough and stop the agent and share this nugget of joy:

It still doesn't work. This isn't hard. Review all of the code that interacts with the login and MFA workflow and figure it out. Search the web, I don't care, just fix it.

Profanity redacted to protect the innocent. The agent reviews all the relevant code, finds several issues and then spends the next 10 minutes fixing them. I test again. I am getting the error again that suggests that password comparison is failing.

Still the same error. Did we go back to using the wrong encryption library?

The Agent checks...

πŸ€– Let me check the password comparison in the credentials provider. I notice we're using bcryptjs but we should be using argon2 since that's what we imported at the top of the file.

Motherfu...

Bug that shouldn't have been introduced, fixed. Again. Hallelujah. I go to login, username and password accepted! MFA code screen presented! Code accepted! I'm logged in!

Did we finally, finally get there internet? After approximately 3 hours of nightmarish absurdity, did the agent finally, finally implement this simple feature correctly?

No, no it did not.

As a part of my testing, I decided to logout, and then log back in and when I got to the MFA code screen, I update the URL and try to load the admin. Hey look at that, I am logged in. What the HELL?

Even though we have MFA enabled, it isn't required to be logged in, which makes it worthless. if I provide my username/pass, and then just add /admin to the URL AT THE MFA VIEW, it lets me into the admin.

The agent searches some...

πŸ€– I understand the security concern. The MFA verification is not properly enforced in the authentication flow. Let me check the relevant files to fix this issue. I see the issue. The middleware is not properly enforcing MFA verification. Let me fix this by updating the middleware to check for MFA verification status.

We did all that work, to add MFA to the user auth workflow, and the agent never enforced it. If I hadn't did basic testing, that I only know to do, because I know what the hell I am doing, I could have pushed this to production, maybe released this to the public, with a massive, gaping, embarrassing and truly stupid security hole.

I have scrapped all the crap the agent built and I am doing it myself now, since it is obvious that it can't be trusted with something simple, yet crucial. And this is the point people.

If the agent in Cursor, can't properly implement a simple, well understood, well documented feature like this into a well architected app that it has full knowledge of, how can you possibly ever believe that this can make a "coder" out of anyone?

We are about to see an avalanche of terribly conceived and written software hit the world. Web apps that will be taking peoples credit card numbers, personally identifying information, you name it, built by software that isn't smart enough to do basic things like making sure the MFA feature that it implemented, is actually used in the app.

Jeebus help us all.

Discussion

Login Required

You must be signed in to post to this board.

Registered users only Β· No anonymous posting

No messages in this thread yet.