Vydáno ve v2026.10.17, 21. 10. 2026  Oprava chyby v upstreamu mise

mise: neukončený řetězec v aqua šabloně zacyklil lexer

Náš skener upozornil, že mise, správce verzí vývojářských nástrojů, se mohl při čtení šablony z položky aqua registry donekonečna zacyklit. Poslali jsme pull request s opravou a regresním testem. Správce Jeff Dickey přidal další testy a týž den ho začlenil. Oprava vyšla v mise v2026.10.17.

Co bylo špatně

mise instaluje řadu nástrojů přes backend aqua. Položky registry popisují URL ke stažení a názvy souborů malými šablonami ve stylu Go a mise je parsuje vlastním lexerem v crates/aqua-registry/src/template.rs.

Když token začínal znakem ", lex() hledal uzavírací uvozovku. Pokud žádná nebyla, nebo byly všechny kandidátní uvozovky escapované, vstup se neposunul a vnější smyčka while !code.is_empty() vstupovala pořád do stejné větve. Vadná šablona jako {{"abc}} tak mise zasekla místo toho, aby ohlásil chybu.

Kontrola escapování měla ještě druhou vadu: bajtový offset z match_indices používala jako index znaku (code.chars().nth(end)) a nerozlišovala \" od \\".

Šablony pocházejí ze zabudované registry nebo z registry, které si nastaví sám uživatel. Jde tedy o zaseknutí na vadné položce registry, ne o vzdálený útok. Upstream to popisuje stejně.

Jak to bylo opraveno

Lexer teď před každou kandidátní uvozovkou spočítá zpětná lomítka po bajtech, za uzavírací ji považuje jen při sudém počtu, a když uzavírací uvozovku nenajde, skončí chybou:

             for (end, _) in code[1..].match_indices('"') {
-                if code.chars().nth(end) != Some('\\') {
-                    tokens.push(Token::String(&code[1..end + 1]));
+                let slash_count = code[1..=end]
+                    .bytes()
+                    .rev()
+                    .take_while(|&b| b == b'\\')
+                    .count();
+                if slash_count % 2 == 0 {
+                    tokens.push(Token::String(&code[1..=end]));
                     code = &code[end + 2..];
+                    found = true;
                     break;
                 }
             }
+            if !found {
+                bail!("unterminated string literal");
+            }

Náš pull request přidal regresní test test_render_unterminated_string_fails. Jeff Dickey (jdx) pak doplnil commity, které ověřují přesné znění chyby „unterminated string literal“ a pokrývají prázdný řetězec, a pull request začlenil. Poznámky k vydání mise v2026.10.17 změnu popisují takto:

“An aqua registry template with an unterminated string literal now fails with an "unterminated string literal" error instead of hanging. Escaped quotes after backslashes are also detected correctly.”

Časová osa

Jak to číst

Triáž skeneru počítala se škodlivou registry nebo útočníkem uprostřed spojení. Ve skutečnosti šablony pocházejí z registry, kterou mise dodává, nebo z registry, kterou si zvolil uživatel. Poctivý popis je tedy zaseknutí na vadné šabloně a stejně to popisuje i upstream. Nálezy jsou podněty pro lidi, ne rozsudky.

Zdroje

← Zpět na příběhy úspěchu