Zero Trust

Zero Trust means “never trust, always verify.” In practice: treat all user input as untrusted, validate it strictly, and sanitize/encode on output. This lesson keeps it practical for your first feature.

Why this matters (OWASP Top 10)

The OWASP Top 10 is a community‑maintained list of the most common and serious web application risks. Think of it as a practical safety checklist for web apps. One of the biggest items is Cross‑Site Scripting (XSS) – exactly what Zero Trust helps prevent by default. (Injection, another big one, becomes relevant once you add a database in the next level – we'll flag where it fits.)

1. What goes wrong without validation and sanitization

In human terms: if your app accepts text and shows it to others (comments, names, messages), attackers can sneak in scripts or special characters that run code in your users’ browsers. That’s XSS – the risk that’s real right now, before you even have a database.

Examples you might encounter:

  • XSS (Cross‑Site Scripting):
    • Harmless‑looking input like <script>alert('xss')</script> or <img src=x onerror=alert(1)> ends up rendered as HTML and runs JavaScript in someone else’s browser.
    • Impact: pop‑ups are the demo; real attacks can steal cookies, tokens, and session data.

Key technical ideas alongside the plain language:

  • “Validate”: ensure input has the right type/shape/length (e.g., via Zod schemas) before accepting it.
  • “Sanitize/encode”: strip or neutralize dangerous characters before output (e.g., encode HTML), and never render raw HTML unless sanitized.
Looking ahead: injection

When you add a database in the next level, a second risk shows up: injection (e.g., SQL injection), where input like ' OR 1=1 -- tries to change a query instead of being treated as data. The same never‑trust‑input rule applies – Claude will use parameterized queries (prepared statements) so user input can’t become a command. You don’t need to do anything about it yet; just know the principle carries straight over.

Outcome: You can explain XSS in plain language, name the essential defenses, and know that the same principle will cover injection once you have a database.

I understand XSS risks and the core defenses

2. Harden your first feature (prompts + updates + commit)

Assume your first feature includes a form submission. We’ll guide Claude to find inputs, add validation, and sanitize/encode outputs. Then we’ll review and commit.

About Zod (used here)

Zod is a lightweight TypeScript‑first schema library for runtime validation. Define a schema once and use it on client (forms) and server (API routes/server actions) so only valid data gets through. See Zod docs.

Apply Zero Trust to my first feature (validation, sanitization, safe queries)
You are my security copilot. Look at my first feature and the files it touches. Then:
1.Inventory inputs
- Locate form fields, URL params, request bodies, and any user-generated content.
- List the files and functions that receive/process these inputs.
2.Add validation (Zod) on both client and server
- Create Zod schemas close to the boundaries (form handler, API route, server action).
- Enforce type, min/max length, enums/allowed values, and trimming.
- Reject invalid input early with friendly error messages.
- If Zod is missing, install it: npm i zod
3.Sanitize/encode outputs
- Do NOT use `dangerouslySetInnerHTML`.
- When rendering user text, ensure it is treated as text (escaped/encoded). If rich text is required, propose using a sanitizer library and add a minimal allowlist.
4.Error handling and logging
- Add clear error messages for validation failures (no stack traces to users).
- Log unexpected errors server-side (avoid leaking secrets to clients).
5.Update UX
- Show inline form errors, disable submit when invalid, and keep inputs in sync with schema.
6.Summarize the changes you made (we'll test, then ship in a moment).

Outcome: Your feature validates inputs and encodes outputs so user text can’t run as code.

I added validation and sanitization/encoding to my feature

3. Try common attack payloads (manual smoke test)

Manually test a few classic payloads in your form to verify defenses.

Guide me through a quick XSS smoke test
Provide short steps to test:
1.XSS strings
- <script>alert('xss')</script>
- <img src=x onerror=alert(1)>
2.Injection-style strings (for now, these are just odd text – my app has no database yet)
- ' OR 1=1 --
- 1; DROP TABLE users; -- (should be treated as plain text, not executed – the same will be true once I add a database)
3.Long input / unexpected unicode
- 10,000 characters; emoji and RTL markers
For each case, describe the expected safe behavior (reject or render as inert text), and what to fix if unsafe behavior appears.

Outcome: Inputs that previously could be dangerous are now rejected or rendered safely as plain text.

I tested with classic XSS payloads and confirmed safe behavior

4. Ship the secured feature

Your defenses are in and tested – ship them. Since you're working on main, committing and pushing sends the hardened feature live.

Commit and push the security fixes
Commit the security work with a clear message (validation, sanitization/encoding) and push it to main so it goes live. Confirm when the deploy is done.

Outcome: Your hardened feature is live.

I shipped the secured feature to my live site