# Run a Security Audit on a SvelteKit App

Yes. An agent reads your SvelteKit app's hooks, form actions, cookies and HTML rendering, audits the dependencies, and reports each finding with a fix.

[Run this on Rush](https://cloud.getrush.ai/run/security-audit/sveltekit/), in a Project that has your repository.

## What the agent does

The agent reads the request path first, because in SvelteKit that is where trust is decided. In an app like `sveltejs/realworld`, `src/hooks.server.js` is four lines: it reads the `jwt` cookie and sets `event.locals.user` to `JSON.parse(atob(jwt))`, so the whole user object, token included, lives in a cookie the server decodes but never verifies. Every `+page.server.js` then trusts `locals.user`: `settings` redirects to `/login` without it, and the `createComment`, `deleteComment`, `deleteArticle` and `toggleFavorite` actions in `src/routes/article/[slug]/+page.server.js` answer `error(401)` without it. The upstream API still checks the token on each call, so a forged cookie cannot act as another user, but a cookie that is not valid base64 JSON makes `hooks.server.js` throw on every request until it is cleared, and the report says exactly that rather than calling it an authentication bypass.

Next it reads how the cookie is set and how HTML gets onto the page. `login`, `register` and `settings` all call `cookies.set('jwt', value, { path: '/' })` with no other options, so the agent checks the framework defaults that apply, `httpOnly`, `secure` and `sameSite`, and notes that nothing in `svelte.config.js` sets a Content Security Policy or changes the origin check on form actions. The one `{@html}` in the app is `data.article.body` in `src/routes/article/[slug]/+page.svelte`, fed by `marked(article.body)` passed through `sanitizeHtml` with the library's default options in the page's server load, so the agent reads which tags and URL schemes those defaults allow and checks whether comment bodies, usernames and bios ever reach `{@html}` too, which they do not.

Then it reads the API client and the actions for the quieter problems. `src/lib/api.js` hardcodes the API base URL, turns any status other than 2xx or 422 into a thrown `error(res.status)`, and forwards the token in an `Authorization: Token` header; `toggleFavorite` calls `api.post` and `api.del` without awaiting them, so a failure is swallowed and the page redirects as if it worked; `register` returns `fail(401, body)` with the API's whole response body, and `settings.save` sends `password: data.get('password')` even when the field is empty. The agent runs `pnpm audit` against `pnpm-lock.yaml` for `marked`, `sanitize-html`, `@sveltejs/kit` and `vite`, and notes that `package.json` has a `lint` script that only runs Prettier and no test script at all.

The result is `security-audit.md`, ordered by severity, each finding with the file and line, what an attacker or an unlucky user can do, and a fix written for this codebase: a `try` around the cookie decode in `hooks.server.js` that clears a bad cookie instead of throwing, explicit `httpOnly`, `secure`, `sameSite` and `maxAge` on each `cookies.set`, a `kit.csp` block in `svelte.config.js`, `await` on the favorite calls, and an `allowedSchemes` list for `sanitizeHtml`. The agent changes no code and opens no pull request.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Run a security audit on this SvelteKit app without changing anything. Read package.json, pnpm-lock.yaml, svelte.config.js, vite.config.js, src/hooks.server.js, src/lib/api.js, src/app.html and every +page.server.js, +layout.server.js and .svelte file under src/routes first. For each place the app decides who the user is, sets or reads a cookie, renders HTML with {@html}, forwards a token, or passes form data to the API, say what it trusts and whether that trust is checked. Check the cookie options the framework applies when none are passed, whether a Content Security Policy or origin check is configured, which tags and URL schemes the HTML sanitizer's default options allow for article bodies, whether any other user-supplied field reaches {@html}, which API calls are not awaited, and what the register and settings actions echo back or send. Run pnpm audit and list vulnerable packages with their advisories. Write security-audit.md: findings ordered by severity, each with file and line, impact, and a fix written for this codebase, then a dependency section, then what the app already does right. Change no code and open no pull request.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is `security-audit.md` as an artifact on the session, with a download link the session read returns. The findings come first, ordered by severity, each with the file and line, a sentence on what a user or an attacker can do with it, and the fix as it would be written in this codebase, so a reviewer can read `hooks.server.js` and the proposed `try` block side by side.

A dependency section lists what `pnpm audit` reported for the packages in `pnpm-lock.yaml`, with the advisory and the version that fixes it, and the output of the command is quoted so the list is checkable. A final section says what the app already does right: HTML is sanitized server-side before `{@html}`, the only `{@html}` is the article body, and form actions keep the framework's origin check.

A reviewer decides which findings to fix now, which to accept, and whether the hardcoded API base in `src/lib/api.js` belongs in an environment variable. A follow-up message to the same session asks the agent to apply any subset of the fixes and open a pull request, with the sandbox still holding the installed app.

## Run it on every release candidate branch

A team that cuts a release branch before each deploy starts one run per release with `POST /o/{org}/sessions`, that branch in `resources` as `https://github.com/your-org/your-app/tree/release-1.4`, and this prompt. A step in the release workflow sends the request with the key from its secrets and attaches the artifact link to the release notes.

A webhook on the key receives `run.completed` with the `session_url`, so the workflow can wait for the report and fail the release if the audit's top finding is above an agreed severity, read from the artifact.

## Why run it on Rush?

A security read of a SvelteKit app is a read of trust: what `hooks.server.js` believes, what each action checks, what reaches `{@html}`. It is careful work that gets squeezed out of a release week. In a Rush sandbox the agent reads every server file, installs the app, runs `pnpm audit` and keeps every command and its output in the transcript, so each finding points at a line and each dependency claim points at an advisory.

The report is also honest about severity. It distinguishes a cookie the server decodes without verifying from an authentication bypass, because the API still checks the token, and it says which fixes are a line and which are a design change, so the team spends its attention where the risk is.

## Frequently asked questions

### Does it change any code or open a pull request?

No. The result is a report with a fix for each finding written for this codebase. A follow-up message to the same session asks the agent to apply the ones you choose and open a pull request.

### Is the unverified cookie an authentication bypass?

Not on its own. `hooks.server.js` decodes the cookie without checking it, so the UI shows whatever the cookie claims, but every write goes to the API with the token inside that cookie and the API verifies it. The report rates it by what it actually allows: a malformed cookie that breaks every request for that browser, and a user object the server trusts for display.

### Does it check the Markdown rendering?

Yes. Article bodies go through `marked` and then `sanitizeHtml` with default options in `src/routes/article/[slug]/+page.server.js` before `{@html}` renders them, and the report says which tags and URL schemes those defaults allow and whether that fits. It also confirms that comments, usernames and bios never reach `{@html}`.

### Does it audit dependencies?

Yes. It runs `pnpm audit` against `pnpm-lock.yaml` in the sandbox and lists each advisory with the installed and fixed versions, with the command output quoted so the list can be checked.

### The app has no tests. Does that matter for the audit?

It limits what a fix can be proven with. The report notes that `package.json` has only a Prettier `lint` script and suggests where a test for the cookie decode and the sanitizer options would go, but it does not add them.
