> Missbrauch und ausufernde Kosten auf einer öffentlichen LLM-Route in Nuxt stoppen: Auth, Rate Limits, Prompt-Limits, Token-Budgets, Turnstile, Spend Limits.
>
> Web page: https://balazscsorba.com/de/blog/llm-endpoint-abuse-denial-of-wallet · Language: Deutsch · Also available in: [English](https://balazscsorba.com/blog/llm-endpoint-abuse-denial-of-wallet.md) · [Magyar](https://balazscsorba.com/hu/blog/llm-endpoint-abuse-denial-of-wallet.md)
> Author: Balázs Csorba · Published: 2026-10-16 · Keywords: denial of wallet llm, owasp llm10 unbounded consumption, rate limit llm api nuxt, nuxt security rate limiter, protect openai api key frontend, llm token budget per user, limit llm cost per user, nitro api rate limiting, cloudflare turnstile nuxt, anthropic spend limit, openai hard spend limit, llm prompt size limit

[Blog](https://balazscsorba.com/de/blog)/Web-Engineering

# Denial of Wallet: öffentliche LLM-Endpunkte in einer Nuxt-App absichern

Missbrauch und ausufernde Kosten auf einer öffentlichen LLM-Route in Nuxt stoppen: Auth, Rate Limits, Prompt-Limits, Token-Budgets, Turnstile, Spend Limits.

[Balázs Csorba](https://balazscsorba.com/de/about)·16\. Oktober 2026·14 Min. Lesezeit

-   Nuxt
-   LLM security
-   Rate limiting
-   OWASP
-   Cost control

![Anfragen an einen Nuxt-Chat-Endpunkt durchlaufen Bot-Prüfung, Session, Rate Limit, Prompt-Limit und Token-Budget, bevor sie die Modell-API erreichen.](https://balazscsorba.com/images/blog/llm-endpoint-abuse-denial-of-wallet/cover.webp?v=87cca578cd)

## Das Wichtigste in Kürze

-   Eine öffentliche LLM-Route ist eine nutzungsbasiert abgerechnete API mit Ihrer Kreditkarte dahinter; OWASP führt das Risiko als LLM10:2025 Unbounded Consumption.
-   Vor den Modellaufruf gehört eine Session, und nie ein generischer Proxy: Der Server wählt Modell, System-Prompt und max\_tokens.
-   Anfragen pro Nutzer und pro IP in einem gemeinsamen Speicher begrenzen und Tokens getrennt davon, denn eine Anfrage kann tausendmal mehr kosten als eine andere.
-   Vor dem Aufruf ein Token-Budget reservieren und danach mit dem tatsächlichen Verbrauch abrechnen, über einen atomaren Zähler.
-   Spend Limits beim Anbieter sind die letzte Sicherung, nicht die Kontrolle: Sie schalten die Funktion für alle Nutzer gleichzeitig ab und greifen nicht sofort.

Auf dieser Seite

1.  [Was ist Denial of Wallet?](https://balazscsorba.com/#what-is-denial-of-wallet)
2.  [Welche Missbrauchsmuster treffen öffentliche LLM-Routen?](https://balazscsorba.com/#abuse-patterns)
3.  [Wie sieht eine mehrschichtige Abwehr aus?](https://balazscsorba.com/#layered-defence)
4.  [Warum kommt die Authentifizierung zuerst?](https://balazscsorba.com/#authentication-first)
5.  [Wie limitiert man pro Nutzer und pro IP?](https://balazscsorba.com/#rate-limits)
6.  [Wie begrenzt man Prompt-Größe und Ausgabe?](https://balazscsorba.com/#input-limits)
7.  [Wie setzt man Token-Budgets pro Nutzer durch?](https://balazscsorba.com/#token-budgets)
8.  [Wo passen CAPTCHAs und Turnstile hin?](https://balazscsorba.com/#bot-protection)
9.  [Was fangen Spend Limits beim Anbieter ab?](https://balazscsorba.com/#provider-spend-limits)
10.  [Was sollte man überwachen und alarmieren?](https://balazscsorba.com/#monitoring)
11.  [Checkliste für eine öffentliche LLM-Route](https://balazscsorba.com/#checklist)
12.  [Quellen](https://balazscsorba.com/#sources)

Diesen Artikel anhören

0:000:00

Eine LLM-Funktion auf einer öffentlichen Website ist eine nutzungsbasiert abgerechnete API mit Ihren Zahlungsdaten dahinter. Ein Kontaktassistent, ein Produktfinder oder ein Button „Seite zusammenfassen“ enden alle in einer Server-Route, die Text an ein Modell weiterreicht und pro Token bezahlt. Wenn diese Route jedem beliebig oft mit beliebiger Eingabe antwortet, ist nicht die Frage, ob jemand sie als kostenlose Modell-API nutzt, sondern nur wann.

Dieser Artikel ist die Kosten- und Missbrauchsseite von LLM-Funktionen in Nuxt. Er übersetzt das OWASP-Risiko LLM10:2025 Unbounded Consumption in konkrete Schichten einer Nuxt- und Nitro-App: Sessions, Anfrage- und Token-Limits, Prompt-Größenlimits, Budgets pro Nutzer, Cloudflare Turnstile und die Spend Limits von OpenAI und Anthropic, mit Code zum Anpassen.

## Was ist Denial of Wallet?

OWASP beschreibt [Unbounded Consumption](https://genai.owasp.org/llmrisk/llm102025-unbounded-consumption/) als LLM-Anwendung, die Nutzern „übermäßige und unkontrollierte Inferenzen“ erlaubt, was zu Denial of Service, wirtschaftlichen Verlusten, Modelldiebstahl und verschlechtertem Dienst führt. Denial of Wallet ist die kostenorientierte Variante: Ein Angreifer erzeugt übermäßig viele Operationen, um das nutzungsbasierte Abrechnungsmodell von Cloud-KI-Diensten auszunutzen, und verursacht untragbare Kosten. Dafür muss nichts ausfallen; der Schaden ist die Rechnung.

LLM-Routen sind aus zwei Gründen exponierter als gewöhnliche API-Routen. Die Kosten pro Anfrage sind variabel und hoch: Eine Anfrage mit langem Gesprächsverlauf und langer Antwort kann um Größenordnungen mehr kosten als eine einzeilige Frage. Und die Ausgabe ist für den Angreifer direkt nützlich, ein offener Chat-Endpunkt lohnt sich also zum Skripten, auch wenn er mit Ihrem Produkt nichts zu tun hat.

## Welche Missbrauchsmuster treffen öffentliche LLM-Routen?

Der OWASP-Eintrag nennt sieben Beispiele. Auf eine typische Nuxt-Funktion übertragen, bleiben wenige Muster mit jeweils einer Hauptmaßnahme:

Muster

Wie es aussieht

Hauptmaßnahme

Trittbrett-Proxy (Denial of Wallet)

Skripte nutzen Ihre Route als kostenlose Modell-API; Prompts ohne Bezug zum Produkt

Session, fester System-Prompt, Token-Budget pro Nutzer

Wiederholte Anfragen

Hohe Anfragerate von wenigen Konten oder IPs

Rate Limits an der Edge und pro Nutzer

Variable-Length Input Flood, Continuous Input Overflow

Riesige Bodies, eingefügte Dokumente, wachsende Verläufe

Body-Limit, Schema-Validierung, Token-Obergrenze

Ressourcenintensive Anfragen

Sehr lange Ausgaben, Tool-Schleifen, aufwendiges Reasoning

max\_tokens auf dem Server, Schrittlimits, Timeouts

Modellextraktion und funktionale Replikation

Systematische Anfragen, die Ausgaben als Trainingsdaten sammeln

Volumenlimits, keine Logprobs, Anomalie-Monitoring

Ein sechstes Muster benennt OWASP nicht, aber jedes Team erlebt es: selbst verursachter Verbrauch. Eine Retry-Schleife ohne Obergrenze, ein Agent, der immer weiter Tools aufruft, oder ein Client-Bug, der bei jedem Tastendruck den ganzen Verlauf schickt, verbrennen Budget genau wie ein Angreifer. Dieselben Limits fangen das ab.

## Wie sieht eine mehrschichtige Abwehr aus?

Keine einzelne Maßnahme reicht, weil jede etwas anderes misst. Ein Rate Limiter zählt Anfragen, ein Größenlimit Bytes, ein Budget Tokens und ein Spend Limit Geld. Ich ordne sie von der billigsten zur teuersten Prüfung, damit abgewiesener Verkehr so wenig wie möglich kostet:

Billige Prüfungen zuerst: Eine an der Edge abgewiesene Anfrage kostet nichts, eine vom Spend Limit gestoppte hat die Funktion schon lahmgelegt.

## Warum kommt die Authentifizierung zuerst?

Jedes andere Limit braucht eine Identität, an der es hängt. Ohne Session ist der einzige Schlüssel die IP-Adresse, und die ist schwach. Mit [nuxt-auth-utils](https://github.com/atinux/nuxt-auth-utils) liefert `requireUserSession(event)` die Session oder antwortet mit 401, die erste Zeile des Handlers entscheidet also, ob der Modellaufruf überhaupt stattfinden darf. Für eine Funktion, die vor dem Login funktionieren muss, etwa einen Produktfinder, nach einer Bot-Prüfung eine leichte anonyme Session ausgeben und ihr ein deutlich kleineres Budget geben als einem eingeloggten Kunden.

Die zweite Regel: Nie einen generischen Proxy ausliefern. Wenn der Client Modell, System-Prompt, `max_tokens` oder Tools wählen kann, ist Ihr Endpunkt eine offene Modell-API mit Umweg. Der Client schickt eine Nachricht und eventuell eine Gesprächs-ID; alles andere entscheidet der Server. So bleibt auch der API-Schlüssel auf dem Server, wie in [LLM-Funktionen in Nuxt ausliefern](https://balazscsorba.com/de/blog/nuxt-llm-features-ai-sdk-streaming) beschrieben.

## Wie limitiert man pro Nutzer und pro IP?

Das Modul [nuxt-security](https://nuxt-security.vercel.app/middleware/rate-limiter) bringt einen Rate Limiter mit, der standardmäßig global aktiv ist: 150 Anfragen pro 300.000 ms pro IP, gespeichert in einem LRU-Cache, mit 429 Too Many Requests bei Überschreitung. Er lässt sich pro Route über `routeRules` einstellen, und als Speicher dient jeder [unstorage](https://unstorage.unjs.io/)\-Treiber. Die eigene Dokumentation ist ehrlich zu den Grenzen: Der eingebaute Rate Limiter sei „nicht für komplexe Produktionsanwendungen geeignet“, empfohlen werden Lösungen auf Infrastrukturebene.

Für eine LLM-Route heißt das drei Anpassungen. Einen gemeinsamen Speicher verwenden, denn ein LRU-Cache im Speicher gilt pro Instanz und wird bei jedem Deploy zurückgesetzt. Auf der Modellroute ein viel engeres Limit setzen als auf dem Rest der Site. Und die Client-IP korrekt ermitteln: `getRequestIP` aus h3 liest `X-Forwarded-For` nur nach ausdrücklicher Aktivierung, weil der erste Eintrag Client-Eingabe ist; hinter Cloudflare kann die Option `ipHeader` von nuxt-security stattdessen auf `cf-connecting-ip` zeigen.

```
// nuxt.config.ts (illustrative)
export default defineNuxtConfig({
  modules: ['nuxt-security', 'nuxt-auth-utils'],
  security: {
    rateLimiter: {
      driver: { name: 'redis', options: { url: process.env.REDIS_URL } },
      ipHeader: 'cf-connecting-ip', // only if Cloudflare sits in front
    },
  },
  routeRules: {
    '/api/chat': {
      security: {
        rateLimiter: { tokensPerInterval: 20, interval: 60_000 },
        requestSizeLimiter: { maxRequestSizeInBytes: 32_000 },
      },
    },
  },
})
```

Dieser Limiter arbeitet pro IP. Das Limit pro Nutzer gehört in den Handler, nach `requireUserSession`, mit der Nutzer-ID als Schlüssel. Welcher Algorithmus dort läuft, ist weniger wichtig, als überhaupt konsequent einen zu nutzen; die Abwägungen, wie [Upstash sie dokumentiert](https://upstash.com/docs/redis/sdks/ratelimit-ts/algorithms):

Algorithmus

Stärke

Schwäche

Festes Fenster

Sehr günstig bei Speicher und Rechenaufwand

Bursts an Fenstergrenzen rutschen durch; Ansturm bei jedem neuen Fenster

Gleitendes Fenster

Behebt das Grenzproblem

Mehr Speicher und Rechenaufwand; eine Näherung

Token Bucket

Glättet Bursts; erlaubt einen höheren Anfangs-Burst

Mehr Zustand, über den man nachdenken muss

Anthropics eigene API nutzt einen Token Bucket, der kontinuierlich bis zum Limit aufgefüllt statt in festen Abständen zurückgesetzt wird, ein vernünftiges Vorbild für eine Chat-Funktion, in der Nutzer schubweise tippen.

## Wie begrenzt man Prompt-Größe und Ausgabe?

Ein Anfragelimit sagt nichts darüber, was jede Anfrage kostet. Die Eingabe in drei Schritten deckeln. Zuerst Bytes: Der Request Size Limiter von nuxt-security antwortet über `maxRequestSizeInBytes` mit 413 Payload Too Large, Standard ist 2.000.000; eine Chatnachricht braucht wenige Kilobyte. Dann die Form: den Body mit `readValidatedBody` und einem Schema prüfen, das die Nachrichtenlänge begrenzt. Dann Tokens: vor dem Aufruf zählen.

Das größte Loch ist meist der Gesprächsverlauf. Schickt der Client bei jedem Zug das ganze Gespräch, kann ein Angreifer einen erfundenen Verlauf beliebiger Länge senden. Den Verlauf auf dem Server halten, mit der Gesprächs-ID als Schlüssel, und auf eine feste Zahl von Zügen oder Tokens kürzen. Der [Token-Counting-Endpunkt](https://platform.claude.com/docs/en/build-with-claude/token-counting) von Anthropic ist kostenlos, hat ein eigenes, von der Nachrichtenerstellung getrenntes Rate Limit und liefert eine Schätzung der Eingabe-Tokens, das genügt für eine Obergrenze.

Die Ausgabe deckelt `max_tokens`, gesetzt auf dem Server. Wichtig ist, was es tut und was nicht: Für Anthropics Rate Limits werden Ausgabe-Tokens gezählt, während sie entstehen, und `max_tokens` fließt nicht in die Berechnung der Ausgabe-Tokens pro Minute ein. Es ist eine Kostenobergrenze pro Anfrage, keine Ratensteuerung, das Budget aus dem nächsten Abschnitt braucht es trotzdem.

```
// server/api/chat.post.ts (illustrative)
import { z } from 'zod'

const Body = z.object({
  conversationId: z.string().uuid(),
  message: z.string().min(1).max(4000),
})
const MAX_INPUT = 12_000   // tokens, after history trimming
const MAX_OUTPUT = 800     // the server decides, never the client

export default defineEventHandler(async (event) => {
  const { user } = await requireUserSession(event)          // 401 without a session
  const body = await readValidatedBody(event, Body.parse)    // 400 on bad or long input

  const history = await loadHistory(user.id, body.conversationId, { maxTurns: 10 })
  const messages = [...history, { role: 'user', content: body.message }]

  const { input_tokens } = await anthropic.messages.countTokens({ model: MODEL, system: SYSTEM, messages })
  if (input_tokens > MAX_INPUT) throw createError({ statusCode: 413, statusMessage: 'Conversation too long' })

  const reserved = input_tokens + MAX_OUTPUT
  const key = await reserveTokens(user.id, reserved)          // null when the daily budget is spent
  if (!key) throw createError({ statusCode: 429, statusMessage: 'Daily limit reached' })

  let used = 0
  try {
    const res = await anthropic.messages.create({ model: MODEL, system: SYSTEM, messages, max_tokens: MAX_OUTPUT })
    const u = res.usage
    used = u.input_tokens + (u.cache_creation_input_tokens ?? 0) + (u.cache_read_input_tokens ?? 0) + u.output_tokens
    await saveTurn(user.id, body.conversationId, body.message, res.content)
    return res.content
  } finally {
    await settleTokens(key, reserved, used)                   // refund the unused part
  }
})
```

## Wie setzt man Token-Budgets pro Nutzer durch?

Ein Budget ist die Maßnahme, die Kosten tatsächlich begrenzt: Tokens pro Nutzer und Tag oder pro anonymer Session und Stunde. Mein Muster ist Reservieren, dann Abrechnen. Vor dem Aufruf den schlimmsten Fall reservieren, also gezählte Eingabe plus `max_tokens`. Würde die Reservierung das Budget überschreiten, mit 429 ablehnen. Nach dem Aufruf mit dem tatsächlichen Verbrauch aus der Antwort abrechnen und die Differenz gutschreiben. Parallele Anfragen desselben Nutzers können dann nicht überziehen, weil jede ihren Anteil schon beansprucht hat.

Die Reservierung macht das Budget bei Parallelität sicher; das Abrechnen hält es genau.

Der Zähler muss atomar sein. Ein `getItem` gefolgt von `setItem` über den Nitro-Speicher ist ein Read-Modify-Write, zwei parallele Anfragen können beide den alten Wert lesen. Redis `INCRBY` liefert die neue Summe in einem Schritt, Prüfung und Reservierung können sich also nicht überholen:

```
// server/utils/budget.ts (illustrative, ioredis)
const DAILY_TOKENS = 200_000

export async function reserveTokens(userId: string, n: number) {
  const key = `llm:budget:${userId}:${new Date().toISOString().slice(0, 10)}`
  const total = await redis.incrby(key, n)
  if (total === n) await redis.expire(key, 60 * 60 * 48)
  if (total > DAILY_TOKENS) { await redis.decrby(key, n); return null }
  return key
}

export async function settleTokens(key: string, reserved: number, used: number) {
  if (reserved > used) await redis.decrby(key, reserved - used)
}
```

Beim Abrechnen alle Eingabe-Tokens zählen. Mit Prompt Caching umfasst Anthropics `input_tokens` nur die Tokens nach dem letzten Cache-Breakpoint; die gesamte Eingabe ist `cache_read_input_tokens + cache_creation_input_tokens + input_tokens`. Ob man gecachte Tokens zum niedrigeren Preis gewichtet, ist eine Produktentscheidung; ein schlichtes Token-Budget ist Nutzern leichter zu erklären. Zur Kostenseite von Caching und Routing siehe [Prompt Caching und Model Routing](https://balazscsorba.com/de/blog/llm-cost-latency-prompt-caching-routing).

## Wo passen CAPTCHAs und Turnstile hin?

Eine Bot-Prüfung verteuert Automatisierung; sie deckelt keine Kosten. Ich setze sie dort ein, wo eine Identität entsteht, etwa bevor eine anonyme Chat-Session ausgegeben wird, nicht bei jeder Nachricht. Bei [Cloudflare Turnstile](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/) ist die serverseitige Validierung über die Siteverify-API Pflicht, denn das Client-Widget allein schützt nichts: Tokens lassen sich fälschen, jedes Token ist 300 Sekunden gültig und kann nur einmal validiert werden, eine Wiederverwendung wird als `timeout-or-duplicate` abgelehnt.

```
// server/api/session/anonymous.post.ts (illustrative)
export default defineEventHandler(async (event) => {
  const { token } = await readBody<{ token: string }>(event)
  const r = await $fetch<{ success: boolean }>('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
    method: 'POST',
    body: { secret: useRuntimeConfig().turnstileSecret, response: token, remoteip: getRequestIP(event) },
  })
  if (!r.success) throw createError({ statusCode: 403 })
  await setUserSession(event, { user: { id: crypto.randomUUID(), tier: 'anonymous' } })
  return { ok: true }
})
```

**Eine Bot-Prüfung ist kein Budget**

Menschen lassen sich fürs Lösen von Challenges bezahlen, und eine gültige Session kann trotzdem den ganzen Tag teure Anfragen senden. Turnstile ist eine Bremsschwelle vor der Session-Erstellung, die Begrenzung übernimmt das Token-Budget pro Session.

## Was fangen Spend Limits beim Anbieter ab?

Beide großen Anbieter erlauben eine monatliche Ausgabengrenze, und man sollte sie unter dem Betrag setzen, der weh täte. Aber man sollte das Verhalten kennen: Diese Limits stoppen sämtlichen Verkehr in ihrem Geltungsbereich, für alle Nutzer, bis der Monat zurückgesetzt wird oder man sie anhebt.

Aspekt

Claude API (Anthropic)

OpenAI API

Selbst gesetztes Limit

Spend Limit pro Organisation unter der Tier-Grenze; eigene Spend- und Rate Limits pro Workspace

Hard Spend Limit pro Organisation oder Projekt; Spend Alerts, die nur benachrichtigen

Antwort beim Erreichen

HTTP 400 `invalid_request_error`, „You have reached your specified API usage limits“

HTTP 429 mit `organization_spend_limit_exceeded` oder `project_spend_limit_exceeded`

Eingebaute Obergrenze

Monatliche Tier-Grenze: Start 500, Build 1.000, Scale 200.000 USD; 429 `enforced_spend_limit_reached` ohne retry-after

Monatliche Nutzungslimits pro Usage Tier

Einschränkung

Für den Default-Workspace lassen sich keine Workspace-Limits setzen

„Enforcement is not instantaneous“; die erfasste Ausgabe kann das Limit leicht überschreiten

Zwei praktische Folgen. Jeder öffentlichen Funktion einen eigenen Anthropic-Workspace oder ein eigenes OpenAI-Projekt mit eigenem Schlüssel und Limit geben, damit ein außer Kontrolle geratener Chatbot nicht Ihre internen Werkzeuge stoppt. Und die Spend-Limit-Antworten ausdrücklich behandeln: Die SDKs wiederholen 429er automatisch, und laut Anthropic schlagen Wiederholungen fehl, bis der Zugang zurückkehrt. Auf einen freundlichen Zustand „vorübergehend nicht verfügbar“ abbilden und jemanden alarmieren.

## Was sollte man überwachen und alarmieren?

Zu den Maßnahmen von OWASP gehören umfassendes Logging mit Anomalieerkennung und Graceful Degradation. In einer Nuxt-App heißt das einige Kennzahlen pro Funktion, protokolliert mit Nutzer-ID und Gesprächs-ID:

-   **Tokens pro Nutzer und Tag**, mit Alarm, wenn der Spitzennutzer weit über dem Median liegt. Trittbrettfahrer tauchen hier zuerst auf.
-   **Ablehnungen pro Schicht**: 401, 413 und 429 pro Stunde. Ein plötzlicher Anstieg der Budget-429er heißt, dass jemand sondiert.
-   **Eingabe-Tokens pro Anfrage** als Verteilung, nicht als Durchschnitt. Ein langer Ausläufer bedeutet zu lockere Verlaufs- oder Größenlimits.
-   **Tageskosten pro Funktion gegen eine Baseline**, mit einem Spend Alert beim Anbieter deutlich unter dem Hard Limit.

Abstufen, bevor man abschaltet. Überschreiten die Ausgaben eine Schwelle, zuerst anonyme Nutzer abschalten, dann eingeloggte Nutzer auf ein kleineres Modell umstellen und die Funktion für zahlende Kunden am Leben halten. Das ist ein weit besserer Ausfallmodus, als wenn das Anbieterlimit alles auf einmal abschaltet. Zum Tracing der Aufrufe hinter diesen Zahlen siehe [Observability für LLM-Agenten](https://balazscsorba.com/de/blog/agent-observability-opentelemetry).

## Checkliste für eine öffentliche LLM-Route

1.  Der API-Schlüssel liegt nur in der Server-Runtime-Config; der Client sieht ihn nie.
2.  Die Route verlangt eine Session; anonyme Sessions gibt es nur nach serverseitig geprüfter Bot-Kontrolle.
3.  Modell, System-Prompt, Tools und `max_tokens` sind auf dem Server festgelegt.
4.  Anfragelimits pro IP an der Edge und pro Nutzer im Handler, in einem gemeinsamen Speicher.
5.  Body-Limit, Schema-Validierung, serverseitiger Verlauf und Token-Obergrenze vor dem Aufruf.
6.  Ein tägliches Token-Budget pro Nutzer mit atomarem Reservieren und Abrechnen.
7.  Begrenzte Retries, Tool-Schritte und Timeouts, damit der eigene Code nicht in Schleifen gerät.
8.  Ein eigener Workspace oder ein eigenes Projekt beim Anbieter pro Funktion, mit Spend Alert und Hard Limit.
9.  Alarme bei Token-Ausreißern pro Nutzer, Ablehnungsspitzen und Tageskosten, dazu ein Abstufungsplan.

Kostenmissbrauch ist die eine Hälfte des Risikos; die andere ist, was das Modell mit feindlicher Eingabe macht. Dazu siehe [Abwehr von Prompt Injection](https://balazscsorba.com/de/blog/prompt-injection-lethal-trifecta-patterns).

## Quellen

1.  [OWASP GenAI Security Project: LLM10:2025 Unbounded Consumption](https://genai.owasp.org/llmrisk/llm102025-unbounded-consumption/)
2.  [Nuxt Security: Rate Limiter middleware](https://nuxt-security.vercel.app/middleware/rate-limiter)
3.  [Nuxt Security: Request Size Limiter middleware](https://nuxt-security.vercel.app/middleware/request-size-limiter)
4.  [nuxt-auth-utils: README (GitHub)](https://github.com/atinux/nuxt-auth-utils)
5.  [h3: request utilities (getRequestIP, readValidatedBody)](https://h3.dev/utils/request)
6.  [Upstash: Ratelimiting algorithms](https://upstash.com/docs/redis/sdks/ratelimit-ts/algorithms)
7.  [Cloudflare Turnstile: Validate the token](https://developers.cloudflare.com/turnstile/get-started/server-side-validation/)
8.  [Claude Platform Docs: Rate limits and spend limits](https://platform.claude.com/docs/en/api/rate-limits)
9.  [Claude Platform Docs: Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting)
10.  [OpenAI API Docs: Spend limits](https://developers.openai.com/api/docs/guides/spend-limits)
11.  [OpenAI API Docs: Rate limits](https://platform.openai.com/docs/guides/rate-limits)

## Häufige Fragen

Was ist Denial of Wallet?

Denial of Wallet ist ein Angriff auf einen nutzungsbasiert abgerechneten Dienst, bei dem es um Kosten statt um Ausfall geht. OWASP nennt ihn als Beispiel für LLM10:2025 Unbounded Consumption: Ein Angreifer erzeugt so viele Operationen, dass die Rechnung für den Betreiber untragbar wird.

Reicht der Rate Limiter von nuxt-security für einen LLM-Endpunkt?

Er ist eine gute erste Schicht, aber laut eigener Dokumentation ist der eingebaute Rate Limiter nicht für komplexe Produktionsanwendungen geeignet. Er zählt Anfragen, keine Tokens, und sein Standard-LRU-Cache gilt pro Serverinstanz. Kombinieren Sie ihn mit einem Limit an der Edge und einem Token-Budget pro Nutzer in einem gemeinsamen Speicher wie Redis.

Soll ich nach IP oder nach Nutzer limitieren?

Beides. IP-Limits schützen die Routen, die vor dem Login funktionieren, und bremsen einfache Fluten. Für die Kosten zählen die Limits pro Nutzer, denn viele legitime Nutzer können sich eine IP teilen, und ein Angreifer kann viele IPs durchwechseln.

Wie begrenze ich die Länge von Prompts?

Die Größe des Request-Bodys begrenzen, die Nachrichtenlänge mit einem Schema prüfen, den Gesprächsverlauf auf dem Server halten statt ihn vom Client anzunehmen, und vor dem Modellaufruf die Token-Zahl prüfen. max\_tokens auf dem Server setzen, um die Ausgabe zu deckeln.

Schützen mich Spend Limits des Anbieters vor Missbrauch?

Nur als letzte Instanz. Hard Limits bei OpenAI und Spend Limits bei Anthropic stoppen beim Erreichen den gesamten Verkehr der Organisation, des Projekts oder Workspaces, ein Angreifer legt die Funktion damit für alle lahm. OpenAI weist außerdem darauf hin, dass die Durchsetzung nicht sofort erfolgt und die Ausgaben das Limit leicht überschreiten können.

Geschrieben von Balázs Csorba

Senior Fullstack & AI Engineer in der Steiermark – über 10 Jahre Vue, Nuxt, Node.js und PHP, heute baue ich Werkzeuge für KI-Agenten.

[Vue.js- & Nuxt-Entwicklung →](https://balazscsorba.com/de/expertise/vue-nuxt-developer)[Über mich →](https://balazscsorba.com/de/about)

## Weitere Artikel

-   [Mehrsprachiges SEO mit Nuxt i18n: URL-Strategie, hreflang, Canonicals und Sitemaps](https://balazscsorba.com/de/blog/nuxt-i18n-multilingual-seo-hreflang)
-   [llms.txt versus Markdown Content Negotiation: was Agenten wirklich abrufen](https://balazscsorba.com/de/blog/llms-txt-vs-markdown-content-negotiation)
-   [Ein 3D-Segelspiel mit Multiplayer in reinem three.js](https://balazscsorba.com/de/blog/multiplayer-sailing-game-threejs)
-   [Laden nach EPEX-Preisen in Österreich: was meine Home-Assistant-App spart](https://balazscsorba.com/de/blog/home-assistant-ev-charging-energy-manager)

## Klingt nach dem, was du suchst?

Erzähl mir von deinem Projekt oder deiner Stelle – ich freue mich, von dir zu hören.

[Kontakt aufnehmen](mailto:contact@balazscsorba.com) [Auf LinkedIn vernetzen](https://www.linkedin.com/in/balazs-csorba)
