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 with this body:
{
"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"
}
]
}- 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.
- 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.
- 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.
The use case this job follows, with its automation and trigger: Produce a report or file, no repo.
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.