fix: SSRF-haertung (IP-pinning) + blank-page-schutz aus security-review

- scan & releases/from-url: verbindung wird an die bereits validierte IP
  gepinnt (node:http/https lookup-option), statt fetch erneut aufloesen zu
  lassen. Schliesst DNS-rebinding/TOCTOU, mit dem ein lizenzierter Kunde
  ueber die DNS seiner eigenen Domain interne Dienste/Cloud-Metadaten
  erreichen koennte.
- releases/from-url folgt redirects jetzt manuell und validiert jeden hop
  (protokoll + private-IP-guard); gitea-token nur an den ausgangs-host.
- pinnedRequest: settle-guard + body-cap loesen das promise auch bei
  ueberlangen antworten (kein haengen).
- autodetect process(): kein blank-page mehr bei PCRE-fehler (fallback auf
  original-HTML statt (string) null = "").
- cleanup: ungenutztes extract_iframe_src() entfernt; redundantes
  &-replace in get_src() entfernt (DOMDocument dekodiert bereits).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
s4luorth
2026-06-08 06:52:22 +02:00
parent 40f4207024
commit ca0f2f2c32
3 changed files with 113 additions and 32 deletions

View File

@@ -52,13 +52,18 @@ class CB_Autodetect {
}
// Locate iframe blocks only. Attribute parsing happens via DOMDocument below.
return (string) preg_replace_callback(
$out = preg_replace_callback(
'#<iframe\b[^>]*>.*?</iframe>#is',
function ( array $m ) use ( $services ): string {
return self::maybe_replace_iframe( $m[0], $services );
},
$html
);
// On a PCRE error (e.g. backtrack/recursion limit on a huge page),
// preg_replace_callback returns null. Never blank the page — fall back to
// the original, unmodified HTML.
return $out === null ? $html : $out;
}
/**
@@ -99,11 +104,8 @@ class CB_Autodetect {
return '';
}
$src = trim( $node->getAttribute( 'src' ) );
// Normalise protocol-relative and HTML-entity-encoded ampersands.
$src = str_replace( '&amp;', '&', $src );
return $src;
// getAttribute() already returns the entity-decoded value (e.g. &amp; → &),
// so no further unescaping is needed here.
return trim( $node->getAttribute( 'src' ) );
}
}