HOW TO SECURE AN EMERGENT APP

Emergent Security Context

Emergent is an agentic vibe-coding platform: you describe the app, an autonomous agent builds and deploys it — typically a React frontend, a FastAPI (Python) backend, and MongoDB — and hands you a public URL. That last part is the security context in one sentence. The agent takes you from prompt to deployed public URL in a single session, so there is no natural pause where hardening happens. The recurring shape we see is “the agent shipped it, I shared the link, nobody ever added the ownership checks.” The window between “deployed” and “hardened” is where incidents happen — the checklist below is how you close it before sharing the URL.

Security Checklist

1. Scope every MongoDB query to the current user

Agent-generated CRUD reads documents by ID without checking who owns them: db.items.find_one({"_id": item_id}). Any authenticated user who obtains or guesses another user’s document ID gets the document. Every query on user-scoped collections needs the owner in the filter:

doc = await db.items.find_one({"_id": item_id, "user_id": current_user.id})

This is BOLA, and it is the most common finding in AI-generated CRUD. See BOLA in AI-generated CRUD.

2. Add an auth dependency to every FastAPI route

FastAPI routes are public unless a dependency says otherwise, and generated routers often skip the dependency on half the endpoints. Attach it at the router level so a forgotten route fails closed:

router = APIRouter(dependencies=[Depends(get_current_user)])

Then audit the app for any router or standalone route created without it.

3. Fix the JWT signing secret

Generated auth code frequently ships with a weak or hardcoded signing secret (SECRET_KEY = "secret" or a value the agent invented and committed) and long-lived tokens. Replace it with a 32+ byte random value from environment config, pin the algorithm (algorithms=["HS256"] — never accept none), and cut token lifetime to hours, not weeks. See JWT alg:none and kid traversal for the decode-side failure modes.

4. Validate request bodies with Pydantic — strictly

FastAPI gives you Pydantic validation for free, but generated models are often permissive: dict fields, Optional[str] everywhere, no length caps. Tighten the models: bounded string lengths, constrained numbers, model_config = ConfigDict(extra="forbid") so unexpected fields (like role or is_admin) are rejected instead of silently passed to the update.

5. Strip role fields from user-editable updates

If the users collection has a role, is_admin, or plan field and the generated profile-update endpoint writes the whole request body with {"$set": body}, a user can promote themselves. Build the update dict from an explicit allowlist of fields server-side.

6. Move secrets out of the code

Agent-built apps accumulate pasted keys — OpenAI, Stripe, Mongo connection strings — as string literals in server.py or a committed .env. Grep the repo for sk-, sk_live_, mongodb+srv://, and AIza. Move everything to environment configuration in the platform’s settings, and rotate any key that ever appeared in source. The Token Leak Checker finds the ones that made it into the deployed frontend bundle.

7. Rate-limit auth and LLM-backed endpoints

There is no rate limiting unless you add it. Two endpoints need it most: login/signup (credential stuffing) and anything that calls an LLM on your API key (one user with a loop can run up your bill in minutes). Add slowapi or equivalent middleware with per-IP limits, and a per-user quota on LLM calls.

8. Return generic errors in production

FastAPI’s default behavior plus generated except Exception as e: return {"error": str(e)} handlers leak stack traces, file paths, and Mongo error strings to clients. Add a global exception handler that logs server-side and returns {"detail": "Internal server error"}. Confirm the app doesn’t run with --reload or debug tracebacks in production.

9. Lock down CORS

Generated FastAPI apps commonly ship allow_origins=["*"] with allow_credentials=True so the preview frontend works. Before sharing the URL, set allow_origins to your production domain only. See CORS credentials misconfig.

10. Validate file uploads

If the agent built an upload endpoint: cap the size, allowlist MIME types (by content sniff, not just header), and regenerate filenames server-side as UUIDs. The recurring bug is an “image upload” that accepts anything and serves it back from the app’s origin. See file upload zip-slip / XXE.

11. Sanitize user content before rendering

If user- or LLM-generated text renders as HTML or Markdown in the React frontend, sanitize before rendering. dangerouslySetInnerHTML on stored raw input is stored XSS. See LLM-rendered HTML/Markdown.

12. Check the MongoDB connection surface

Confirm the database is only reachable from the backend — no publicly exposed Mongo port, and the connection string uses a scoped user, not an admin account. If you exported the project to your own infra, this is the first thing to verify.

13. Guard LLM-backed features against injection

If the app itself calls an LLM with user input plus your data, user input can steer the model into dumping context or calling tools it shouldn’t. See indirect prompt injection for the patterns and mitigations.

14. Test with two accounts (BOLA)

Sign up as user A, create a record, copy its ID from the URL or a network request. Sign up as user B and request the same ID. If B gets A’s data, the Mongo queries are missing the user scope (item 1). Do this for every collection before sharing the app.

15. Run a security scan

The Vibe Code Scanner covers the deploy-side patterns; the full VibeEval scan adds BOLA, role-escalation, and auth-bypass probes against the deployed URL.

Common Vulnerabilities in Emergent Apps

Unscoped MongoDB Queries

find_one({"_id": id}) with no user filter — any authenticated user reads any user’s documents by ID. The fix is the compound filter with user_id, on every user-scoped collection.

Weak or Hardcoded JWT Secrets

A guessable signing secret means anyone can mint valid tokens for any user, including admins. Random 32+ byte secret from environment config, pinned algorithm, short expiry.

Routes Without Auth Dependencies

Every FastAPI endpoint is public until a dependency gates it. The bug ships when the agent generates a new router mid-session and skips the dependency it used earlier.

Verbose Error Responses

Raw exception strings and tracebacks in responses map your stack for attackers — Mongo errors, file paths, package versions. Generic errors client-side, full logs server-side.

Free Self-Audit Suite

Five free scanners.

Vibe Coding Vulnerabilities

Full vulnerability taxonomy across AI tools.

OWASP Top 10 for AI Code

The standard risks mapped to AI-generated code.

Automate Your Security Checks

VibeEval scans your deployed Emergent application against every category above plus 305 more probes. Findings ship with fix prompts you can paste back into the Emergent agent for one-shot remediation.

SCAN YOUR EMERGENT APP

14-day trial. No card. Results in under 60 seconds.

START FREE SCAN