Vibe Coding Security: What DaloyJS Already Blocks Before Your AI Even Ships
Aikido's 'WTF is Vibe Coding Security' post lists the usual suspects: SQL injection, path traversal, hardcoded secrets, unlocked admin routes, missing input sanitization, dependency rot. Here's the honest mapping of which of those a DaloyJS app already blocks by default — even when the code is written by a sales rep at 1am with Claude — and the small list of things you still have to opt into.
Same reader. Different week. This time the link was Aikido's "WTF is Vibe Coding Security" and the question was, again, the only one worth asking: so are we doing anything about this?
For the unfamiliar: vibe coding is when someone — often someone who is not a developer — describes what they want in English and ships whatever the model writes. Agentic codingis the same thing with the model also installing the dependencies, running the tests, and pushing the PR. The Aikido post lists the usual scary outcomes: SQL injection, path traversal, hardcoded secrets, an admin route left mounted on the public app (the "Tea app" story), and an AI agent that deleted a production database while "lying about unit tests" (the Replit / SaaStr story).
I read it, opened DaloyJS, and went through each risk to see what we already block, what needs one opt-in line, and where we honestly can't help. Below is that mapping. The TL;DR: if a sales rep uses Claude to scaffold a DaloyJS app at 1am, the boring stuff — body limits, prototype pollution, header splitting, path traversal, secret-shaped logs — is on before they type their first prompt. What they still have to choose is which routes need auth and where the admin surface lives. Those are policy, not defaults.
Risk 1 — SQL injection
- DaloyJS blocks
- Standard Schema (Zod / Valibot) validation is a route-level requirement, not an afterthought. The framework has no untyped req.body escape hatch in the public API. /docs/security/sql-injection documents the per-ORM patterns; the scaffolder ships Prisma / Drizzle / TypeORM templates that are parameterized by construction.
- You still own
- Pick a real ORM. Don't write template-string SQL. The framework will not stop you from doing the wrong thing inside your handler — but it will hand you a fully-typed, validated input object so you have no excuse.
DaloyJS doesn't ship an ORM. That's deliberate — pinning one ORM would be the same kind of opinionation that gets frameworks in trouble. What it does ship is a route shape where the input is validated before your handler runs:
And a documented path for the database layer:
Full guidance: /docs/security/sql-injection and the per-ORM pages under /docs/orm.
Risk 2 — Path traversal
- DaloyJS blocks
- The router rejects '..' segments, '//', encoded NULs, and percent-encoded traversal sequences before the route is matched. Returns 400 with no handler invocation.
- You still own
- Constrain :param shapes with a Zod regex anyway. Defense in depth costs you one line.
The full list of what the router refuses to walk into is in /docs/security/runtime-protections.
Risk 3 — Hardcoded secrets and AI-generated supply-chain rot
- DaloyJS blocks
- Repo-wide CI gates that block leaked credentials, base64-smuggled payloads, invisible-unicode Trojan Source, install-time lifecycle scripts (the #1 npm attack vector), remote exec (curl|sh, eval(fetch())), unpinned GitHub Actions, and unauthorized license categories. A CycloneDX SBOM is generated and signed on every release. @daloyjs/core itself ships with zero runtime dependencies — there is no transitive blast radius.
- You still own
- Run 'pnpm verify' in your project's CI. The create-daloy templates ship the workflow. Don't disable it because a dependency 'needs' a postinstall — that's the attack.
The full reasoning behind each gate is in "Supply-chain hardening for TypeScript libraries". The shorter version: attackers do not need a 0-day if they can ship a malicious postinstall, and AI agents do not inspect scripts blocks before running npm install. The gate that says "no lifecycle scripts at all" is the one that stops the next chalk-style compromise from reaching a vibe-coded project.
Risk 4 — Unlocked admin routes (the "Tea app" story)
- DaloyJS blocks
- ipRestriction() and basicAuth() are first-class middleware. /docs/security/admin-panels exists specifically to argue that the safest admin route is the one that isn't mounted on the public app at all, and shows the multi-App pattern that makes that easy.
- You still own
- Pick a pattern: separate App on a separate hostname (best), or /admin mounted with ipRestriction + basicAuth (acceptable). The framework refuses to invent a default 'admin' user — there is none — so a forgotten password is not a backdoor.
The dedicated page is /docs/security/admin-panels. If the "Tea app" team had read it, they'd have shipped an internal-only deploy and the breach would not have happened. I am not claiming the framework would have forced them to — policy is policy — but the path of least resistance in DaloyJS is the safe one.
Risk 5 — Missing input sanitization
- DaloyJS blocks
- Standard Schema everywhere (Zod, Valibot, ArkType all supported). Body, query, params, and headers are all validated against a declared schema. Unknown fields are stripped, the wrong type 400s before the handler runs, and the validated value is the only thing visible to the handler.
- You still own
- Write the schema. The framework will hold the line.
This is the same pattern as Risk 1, applied to everyinput surface, not just bodies. The router itself is the sanitization layer — there is no "remember to call zod.parse" convention. If a route omits a body schema and declares a body content type, the build complains. If the body schema rejects, the handler never runs.
Risk 6 — Agentic coding doing things the prompt didn't ask for
- DaloyJS blocks
- fetchGuard() — explicit egress allow-list, default-deny on cloud metadata and RFC1918. requestTimeoutMs + bodyLimitBytes — bounded resource use. Per-request structured logs with correlated request IDs go to your SIEM, so 'the AI agent did what?!' becomes a query, not an archeology dig. The scaffolder ships an AGENTS.md and a daloyjs-best-practices SKILL.md so the agent reads the rules before it writes code.
- You still own
- Don't give the production-DB password to the agent. Run agentic tools against a sandbox account. Treat AI commits like junior-dev commits — review them. The framework cannot stop you from handing your prod credentials to a model.
The "agent reads the rules before it writes code" piece is covered in "Designing for Coding Agents". The point of scaffolding AGENTS.md is exactly the "PromptBOM" idea the Aikido post pitches at the end — give the agent provenance and rules before it generates, not after.
The assume-the-vibe-coder-skipped-it defaults
The article's most useful line: "Treat AI code like a junior developer wrote it." Translated into framework defaults, that means the dangerous things have to be off when nobody remembered to turn them off. That's the constructor:
What we honestly do not do
- We do not stop you from
rm -rfyour production database from inside a handler. If you give the agentDATABASE_URLwith destructive privileges, the framework cannot save you. Use a read-replica for the agent. Use least-privilege DB roles. - We do not scan the AI-generated code for logic flaws — the article is right that scanners catch known patterns and miss business logic. We give you the structured surface (typed routes, typed client, OpenAPI) so a reviewer or a SAST tool has something to bite into.
- We do not enforce authentication on every route. We can't — some routes are deliberately public. What we give you is
jwt(),basicAuth(),bearerAuth(),session(), and an auth-slice pattern so the choice is visible per route. - We do not provide an AI moderation layer or a runtime intrusion-detection system. Daloy gives you the structured event stream a detector needs; the detector itself is your call.
The vibe-coder prompt that produces a defensible app
That paragraph plus pnpm create daloy@latest is the entire setup. The scaffolded project ships with the verify gates wired into CI, the AGENTS.md the model needs, the security docs linked from the README, and the secure-by-default constructor. The sales rep at 1am has to actively work to disable any of it.
The honest answer to the original question
Are we doing anything about vibe coding security?Yes — the framework was designed assuming the person writing the handler either doesn't know or doesn't care about the security layer, and the defaults reflect that. The Aikido post's shopping list of risks maps almost one-for-one to a primitive that already exists in DaloyJS today. The few items that don't map are the ones no framework can own — pick an IdP, lock down the DB role, don't hand the prod creds to the agent, review the commits.
The vibes can stay good. Just point them at a framework that won't let them ship the obvious mistakes.
Related reading on this blog: Cloud Security Architecture, Mapped, Secure by Default, Supply-chain hardening for TypeScript libraries, Designing for Coding Agents, Scaffolding a production-ready DaloyJS app in 60 seconds. Relevant docs: /docs/security, admin panels, SQL injection, fetch guard, runtime protections, supply chain.