rep+: Ein AI-gestützter Repeater direkt in den Chrome DevTools

Motivation rep+ ist eine leichte Chrome-DevTools-Erweiterung, inspiriert von Burp Suite Repeater. Ziel: Requests schnell untersuchen, ohne die komplette Burp-Pipeline hochzufahren. Mit integrierter LLM-Unterstützung (lokal oder API) werden Header/Bodies generiert, transformiert oder erklärt – direkt neben dem Network-Panel.

Kernfunktionen

  • DevTools-Panel “rep+” mit tabs für einzelne Requests
  • Import aus Network-Panel (inkl. Methode, URL, Header, Body)
  • Wiederholung von Requests mit editierbaren Headern/Body
  • Mehrere Umgebungen (Base URL, Default-Header, Variablen)
  • AI-Aktionen: Body/Headers vorschlagen, transformieren, Templates erzeugen, Unterschiede erklären
  • Diff-Ansicht für Response-Körper und -Header (inline und side-by-side)
  • Status/Timing/Size-Metriken, automatische Wiederholungen
  • cURL/HAR Import/Export, JSON-Sessionsharing
  • Tastatursteuerung für schnelles Iterieren

Architekturüberblick

  • MV3 Service Worker: führt Requests aus (fetch), verwaltet Sessions und Settings, ruft optional LLMs
  • DevTools Panel (UI): Editor, Diff, AI-Controls, Session-Verwaltung
  • Messaging: chrome.runtime/message passing zwischen Panel und Worker
  • Persistenz: chrome.storage.local (Sessions, Environments, Provider-Konfiguration)
  • Optional: Offlinemodus für AI (lokale Modelle)

DevTools-Integration

  • Panel-Erstellung via chrome.devtools.panels.create(“rep+”, …).
  • Import aus Network-Panel über chrome.devtools.network.onRequestFinished:
    • Extrahiert: URL, Methode, Header (request/response), Body (request), Timing, Status, Cookies (soweit zugänglich).
    • Speichert als RequestSpec in rep+.

Request-Replay-Engine

  • Ausführung: fetch im Service Worker mit RequestInit (method, headers, body, redirect, credentials)
  • Wiederholungen: konfigurierbarer Retry mit Backoff
  • Protokolle: HTTP/1.1/2 abhängig vom Browser; kein Low-Level-TLS-Fingerprint-Tuning
  • Zeitlimits: globales Timeout pro Request; Abbruch via AbortController
  • Response-Erfassung: Status, Header, Body (Text/Binär als Base64), Größe, Dauer, Redirect-Kette

Header/Body-Grenzen und CORS

  • Nicht setzbare Header (Browser-forbidden): Host, Content-Length, Connection, Transfer-Encoding, Origin (teilweise), Referer (restriktiv), Sec-*
  • Content-Length wird automatisch gesetzt
  • Cookies: mit credentials: “include” werden Domain-Cookies gesendet, wenn host_permissions passen
  • CORS: Extension-Kontext unterliegt nicht der Page-CORS-Policy, aber Cross-Origin-Fetch benötigt host_permissions
  • TLS/ALPN/Fingerprint weicht von nativen Clients oder Burp ab; Serververhalten kann minimal variieren

AI-Assistenz

  • Provider:
    • Lokal: Ollama (HTTP API), LM Studio, OpenAI-compatible Gateway
    • Remote: OpenAI, Anthropic, Azure OpenAI, Together, Mistral (API-Keys)
  • Funktionen:
    • Prompt-gestützte Transformationen (z. B. “mach daraus valid JSON”, “erzeuge multipart/form-data mit Datei-Platzhalter”)
    • Header/Body-Vervollständigungen, Param-Exploration, Payload-Mutationen (fuzz-lite)
    • Response-Erklärung, Regexp-Extraktion, Schema-Hypothesen
  • Token-/Kostenkontrolle:
    • Max tokens pro Anfrage, Rate Limit, Stop-Sequenzen
    • Kontext-Zuschnitt: nur relevante Teile (Methode, URL, selektive Header, Body-Ausschnitt)
  • Privacy:
    • Redaktionsregeln: Secrets (Cookies, Tokens) standardmäßig maskieren, manuell freigeben
    • Offlinemodus: Nur lokaler LLM, kein externer API-Call
  • Streaming:
    • Optionales Token-Streaming ins UI für schnelle Iteration

Installation (aus Source)

  • Voraussetzungen: Node.js 18+, pnpm oder npm
  • Schritte:
git clone https://github.com/your-org/rep-plus.git
cd rep-plus
pnpm install
pnpm build
  • In Chrome:
    • chrome://extensions
    • Entwicklermodus aktivieren
    • Entpackte Erweiterung laden dist/ auswählen
    • DevTools öffnen Tab “rep+”

Minimaler MV3-Manifestauszug

{
  "name": "rep+",
  "description": "Lightweight DevTools Repeater with AI",
  "version": "0.1.0",
  "manifest_version": 3,
  "devtools_page": "devtools.html",
  "background": { "service_worker": "worker.js", "type": "module" },
  "permissions": ["storage"],
  "host_permissions": ["https://*/", "http://*/"],
  "action": { "default_title": "rep+" },
  "icons": { "16": "icon16.png", "48": "icon48.png", "128": "icon128.png" }
}

DevTools-Panel Bootstrap

  • devtools.html bindet devtools.js, das das Panel erzeugt
chrome.devtools.panels.create(
  "rep+",
  "icon16.png",
  "panel.html",
  function(panel) {
    // optional: panel.onShown.addListener(...)
  }
);

Service-Worker Skizze (Request-Ausführung)

chrome.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
  if (msg.type === "REPLAY") {
    try {
      const ctrl = new AbortController();
      const t = setTimeout(() => ctrl.abort(), msg.timeoutMs ?? 30000);
      const res = await fetch(msg.url, {
        method: msg.method,
        headers: msg.headers,
        body: msg.body,
        redirect: msg.redirect ?? "follow",
        credentials: msg.credentials ?? "include",
        signal: ctrl.signal
      });
      clearTimeout(t);

      const buf = await res.arrayBuffer();
      sendResponse({
        ok: res.ok,
        status: res.status,
        statusText: res.statusText,
        headers: [...res.headers.entries()],
        bodyB64: btoa(String.fromCharCode(...new Uint8Array(buf))),
        url: res.url
      });
    } catch (e) {
      sendResponse({ error: String(e) });
    }
    return true; // async
  }
});

Import aus Network Panel

  • Listener in devtools.js:
chrome.devtools.network.onRequestFinished.addListener(async (req) => {
  const requestBody = await new Promise((resolve) =>
    req.getContent((content, encoding) => resolve({ content, encoding }))
  );
  const entry = {
    url: req.request.url,
    method: req.request.method,
    headers: req.request.headers,
    postData: requestBody,
    status: req.response.status,
    responseHeaders: req.response.headers,
    timings: req.time,
  };
  chrome.runtime.sendMessage({ type: "IMPORT", entry });
});

Datenmodell (vereinfacht)

type RequestSpec = {
  id: string
  name?: string
  url: string
  method: string
  headers: { name: string, value: string }[]
  body?: string | { type: "base64", data: string }
  environmentId?: string
};

type ResponseRecord = {
  status: number
  statusText: string
  headers: { name: string, value: string }[]
  bodyB64?: string
  durationMs: number
  sizeBytes: number
  url: string
};

type Tab = { request: RequestSpec, history: ResponseRecord[] };

type Session = { tabs: Tab[], environments: Environment[], createdAt: number };

Umgebungen und Variablen

  • Environments definieren:
    • baseUrl, defaultHeaders, variables (Key/Value, z. B. token, userId)
  • Variablenersetzung im Request:
    • {{varName}} in URL, Headern, Body
  • Mehrere Environments pro Session; schnelle Umschaltung

AI-Provider-Konfiguration

  • Felder:
    • provider: “ollama” | “openai” | “anthropic” | “openai-compatible”
    • endpoint: z. B. http://localhost:11434
    • model: z. B. llama3.1:8b, gpt-4o-mini, claude-3.5-sonnet
    • apiKey: nur wenn erforderlich
    • maxTokens, temperature, rateLimitRps
    • redactSecrets: true/false
  • Beispiel (Ollama):
{
  "provider": "ollama",
  "endpoint": "http://localhost:11434",
  "model": "llama3.1:8b",
  "redactSecrets": true
}

Typische Workflows

  • Aus dem Network-Panel übernehmen:
    • Request im Network-Panel wählen Button “Import to rep+”
    • In rep+ Header/Body anpassen
    • Mit Cmd/Ctrl+Enter ausführen, Responses vergleichen
  • cURL importieren:
    • cURL in Zwischenablage Import cURL einfügen
    • Automatisches Mapping auf Methode, URL, Header, Body
  • Schnell-Diff:
    • Tab duplizieren, nur ein Feld ändern
    • Responses side-by-side vergleichen
  • AI-gestützte Mutation:
    • Prompt: “Füge XSS-ähnliche Payload in alle text/html Felder ein”
    • Vorschau prüfen, ausführen, Resultate sichten

Tastenkürzel

  • Cmd/Ctrl+Enter: Ausführen
  • Cmd/Ctrl+D: Tab duplizieren
  • Cmd/Ctrl+/: AI-Prompt öffnen
  • Alt+←/→: Zwischen Tabs wechseln
  • Esc: Laufende AI-Ausgabe/Streaming abbrechen

Import/Export

  • HAR: Auswahl an Requests als HAR exportieren, HAR-Import erzeugt Tabs
  • cURL: Rundtripfähig (Import/Export)
  • Session: JSON mit Tabs/Environments; geeignet zum Teilen/Versionieren

Berechtigungen und Sicherheit

  • host_permissions: Ziel-Domains für Cross-Origin-Fetch
  • storage: Persistenz der Sessions/Settings
  • Optional cookies: Nur wenn programmatic Zugriff auf Cookies benötigt wird
  • Geheimnisse:
    • Redaction by default (Cookies, Authorization) für AI-Prompts
    • Explizites Opt-in zum unmaskierten Senden
  • Keine Inhalte werden ohne Nutzeraktion an externe LLMs gesendet
  • Offlinemodus erzwingt lokale LLMs

Grenzfälle und Tipps

  • Auth-Header: Authorization: Bearer … wird gesendet; aber achte auf Redaction-Regeln beim AI-Context
  • Set-Cookie in Responses: wird erfasst, aber nicht automatisch persistiert; Cookies verwaltet der Browser
  • Multipart: Boundary wird automatisch generiert, wenn Body per FormData gesendet wird; bei Raw multipart muss Boundary konsistent gesetzt werden
  • Redirects: redirect: “follow” / “manual” steuerbar; bei “manual” Location-Header selbst auswerten
  • Binärpayloads: In UI base64 anzeigen; Download-Button für Payload-Export
  • Nicht setzbare Header (Host, Content-Length): vom Browser bestimmt; bei Host-Header-Hardchecks ggf. via Reverse-Proxy testen

Fehlersuche

  • 403/401 trotz gültiger Cookies: Prüfe credentials: “include” und host_permissions
  • CORS-Fehler: In Extensions eher host_permissions-Thema; Manifest prüfen
  • TLS/JA3-Mismatch: Browser-Stack ist nicht anpassbar; vergleiche mit echten Clients nur bedingt
  • AI blockiert: Rate Limit oder Token-Limit erhöhen; Streaming deaktivieren, wenn Prompts groß sind

Tags #chrome-extensiondevtoolsrepeaterburphttpaillmmv3securityprivacycurlharwebdebuggingproductivity

Brain-Overview