Claude Code web appAgent run without web session

Claude Code web agent accepts anonymous runs: secure the agent API boundary

A server-held agent API key authenticates the web server to the agent service; it does not authorize the browser user. Reject a missing web session before saving messages or starting an agent run. Bind each conversation ID to the authenticated owner, limit which tools that user may invoke, and apply quotas and timeouts.

This guide covers check 01: Authentication and access control; check 02: Authorization and data isolation; check 06: Performance and scalability in the Zenveus Production Readiness Standard.

For builders

What this means, in plain words

A server-held agent key does not prove the person using your website is allowed to run the agent. An unprotected route can expose conversations or spend your account’s resources. Check the user, conversation owner, tool permissions, and quota before storing messages or starting a run.

A scoped repair request

Using an AI builder? Paste this

Use this prompt in Lovable, Cursor, Replit, or Claude Code with the relevant server files available.

Audit my Claude Code web app’s agent route. Reject missing sessions before history reads, message writes, or agent calls; verify conversation ownership; enforce caller-specific tool permissions, quotas, and timeouts in the agent service. Work on a branch with synthetic data and mocked external services. Show the smallest diff, identify required adapters and deployment settings, and add allowed and denied tests that prove side effects cannot happen before checks pass. Do not disable security checks to make a test pass.

The same failure may appear as

  • Agent route runs without login
  • Server-held agent key forwards anonymous prompts
  • Another user's conversation ID is accepted
  • Agent tools have more privilege than the caller

Find the failure layer

Run these checks before rewriting anything

Each check removes a class of causes. Keep the first failing result, its timestamp, and the production log beside it.

01

Execution order

Follow session lookup, request parsing, conversation loading, message writes, agent-server forwarding, and tool execution in order.

If this failsAny side effect precedes authorization; move session and ownership checks ahead of storage and agent execution.
02

Caller and owner

With a mock agent service and synthetic conversations, send an anonymous request and another user's conversation ID. Both should stop before database writes and before the agent call.

If this failsAnonymous or cross-user requests succeed; bind conversation access to trusted user identity and retest with a mocked agent.
03

Agent permissions

Confirm the agent service validates the caller and allowed tool set independently. A shared server key should not grant every end user the same filesystem or command access.

If this failsThe internal key substitutes for user permission; add a caller-specific policy at the agent service boundary.
04

Run limits

Check input length, run time, concurrent jobs, user quota, and audit logs for agent actions.

If this failsUnbounded runs can exhaust resources; add shared quota, concurrency, timeout, and cancellation controls.

Ranked diagnosis

Common root causes, in the order we would test them

01

Missing-session fallback

The route substitutes an anonymous identity instead of rejecting a required session.

02

Proxy key is mistaken for authorization

A server-held credential authenticates the proxy but not the browser user.

03

Conversation ownership is unverified

A caller-controlled ID can select history before its owner is checked.

04

Tool scope is too broad

The agent service receives a generic run request without a caller-specific policy.

Step-by-step repair

How to fix this in your app

Edit src/app/api/claude/run/route.ts before message persistence or the call to agent-client.ts. Apply the same ownership check to conversation history and streaming endpoints.

Production safety ruleNever disable access controls, expose service keys, or add wildcard CORS as a routine shortcut.

01

Resolve the web identity first

Use your authentication library to verify the server session. Return 401 when absent before reading history, inserting a message, or starting an agent run. The server-held agent API key is not the browser identity.

02

Load conversations using both ID and owner

Look up the conversation with the submitted conversation ID and authenticated user ID in one query. Return 404 if no authorized row exists. Bind new conversations to the session identity on the server.

03

Scope the run to the authorized workspace

Derive tools, repository, working directory, and allowed actions from server-side workspace permissions. Do not pass caller-supplied tool names, filesystem paths, or credentials straight into the agent.

04

Bound work and isolate tool effects

Reserve quota before starting the run, apply a deadline, and enforce tool permissions inside the agent service as well. Use a durable run ID so retries cannot start duplicate jobs.

Implementation example

Next.js: authorize before agent side effects

// Integration skeleton: use your real auth, DB, and queue adapters.
export async function POST(request: Request) {
  const user = await getVerifiedUser();
  if (!user) return new Response('Unauthorized', { status: 401 });
  const input = await request.json();
  if (typeof input.conversationId !== 'string') {
    return new Response('Invalid conversation', { status: 400 });
  }
  const conversation = await findConversation({
    id: input.conversationId, ownerId: user.id
  });
  if (!conversation) return new Response('Not found', { status: 404 });
  const run = await enqueueAuthorizedRun({ user, conversation, input });
  return Response.json({ runId: run.id }, { status: 202 });
}

The three adapter functions must be implemented by your app. enqueueAuthorizedRun must validate input, derive tool permissions, reserve quota, and persist an idempotent run before dispatch.

Prove the repair

How to check that the fix worked

Run these checks with synthetic data in your test environment, then repeat the relevant acceptance checks after deployment.

  • Anonymous request: 401 with no message write and no agent run.
  • User B submits user A conversation ID: 404 and no agent run.
  • Caller requests a disallowed tool or workspace: rejected by server policy.
  • Retry with the same run identity: one durable run, not two.

If the check still fails

If history leaks or duplicate runs remain, audit every conversation endpoint and the streaming reconnect path. A guard on the run endpoint alone does not protect history or tool execution.

When the built-in AI fix makes it worse

Recover one reproducible failure.

Pause generated changes, restore a known working branch, and capture one failing request with its logs. Change one layer and rerun the allowed and denied checks before proceeding.

Engineering handoff

What Zenveus checks when the quick fix is not enough

We trace one production request through the complete path, isolate the failing boundary, and leave behind evidence your team can repeat.

Run ordering

Session validation and conversation ownership before history or message writes.

Service identity

The difference between an internal agent credential and user permission.

Tool privileges

Caller-specific permissions and resource limits enforced by the agent service.

Execution evidence

Mock agent invocations and storage writes for allowed and denied requests.

Typical repair pattern

Only an authorized owner can start a scoped agent run

Anonymous and cross-user requests stop before message writes or agent calls, while an allowed request runs with restricted tools.

Evidence left behind
  • Root-cause note
  • Verified production check
  • Rollback and prevention steps

Before the next release

Prevent this failure from returning

Include agent routes in ordinary API authorization reviews.
Test end-user identity separately from internal service credentials.

Clear answers

Questions teams ask before they touch production

01Does the internal agent API key protect the public route?

It protects the internal call from callers without that key, but a public web proxy can make that call on their behalf unless it authorizes them first.

02Is an `anonymous` username a safe fallback?

Only if anonymous runs are an intentional, isolated feature with restricted tools and usage. It should never silently replace a required session.

03What should a conversation ID check do?

Verify that the authenticated user owns or may access the conversation before history is loaded or changed.

04How do I know the fix worked in my app?

Run the verification checks on this page against your test environment, then repeat the relevant checks after deployment. Example code needs your app's authentication, data model, and configuration; reading the guide alone does not verify your deployment.

Official documentation and library references

Free next step

Check the boundary before you hand it over

The free tool helps you inspect this symptom. Its result does not establish whether the whole app is production ready.

The Verdict

Know whether the symptom is contained or structural.

We can see the symptom from here. What we cannot tell you from outside is whether it is contained or structural. A scanner collects evidence. A named senior engineer makes the decision. For $299, a named senior engineer reads your code and signs a written Verdict against the nine checks in the Zenveus Production Readiness Standard. The 48-hour clock begins when the required access and context are available. If the report does not give your developer a list they can act on, you do not pay.

The 48-hour clock starts when the required access and context are available.

Scroll to Top