ai newsFr., 23. Okt.
EilmeldungAI Referral Traffic Converts Better. That Does Not Mean You Should Chase It Blindly.

Claude bricht beim Server-Patchen ab, lokales LLM springt ein

Nach zwei kritischen Remote Code Execution Lücken in PHP, bekannt als PHP2Shell, stand ein Admin vor der Aufgabe, sieben RunCloud-Server mit rund 30 WordPress-Seiten zu patchen. Während Claude die Arbeit verweigerte, übernahm ein lokal betriebenes LLM die Aufgabe.

dev.toDonnerstag 23:33 · 22.10.DE5 Min. Lesezeit
Bild: dev.to

Am 21. und 22. Oktober verbrachte ich zwei lange Tage mit dem Patchen unserer eigenen Server. PHP hatte ein Notfall-Release für zwei kritische Remote-Code-Execution-Schwachstellen angekündigt, die inzwischen unter dem Namen "PHP2Shell" bekannt sind. Wir betreiben sieben RunCloud-Server mit etwa 30 WordPress-Seiten, und einige davon laufen auf PHP-Versionen, die keine offiziellen Fixes mehr erhalten.

Die meiste Arbeit erledigte ich gemeinsam mit Hermes, meinem AI-Agenten, der Claude Opus 5.5 verwendete. Es lief gut, bis es nicht mehr lief. Mitten in der Aufgabe hörte das Cloud-Modell auf zu antworten. Mein lokales Modell, Qwen3.8-Flash-Next auf meiner eigenen Workstation, übernahm dieselbe Sitzung und beendete die Arbeit.

Dieser Beitrag beschreibt, was passiert ist, warum das Cloud-Modell aussetzte und warum ich ein lokales Modell inzwischen als echte Absicherung betrachte.

Der Agent hatte das Inventar erstellt: 32 Seiten, 206 Plugins, 300 Plugin/Version-Kombinationen. Er hatte diese mit der kostenlosen WPVulnerability-Datenbank abgeglichen und durchsuchte die Zugriffslogs nach verdächtigen Anfragen an wp-content/uploads.

Dann erhielt ich auf jede Nachricht dieselbe Antwort:

Your request was not processed. Send it again if you still want me to carry it out. Ich probierte "continue", "try it another way" und "try again, differently". Die Antwort war jedes Mal dieselbe. Als ich fragte, wo es hänge, antwortete es ganz normal. Es sagte, es habe in diesen Runden nichts ausgeführt und könne sich keinen Reim darauf machen. Seine Vermutung war ein Problem mit der Kontextlänge oder ein Ausfall.

Das war beides nicht der Fall. Das Hermes-Log enthielt den wahren Grund:

2026-10-22 14:49:28 WARNING [20261021_095417_816396] agent.conversation_loop: Model declined to respond (finish_reason=content_filter). model=claude-opus-5-5[1m]... refusal=This request triggered restrictions on violative cyber content and was blocked under Anthropic's Usage Policy. In dieser Sitzung gab es zwischen 14:49 und 16:42 fünf solcher Vorfälle, und einen weiteren in einer separaten Sitzung, in der ich einen Kundenbericht über dieselbe Schwachstelle anforderte. Diese Berichtssitzung war tatsächlich die erste, die ich zum lokalen Modell verschob, und es fertigte den Bericht dort an.

Claude Opus 5.5 läuft hinter Safety-Klassifikatoren. Wenn einer anspricht, liefert die rohe API eine normale Antwort mit stop_reason: "refusal" und einer Kategorie zurück. Hermes protokollierte dies als finish_reason=content_filter, ohne das Kategorie-Feld, aber der Refusal-Text verweist auf die Cyber-Kategorie. Anthropics Dokumentation zu Refusals und Fallbacks beschreibt es so: Die Kategorie deckt Anfragen ab, die "cyber harm ermöglichen könnten, etwa Malware- oder Exploit-Entwicklung", und "benigne Cybersicherheitsarbeit kann diese Kategorie ebenfalls auslösen."

Dieser zweite Satz betraf uns. Blick darauf, was zu diesem Zeitpunkt im Kontextfenster stand:

Für einen Klassifikator sieht "lies den verwundbaren Codepfad und finde genau heraus, wie der Bug funktioniert" gleich aus, ob man ihn patchen oder ausnutzen will. Meine Lesart ist, dass der Klassifikator die Anfrage als Ganzes betrachtet, einschließlich der Tool-Ausgabe, die der Agent gerade gelesen hatte. Meine Nachricht war "continue". Der Kontext war das Problem.

Zur Fairness: Das ist kein Bug, und ich verstehe, warum es den Klassifikator gibt. Die Dokumentation beschreibt auch eine serverseitige Fallbacks-Option, die eine abgelehnte Anfrage bei einem anderen Claude-Modell erneut versucht. Mein Setup läuft in Hermes über einen abonnementbasierten Anbieter, der das nicht nutzt, deshalb endete die Sitzung für mich einfach. Wer direkt auf der API aufbaut, sollte prüfen, ob es für seine Refusal-Kategorie ein empfohlenes Fallback-Modell gibt, und Refusals als eigenes Ereignis protokollieren. Ein Refusal ist ein HTTP 200, daher sieht das Monitoring der Fehlerrate ihn nicht.

Meine Workstation ist ein Ryzen 9 9950X3D mit einer RTX 5090 und 128 GB RAM. Darauf betreibe ich bereits mehrere große offene Modelle. Ich habe über Qwen3.8-Flash-Next mit Strata und einem 5-Bit-Quant geschrieben und vier lokale Modelle direkt verglichen.

Hermes behandelt den lokalen Server einfach als weiteren OpenAI-kompatiblen Anbieter:

providers: strata-qwen: name: Strata Qwen3.8-Flash-Next (UD-Q5_K_XL) base_url: http://127.0.0.1:8081/v1 default_model: strata models: strata: context_length: 524288 Der Wechsel bestand aus zwei Schritten:

Hermes bewahrt den Sitzungsverlauf auf, sodass Qwen den vollständigen Kontext übernahm: das Inventar, die CVE-Liste, die Recherche, die Opus und seine Subagenten bereits erledigt hatten, die bereits heruntergeladenen Plugin-Quellen, die früheren Entscheidungen und meine ständigen Regeln (keine Plugin-Updates, zuerst Backup, bei jedem Fehler zurückrollen).

Von 17:45 bis 18:38 machte Qwen 66 Modellaufrufe. Der Prompt wuchs von etwa 121k auf 212k Token, deutlich innerhalb des 512k-Kontexts. Sobald der Prompt-Cache warm war, dauerten Runden 3 bis 20 Sekunden. Etwa 20 Runden verfehlten den Cache, meist während er den Patcher schrieb, und dauerten jeweils 70 bis 115 Sekunden. Das ist langsamer als die Cloud, aber es lief weiter.

Perfekt war es nicht. Der Patcher hatte zwei Bugs: \$ in Python-Ersetzungsstrings und einen Slug-Vergleich, der Ordnernamen mit Versionsnummern übersehen hatte. Er fand beide in seinem eigenen lokalen Testlauf und behob sie. Eine Zahl in seiner finalen Zusammenfassung (56 gepatchte Plugin-Kopien) passte nicht zum früheren Bericht (48), und ich habe diese Abweichung noch nicht vollständig geklärt. Solche Dinge prüft man ohnehin, ganz gleich welches Modell man verwendet.

Ein lokales Modell ist eine Versicherung. Ich betreibe Qwen nicht lokal, weil es besser als Opus wäre. Für die meiste Arbeit nutze ich weiterhin das Cloud-Modell. Aber das Cloud-Modell kann aus Gründen aussetzen, die man nicht kontrolliert: ein Klassifikator, ein Ausfall, ein Rate Limit, eine Richtlinienänderung. Wenn das mitten im Patchen laufender Server passiert, ist "kommen Sie später wieder" keine gute Option. Ein lokales Modell mit denselben Tools, demselben Agenten und demselben Sitzungsverlauf bedeutet, dass man weiterarbeiten kann.

Ein paar praktische Hinweise, wenn Sie dieses Setup wollen:

Ich erwarte, dass Cloud-Modelle in einigen Bereichen streng bleiben, und das ist ihre Entscheidung. Sicherheitsarbeit an den eigenen Servern wird immer ein wenig wie Angriffsarbeit aussehen. Ein leistungsfähiges Modell auf der eigenen Hardware bedeutet, dass diese Entscheidung die eigene Arbeit nicht stoppt.

Automatisch übersetzt. Das Original auf Englisch ist unten aufklappbar.

Original (Englisch) anzeigen

On October 21 and 22, I spent two long days patching our own servers. PHP had announced an emergency release for two critical remote code execution bugs, now known as "PHP2Shell". We run seven RunCloud servers with about 30 WordPress sites, and several of them are on PHP versions that no longer get official fixes.

I did most of the work together with Hermes, my AI agent, running Claude Opus 5.5. It went well until it didn't. In the middle of the job, the cloud model stopped answering. My local model, Qwen3.8-Flash-Next on my own workstation, picked up the same session and finished the work.

This post covers what happened, why the cloud model stopped, and why I now see a local model as a real backup.

The agent had built the inventory: 32 sites, 206 plugins, 300 plugin/version pairs. It had matched them against the free WPVulnerability database and was checking access logs for suspicious requests to wp-content/uploads.

Then every message I sent got the same reply:

Your request was not processed. Send it again if you still want me to carry it out. Enter fullscreen mode Exit fullscreen mode I tried "continue", "try it another way", and "try again, differently". The reply was the same each time. When I asked where it got stuck, it answered normally. It said it had not executed anything in those turns and could not see why. Its guess was a context length issue or an outage.

It wasn't either of those. The Hermes log had the real reason:

2026-10-22 14:49:28 WARNING [20261021_095417_816396] agent.conversation_loop: Model declined to respond (finish_reason=content_filter). model=claude-opus-5-5[1m]... refusal=This request triggered restrictions on violative cyber content and was blocked under Anthropic's Usage Policy. Enter fullscreen mode Exit fullscreen mode There were five of these in that session between 14:49 and 16:42, and one more in a separate session where I asked for a client report about the same breach. That report session was actually the first one I moved to the local model, and it finished the report there.

Claude Opus 5.5 runs behind safety classifiers. When one fires, the raw API returns a normal response with stop_reason: "refusal" and a category. Hermes logged it as finish_reason=content_filter, without the category field, but the refusal text points to the cyber category. Anthropic's refusals and fallback docs describe it like this: the category covers requests that "could enable cyber harm, such as malware or exploit development", and "benign cybersecurity work can also trigger this category."

That second sentence was us. Look at what was in the context window at that point:

To a classifier, "read the vulnerable code path and figure out exactly how the bug works" looks the same whether you want to patch it or exploit it. My reading is that the classifier looks at the request as a whole, including the tool output the agent had just read. My message was "continue". The context was the problem.

To be fair: this isn't a bug, and I understand why the classifier exists. The docs also describe a server-side fallbacks option that retries a refused request on a different Claude model. My setup goes through a subscription-based provider in Hermes that doesn't use it, so for me the session just stopped. If you build on the API directly, check whether your refusal category has a recommended fallback model, and log refusals as their own event. A refusal is an HTTP 200, so error-rate monitoring won't see it.

My workstation is a Ryzen 9 9950X3D with an RTX 5090 and 128 GB of RAM. I already run several large open models on it. I wrote about Qwen3.8-Flash-Next with Strata and a 5-bit quant and compared four local models side by side.

Hermes treats the local server as just another OpenAI-compatible provider:

providers: strata-qwen: name: Strata Qwen3.8-Flash-Next (UD-Q5_K_XL) base_url: http://127.0.0.1:8081/v1 default_model: strata models: strata: context_length: 524288 Enter fullscreen mode Exit fullscreen mode The switch took two steps:

Hermes keeps the session history, so Qwen picked up the full context: the inventory, the CVE list, the research that Opus and its subagents had already done, the plugin sources already downloaded, the earlier decisions, and my standing rules (no plugin updates, back up first, roll back on any error).

From 17:45 to 18:38, Qwen made 66 model calls. The prompt grew from about 121k to 212k tokens, well within the 512k context. Once the prompt cache was warm, turns took 3 to 20 seconds. About 20 turns missed the cache, mostly while it was writing the patcher, and took 70 to 115 seconds each. That's slower than the cloud, but it kept going.

It wasn't flawless. The patcher had two bugs: \$ in Python replacement strings, and a slug comparison that missed folder names with version numbers. It found both in its own local test run and fixed them. One count in its final summary (56 patched plugin copies) didn't match the earlier report (48), and I haven't fully reconciled that difference yet. Those are the kinds of things you check anyway, whatever model you use.

A local model is insurance. I don't run Qwen locally because it's better than Opus. For most work, I still use the cloud model. But the cloud model can stop on you for reasons you don't control: a classifier, an outage, a rate limit, a policy change. When that happens halfway through patching live servers, "come back later" isn't a good option. A local model with the same tools, the same agent, and the same session history means you can keep going.

A few practical points if you want this setup:

I expect cloud models to stay strict in some areas, and that's their call to make. Security work on your own servers will always look a bit like attack work. Having a capable model on your own hardware means that decision doesn't stop your work.

Originaltitel: Claude refused to finish patching my servers. My local LLM took overQuelle: dev.to (dev.to). Original öffnen