HOW TO SECURE A DATABUTTON APP

Databutton Security Context

Databutton’s agent builds full-stack apps with a React frontend and a Python FastAPI backend, deployed and hosted by the platform. That’s a real backend with real routes — which means the classic API security work still applies. The recurring shape we see is a FastAPI endpoint generated without any auth dependency: the agent wires up the CRUD, the frontend calls it, everything works — and anyone with the URL can call it too. The platform gives you a secrets store and managed hosting; the generated application code is where the gaps live.

Security Checklist

1. Add an auth dependency to every endpoint

Generated FastAPI routes ship without auth unless you asked for it. Every route that reads or writes user data needs a dependency that verifies the caller’s token (Firebase Auth ID token or whatever provider you wired):

from fastapi import Depends, HTTPException

async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = verify_firebase_token(token)
    if not user:
        raise HTTPException(status_code=401)
    return user

@router.get("/projects/{project_id}")
async def get_project(project_id: str, user=Depends(get_current_user)):
    ...

Walk every router before launch. A route without a Depends on auth is publicly callable.

2. Add ownership checks after auth (BOLA)

Auth confirms the token is valid; it does not confirm the caller owns the record. Generated endpoints routinely look up by ID and return whatever they find. After the lookup, compare the record’s owner to the authenticated user:

project = db.get_project(project_id)
if project is None:
    raise HTTPException(status_code=404)
if project.owner_id != user.uid:
    raise HTTPException(status_code=403)

This is the single most common finding in AI-generated CRUD. See BOLA in AI-generated CRUD.

3. Keep secrets in the secrets store — and out of the React bundle

Databutton has a built-in secrets store for API keys; use it for every third-party credential. The failure mode is generated code that calls a third-party API from the React side — the key ends up in the browser bundle where anyone can extract it. Any Stripe, OpenAI, or Resend call belongs in a FastAPI endpoint that reads the key from the secrets store. Run the Token Leak Checker against your deployed URL to confirm nothing leaked into the bundle.

4. Tighten Pydantic models against mass assignment

Pydantic models exist in the generated code, but endpoints sometimes accept extra fields or trust client-supplied IDs. Use strict models for writes and never take the owner or role from the request body:

from pydantic import BaseModel, ConfigDict

class ProjectUpdate(BaseModel):
    model_config = ConfigDict(extra="forbid")
    name: str
    description: str | None = None
    # no owner_id, no role, no is_admin — server sets those

extra="forbid" rejects unexpected fields instead of silently ignoring (or worse, persisting) them.

5. Fix the CORS middleware

Generated FastAPI apps commonly ship CORSMiddleware with allow_origins=["*"] and allow_credentials=True. That combination is a credentialed cross-origin read. Set the allowlist to your production origin:

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://yourapp.example.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
)

See CORS + credentials misconfig for why allow-all with credentials is the worst of both worlds.

6. Rate-limit LLM-calling endpoints

If your backend calls an LLM or any per-request-billed API, one user with a loop can run up your bill. Add a per-user limit (e.g. slowapi or a simple counter keyed on the authenticated user) on every endpoint that costs money, and a per-IP limit on auth endpoints.

7. Disable docs endpoints in production

FastAPI serves /docs, /redoc, and /openapi.json by default, which hands an attacker your entire API surface with parameter types. Turn them off for the deployed app:

app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)

8. Return generic errors in production

FastAPI’s default validation errors and unhandled exceptions are verbose — they echo field names, internal structure, and sometimes stack context. Add an exception handler that logs server-side and returns {"detail": "Internal server error"} to clients.

9. Harden scheduled jobs

Databutton supports scheduled jobs/tasks. Treat job code with the same discipline as endpoints: secrets from the secrets store, no broad-scope tokens, and no job that writes user-visible data without validating what it ingests. A scheduled job that fetches an external feed and writes it into your database is an injection path if the feed is attacker-influenced.

10. Verify Firebase Auth configuration

If auth is wired via Firebase Auth: verify ID tokens server-side (signature and audience), don’t just decode them; restrict authorized domains in the Firebase console to your production domain; and enable email verification if accounts gate anything sensitive. The Firebase Scanner covers the common client-side Firebase misconfigurations.

11. Validate file handling

If the agent generated an upload flow, check it server-side: size cap, MIME allowlist, and regenerated filenames. The recurring bug is an upload endpoint that stores whatever arrives under the client’s chosen name. See file upload zip-slip / XXE.

12. Test with two accounts (BOLA)

Sign up as user A, create a record, note its ID. Sign in as user B and request the same ID directly against the API. If B gets A’s record, the ownership check from item 2 is missing on that route.

13. Run a security scan

The Vibe Code Scanner covers the deploy-side patterns; the full VibeEval scan adds BOLA, mass-assignment, and unauthenticated-endpoint probes against your deployed Databutton URL.

Common Vulnerabilities in Databutton Apps

Endpoints Without Auth Dependencies

The agent generates working routes fast, and “working” doesn’t include auth unless you prompted for it. Every unprotected route is publicly callable at the deployed URL.

API Keys in the Browser Bundle

A third-party call made from React instead of FastAPI puts the key in the shipped JavaScript. The secrets store only protects keys that stay server-side.

Allow-All CORS With Credentials

allow_origins=["*"] plus allow_credentials=True in the generated middleware lets any site make credentialed requests to your API.

Docs Endpoints in Production

/docs and /openapi.json left enabled enumerate every route, parameter, and model — free reconnaissance for anyone probing the app.

Free Self-Audit Suite

Five free scanners.

Databutton Security Checklist

The pre-launch checklist version of this guide.

Is Databutton Safe?

In-depth analysis of Databutton’s defaults and what to audit before launch.

Automate Your Security Checks

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

SCAN YOUR APP

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

START FREE SCAN