Brod

Guide

How to secure a vibe-coded app

A working checklist for an internal tool you built with Claude Code, Cursor or Codex, before you give it to your team. Each step says what to do, how to do it on Brod, and what Brod does not do for you.

1. Get secrets out of the code

Search the project for API keys, tokens, database URLs and passwords. Check the git history too, not just the current files. Any key that was ever committed or sent to the browser should be rotated with the provider, not just deleted.

On Brod, store each one as a secret. Your agent can do it with set_secret, and the server code reads it as env.NAME on its next request. Names are UPPER_SNAKE_CASE.

  • Encrypted. Values are encrypted with AES-256-GCM and bound to the app, so a value copied to another app does not decrypt.
  • Write-only. Secrets are write-only. Nobody, including the agent that set them, can read a value back. get_files never includes them.
  • Recorded. Each set and removal is recorded.
Still on you

Only server code can read a secret. If a key is used from the browser, every visitor can see it. Move that call into the app's _worker.js.

2. Delete the home-made login

If the agent wrote a login form, a user table or password handling, remove it. On Brod, sign-in happens at the gateway before a request reaches the app, and the app reads who is there from Brod.me() in the browser or the x-brod-user-email and x-brod-role headers on the server. The authentication guide has the details.

3. Decide who can open it

Name the people or group who need the app. Start narrower than you think. A new app on Brod is private: only you and the workspace admins can open it. From there, pick one mode:

  • people

    For named people, groups or an email domain.

  • workspace

    For everyone in the workspace.

  • password

    For someone outside who has no account.

Avoid signed_in for internal data

On brod.sh it lets in anyone with a brod.sh account.

When an agent asks to widen access, nothing changes until a person confirms a link. Narrowing applies at once.

4. Check roles on every write

Hiding a button is not access control. Brod passes the person's role to the app, but it does not enforce what that role may do inside the app. The server code must check x-brod-role before it changes data, on every route that writes. Brod cannot block paths by role yet, so there is no backstop here.

Ask your agent to list every route that changes data and show you the role check on each one.

5. Add the two browser checks

  • Origin on POST

    All Brod apps share one site for browser purposes, so SameSite=Lax cookies do not stop a page in another app posting a form to yours. Check the Origin header, or use a CSRF token, on anything that changes data.

  • Framing

    App pages carry no frame-ancestors policy by default. If someone could be tricked into clicking inside your app in a frame, send your own.

6. Declare the outside hosts

List every outside host the app calls in brod.json under "network" (host names, with *. for subdomains, up to 30). Brod builds the browser's Content-Security-Policy from that list, and server fetch calls pass through an outbound gate.

  • Default mode. Brod logs calls to undeclared hosts and allows them.
  • Refusing. The operator can switch to refusing them.
  • Network tab. Either way, the app's Network tab shows undeclared hosts the app reached, with counts. Open it after your first real use.
  • Unexpected hosts. A host you did not expect is worth a question to your agent.

7. Test changes on staging, carefully

When an agent updates a live app, the new version goes to the app's staging address by default. Try it there, then publish. Staging can be opened by the owner, admins, builders and people with the app's top role, never by anonymous or password visitors.

Staging uses the live data.

Staging and every version share the same database, files and secrets. What you change while testing is real. Be most careful with changes that rewrite tables or delete rows.

8. Know your way back

Every deploy is a numbered version, and rollback serves an earlier one on the next request. Nothing is rebuilt.

Rollback restores code, not data.

If a bad version corrupted rows, rolling back stops the damage but does not undo it, so plan how you would recover data you cannot recreate.

9. Look at the logs once

get_logs shows the app's activity (deploys, access changes, refused requests) and, for server apps, recent requests with console output and errors.

  • Retention. Request logs are kept for 7 days, and get_logs shows the last 50 requests.
  • Look once after launch. Errors and refusals you did not expect are early warnings.
  • Keep them clean. Do not log secrets or personal data you would not want in a log.

10. Limit what the agent can do

An agent's token acts with its creator's role.

  • Expiry. Give tokens an expiry.
  • Read-only. Use read-only connections for agents that only need to look.
  • Revoke. Revoke a token from the connections page if it leaks.
  • Out of config. Keep tokens out of committed config files.

What Brod covers and what you still check

Brod handles

  • Sign-in and the access check before every request
  • Private by default; widening access waits for a person
  • Encrypted, write-only secrets
  • A separate database and file store per app
  • Staging, versions and rollback
  • Activity and request logs

You still check in the app

  • What each role may do, on every write
  • The Origin header on POST
  • Framing protection if you need it
  • Input handling and queries in your own code
  • Data changes tested on staging
  • Recovering data a bad version damaged

Brod assumes the people who deploy apps are trusted members of the team. It is not a sandbox for hostile code. The full model is in Brod's security architecture.

Questions

Does Brod scan my code for vulnerabilities?

No. On brod.sh, a deploy-time check looks for phishing pages, such as a form asking for a password or card number that imitates a brand. It does not scan for malware, leaked secrets or vulnerabilities.

Can my agent read the secrets back to debug?

No. Secrets are write-only. The agent can see secret names in get_status and set or remove values, but only the app's server code can read them.

Is a password-mode app safe for client data?

It is the weakest of the closed modes: anyone with the address and password gets in. Prefer inviting the person as a guest to the one app, which gives them their own sign-in.

Your AI already built the app. Put it in your team's hands.