Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

HTTP request smuggling primitive: bare LF accepted as a request-line terminator in strict mode

Offen
#877 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 6 Tagen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
55/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
node.js, typescript

Rechercherichtung

Beginne in url.ts:176 und verfolge url.exit.toHTTP09 bis zu headers_start. Vergleiche dabei den Pfad für ein einzelnes LF mit der Prüfung LENIENT_OPTIONAL_CR_BEFORE_LF, die für andere Terminatoren der Request-Line verwendet wird. Füge Regressionstests für versionslose und versionierte Requests im Strict Mode hinzu und überprüfe anschließend, dass der Strict Mode den Fall mit einem einzelnen LF ablehnt, ohne HTTP/0.9-Header oder einen Body zu parsen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

llhttp_set_lenient_optional_cr_before_lf documents that llhttp "would error when a LF is not
preceded by CR when terminating the request line", and that relaxing this exposes request smuggling.
url.ts:176 exits on a bare \n straight to the HTTP/0.9 adapter with no
LENIENT_OPTIONAL_CR_BEFORE_LF check — the only line terminator in the grammar that is ungated.

url.exit.toHTTP09 then continues into headers_start with no http_minor guard, so the message is
labelled HTTP/0.9 but headers and a Content-Length body are still parsed.

PoC

const http = require('http'), net = require('net');

const srv = http.createServer((req, res) => {          // default parser, no options
  let body = '';
  req.on('data', c => body += c);
  req.on('end', () => {
    console.log(`  ACCEPTED  HTTP/${req.httpVersion}  ${req.method} ${req.url}` +
                `  headers=${JSON.stringify(req.headers)}  body=${JSON.stringify(body)}`);
    res.end('ok');
  });
});
srv.on('clientError', e => console.log(`  REJECTED  ${e.code}`));

const cases = [
  ['versionless + bare LF', 'GET /x\nHost: a\r\nContent-Length: 5\r\n\r\nhello'],
  ['versioned   + bare LF', 'GET /x HTTP/1.1\nHost: a\r\n\r\n'],
];

srv.listen(0, async () => {
  for (const [name, raw] of cases) {
    console.log(name);
    await new Promise(done => {
      const c = net.connect(srv.address().port, '127.0.0.1', () => c.write(raw));
      c.on('close', done); c.on('error', done);
      setTimeout(() => c.destroy(), 300);
    });
  }
  srv.close();
});
versionless + bare LF
  ACCEPTED  HTTP/0.9  GET /x  headers={"host":"a","content-length":"5"}  body="hello"
versioned   + bare LF
  REJECTED  HPE_INVALID_VERSION

The same terminator is rejected when a version is present and accepted when it is absent. The
accepted message is reported as HTTP/0.9 yet carries headers and a body, neither of which HTTP/0.9
defines.

Scope, stated plainly: this path sets keepalive=0, and a pipelined follow-up request is rejected
with HPE_CLOSED_CONNECTION, so on its own it is a divergence from the documented strict-mode
guarantee rather than a demonstrated desync. Two requests parse on one connection only with
lenient_keep_alive also enabled.

Vorherrschende Sprache
TypeScript
Sterne
2k
Forks
236
Ø Merge
5 T. 2 Std.
Gemergte PRs (30 T.)
1

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus nodejs/llhttp

Alle Issues in nodejs/llhttp

Ähnliche Issues

Weitere Issues zu TypeScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.