Back to Blog

Top Security To-do for Your Vibe-coded App

2781 words
13 min read
Last updated March 19, 2025

Table of Contents

Top Security To-do for Your Vibe-coded App

Security is important for all online applications because Internet is crowded with automated bots, hackers and other bad actors. Vibe-coding with Cursor, Windsurf or similar editors usually generates a pretty good code which sometime may not use best security practices by default.

That is why knowing about simple security-related things is a must for vibe-coders before they deploy their vibe-coded app to the public.

These tips below focus on JavaScript or Python apps. Security is hard, but some small steps can really help and protect your vibe coded application quickly and effectively. Here are few practical ways to improve protection.

1) Protect Signup And Login Pages With Google Captcha Or Cloudflare Turnstile

Add a captcha on your login/signup pages. Captcha is a guardian checks every visitor if they are a robot or not and asks to complete a simple challenge like selecting images with fire hydrants or similar. That blocks most automated bots. Most popular are Google Captcha and Cloudflare Turnstile. Google Captcha is free and Cloudfare Turnstile has a free plan with up to 1 million verifications.

flowchart TB A[User tries to log in] --> B[Captcha challenge shown] B --> C[Captcha verified or invalid] C --> D[If valid, proceed to login]
Some coders adding their own simple "captcha" with showing a simple math question like “solve this: 3+9” (and user should enter 12 as a response) and it may help a bit. But advanced bots might bypass them. Proper captcha solutions like Google Captcha or Cloudflare Turnstile block large attacks.

2) Add A 1-3 Second Delay Before Login and Signup

This small delay can really slow down brute force attempts! It's a simple measure. The idea is that every small delay helps to deter bots and they can not do fast iterations of trying passwords again and again. It is not a perfect solution but it helps.

flowchart TB A[Login attempt] --> B[1-3 Second Delay] B --> C[Check credentials] C --> D{Login successful?} D -- Yes --> E[Log successful login]

What is also important, delay will slow down brute force attacks (i.e. when passwords are guessed by automated bots). If you do not have any delay, attackers can try unlimited number of passwords in one second which overload your app and make it unavailable for real users.

flowchart TB F[Without delay: Unlimited attempts per second] G[With delay: Limited to 1 attempt per 1-3 seconds] F --> G

3) Keep API Keys Off The Client Side Code

Never store API keys in front-end code! Place them on the server side code only. That way, attackers cannot see them by simply viewing the source code of your app in a browser (source code is visible in the browser when you right-click on the page and select "View Page Source"). If your front end needs data from a third-party API, route it through your server. This ensures keys stay hidden.

flowchart TB A[API Key Needed] --> B{Where to store?} B -->|Wrong| C[Frontend Code] B -->|Correct| D[Server-side Code in ENV] C --> E[Visible to Anyone] D --> F[Hidden from Users] E --> G[Security Risk!] F --> H[Secure Access]

What is ENV?</strong> ENV means "ENVironment" which is basically a set of variables stored in memory of your server machine. Ideally, you should not just store API keys directly hadrcoded in the server code but use so called "environment variables". It means that that API keys are not hardcoded in the server code but defined in variables like ENV["openai-api-key"] in your server machine. This way they are actually stored in memory of your server which is harder to hack even if source code of your server app is revealed.

flowchart TB A[API Keys] --> B{Storage Method} B -->|Bad Practice| C[Hardcoded in Server Code] B -->|Best Practice| D[ENVironment Variables] C --> E[Visible in Source Code] D --> F[Stored in Server Memory] E --> G[Vulnerable to Code Exposure] F --> H[Protected Even if Code Exposed]

4) Create A Denylist For IP Addresses

Prepare a quick method to log and block IP addresses or ranges by defining a so called denylist (it can be a plain text file with the list of IP addresses or ranges). If you see repeated attacks from certain IP addresses, add them to the denylist. This is not perfect but can slow down ongoing attacks. Many frameworks for Node, Python, Django, or Flask support an IP denylist approach.

flowchart TB A[Suspicious login attempts] --> B[Log IP addresses] B --> C[Review logs for patterns] C --> D[Add malicious IPs to denylist] D --> E[Server checks denylist before processing requests] E --> F{IP in denylist?} F -- Yes --> G[Block request] F -- No --> H[Process request normally]

How to know which IP addresses are attacking you? Maybe, they easiest way is to send yourself email with IP address used for login attempt when someone is trying to login to your app with wrong credentials. Make sure to setup a separate IMAP email account for sending these emails (do not use your personal or main email account for it!).

flowchart TB A[Failed login] --> B[Log IP] B --> C{Suspicious?} C -- Yes --> D[Email alert] C -- No --> E[Monitor] D --> F[Add to denylist if repeated]

5) Block Disposable Emails on Signup

There is a number of services like Mailinator, 10 Minute Email and others that are providing disposable email addresses. These addresses can be used by hackers or automated bots to signup on your app. So it is a good idea to block them by adding a check againt them into your signup flow and not allowing to signup with those email addresses.

In your signup flow, filter out addresses from known throwaway domains. Check this list on Github: disposable email blocklist. This helps reduce fake signups and spam accounts. Keep that list updated over time.

To extract email domain from email address, you can use a simple code:

For example, in Python:


def get_email_domain(email):
    return email.split('@')[-1]

in Javascript:


function getEmailDomain(email) {
    return email.split('@')[1];
}

or in Node.js:


const getEmailDomain = (email) => email.split('@')[1];
flowchart TB M[New user tries sign up] --> N[Email domain checked] N --> O{Disposable?} O -- Yes --> P[Reject user sign up] O -- No --> Q[Allow registration]

6) Protect Admin Dashboard By Using IP Allowlist

To prevent attackers from accessing your admin dashboard, you can simply define an allowlist of IP addresses or ranges you yourself personally use that are allowed to access it. This can be done by adding a check into the server code for admin area of your app via a function that checks the IP address against the allowlist before allowing access to the admin dashboard.

How to find IP address you have? Just visit whatismyip.com to see your IP address. Then, add it to the allowlist. Note that you can have multiple IP addresses (fixed internet connection, mobile internet connection, etc.), so you need to add all of them if you have more than one or the range of IPs you use.

flowchart TB A[Admin dashboard access attempt] --> B[IP address checked] B --> C{IP in allowlist?} C -- Yes --> D[Allow access] C -- No --> E[Block access]

7) Use Strong Passwords For Admin

Ensure that your admin accounts have strong passwords. Use a password manager to generate and store complex passwords. Regularly change admin passwords (just set a reminder to yourself to do it once in a while).

flowchart TB A[Create admin password] --> B[Minimum 12+ characters] B --> C[Mix of uppercase, lowercase, numbers, symbols] C --> D[No common words or patterns] D --> E[Unique password for each service] E --> F[Store password safely or Use password manager] F --> G[Regular password rotation]

Strong passwords are your first line of defense. For admin accounts your passwords should be at least 12-16 characters long! Avoid just using some common words or patterns or re-using the same password for different services. Each admin account should have a unique password! Again, use password manager to generate and store complex passwords.

flowchart TB A[Attacker] --> B[Common password list] B --> C[Try passwords like 'password123' or 'admin123'] C --> F[Automated script] F --> G[Attempt login] G --> H{Success?} H -- Yes --> I[Account compromised] H -- No --> B J --> G

This is why using common or easily guessable passwords is dangerous. Attackers use automated tools with publicly available dictionaries of almost all common passwords to quickly try thousands and thousands of known combinations. These lists start with the most obvious choices like "password", "admin", "12345", or combinations like "password123" or "admin2023".

8) Implement logging for failed login and admin login attempts

Implement logging for failed login and admin login attempts and write it to logs on a server. This helps you monitor and analyze potential attacks. You can use a simple logging function in your server code to log these events. For example, in Python, you can use the `logging` module. In Node.js, you can use the `winston` library or similar.

flowchart TB A[User/Admin Login attempt] --> B[Log event details] B --> C[Store IP address, timestamp, username used]

Proper logging helps you identify patterns of suspicious activity. Make sure to include relevant information like IP addresses, timestamps, and usernames in your logs. Later, once your app grows enough you may implement setting up alerts for when the number of failed login attempts exceeds a certain threshold (for example, 10 failed attempts in 10 minutes), which could indicate a brute force attach (i.e. someone is trying to guess your admin password) in progress.

9) Enable 2-factor authentication everywhere where supported

Last but not least, enable 2 factor authentication (aka 2FA) on all critical services you use for your app. Even a strong password along is not enough! Your hosting, your Gmail or Google Workspace account, any 3rd party services you use for LLM or AI - just enable 2FA everywhere it is supported even if it is not required! Hacks happen regularly even with big and large companies, and having 2FA enabled can protect your accounts with them.

flowchart TB A[2FA enabled] --> B[All critical services] B --> C[Hosting, email, LLM, AI] C --> D[2FA enabled] D --> E[Accounts Are Protected]

Start with enabling 2FA for your email on Gmail! Here is the guide for Gmail

Conclusion

These security tips help your vibe-coded JavaScript or Python app. They do not solve every issue. But they form a good baseline.

Frequently Asked Questions

1. Why should I use a captcha for signups?

It blocks automated bots from flooding your app with fake accounts.

2. Which is better: Google Captcha or math-based captchas?

Math-based captchas can be bypassed by simple bots. Google Captcha or Cloudflare Turnstile provide more advanced protection.

3. How does a 1-3 second delay slow brute force?

It makes each login attempt take longer. Attackers cannot quickly test many passwords.

4. Why should 2FA focus on developer accounts?

Dev or admin logins often access sensitive data. That is where attackers might aim first.

5. How do I block disposable email domains?

Check signups against an updated list of disposable domains. Reject those addresses.

6. Should I store API keys in client code?

No. They should only live on the server side. That way they are hidden from the public.

7. What does a denylist do?

It lets you block certain IP addresses or ranges. This is useful if you spot malicious traffic.

8. How do I set up an IP allowlist for my admin dashboard?

Find your IP address at whatismyip.com, then add it to your server's allowlist. Only these IPs will be able to access your admin area.

9. What makes a strong admin password?

Admin passwords should be at least 12-16 characters long with a mix of uppercase, lowercase, numbers, and symbols. Avoid common words and use a unique password for each service.

10. How can I monitor for potential attacks?

Set up alerts for failed login attempts that send you the IP address details. This helps identify patterns of malicious activity.

11. How can I keep my vibe-coded app secure?

Use the tips above and regularly update your dependencies to patch known security vulnerabilities. Use tools like npm audit (for Node.js) or safety (for Python) to check for vulnerabilities in your dependencies. Set up a schedule to review and update dependencies at least once a month.

12. Why should I enable 2FA for all services used with my vibe-coded app?

Enable two-factor authentication (2FA) on all services supporting your app - hosting platforms, email services, domain registrars, and code repositories. If attackers gain access to any of these services, they could compromise your entire application. 2FA significantly reduces this risk by requiring a second verification method beyond passwords.

Keywords

security vibe coding vibe-coded app website security google captcha cloudflare turnstile 2fa ip block disposable email block denylist dev/api accounts

About The Author

Ayodesk Team of Writers

Ayodesk Team of Writers

Experinced team of writers and marketers at Ayodesk