### Descrição (como relatado). Em Jetty 12.1.8, org.eclipse.jetty.util.URIUtil.canonicalPath() pode deixar os segmentos de caminho de pontos desnormalizados quando um marcador de caminho de pontos virgulos é seguido por um barra e um segmento de pontos. Um exemplo mínimo é. `/ público;/../ administrador/ secret` Na minha reprodução local, URIUtil.canonicalPath() retorna. `/ público/../ administrador/ secret` em vez do caminho normalizado esperado. Quando o `SecurityHandler.PathMapped` do Jetty é usado para proteger um prefixo de caminho como `/ admin/*`, o caminho canônico não normalizado pode não corresponder ao prefixo protegido. Como resultado, um pedido não autenticado pode evitar a constrição de segurança baseada no caminho configurado.

Jetty: 12.1.8 JDK: 17.0.18 Maven: 3.9.14. Artefatos Maven usados: org. eclipse. jetty: jetty- server: 12.1.8 org. eclipse. jetty: jetty- security: 12.1.8 org. eclipse. jetty: jetty- session: 12.1.8 Apenas Jetty confirmado 12.1.8 Até agora. Inicia um servidor Jetty mínimo com a seguinte configuração de segurança. ```java SecurityHandler.PathMapped Security = novo SecurityHandler.PathMapped(); security.put("/admin/*", Contraint.from("admin")); security.put("/*", Contraint.ALLOWED); security.setAuthenticator(novo Authenticator Basic()); ````.

O teste então envia pedidos sem o cabeçalho `Autorização`. ``` GET /admin/ secret -> 401 GET /public;x/../admin/ secret -> 200 ```. O manipulador recebe caminhos como: `/ público/../ administrador/ secret`. Isto sugere que a constrição de segurança `/ admin/*` é evitada porque a correspondência com o `PathMapped` é realizada contra o caminho canônico não normalizado. #### Suspeito de Causa Raiz. A causa raiz suspeita está em `URIUtil. canonicalPath()'.

A lógica relevante é aproximadamente. ````java for (int i = 0; i < end; i++) { char c = codificadoPath.charAt( i); interruptor (c) { caso '; ': se (construtor == null) { construtor = novo utf 8 StringBuilder(encodedPath.length()); builter. append(encodedPath, 0, i); } enquanto (++i < final) { se (encodedPath.charAt(i) == '/ ') { builder. append('/ '); break; } } break; caso '.': se (slash) normal = false; se (construtor!= null) builder. append( c); quebra; }.

Cordas canônicas = (construtor!= null)? (onBadUtf 8 == null? builder.toCompleteString(): builder.takeCompleteString(onBadUtf 8 )): codificadoPath; retorna normal? canônico: normalizePath (canônico); `` `/ público;/../ administrador/ secret`. quando o loop externo atingir o ponto epígrafe: ``` i = 7 c = '; ' slash = falso normal = verdadeiro `` ' Dentro de `case ';', o loop `while (++i < end)' avança i para o próximo caractere, que já está '/' para o formulário do caminho vazio ";/".

O código então anexa '/' ao construtor canônico. ` builder. append('/');` Neste ponto, o construtor canônico termina com '/'. No entanto, a variável local ` c` ainda é o antigo valor '; ', porque ` c` foi lida antes de inserir o interruptor e não é atualizada quando o loop interno avança ` i '. Após deixar o interruptor, o loop atualiza o estado de barra usando. Como ` c ` ainda é '; ', o slash se torna ` falso '. Na próxima iteração, o scanner atinge '.', que é o primeiro ponto no segmento "../". Como a barra é incorretamente "false", este código não é executado:.

```java se (slash) normal = falso; ```. Portanto `normal` permanece `verdadeiro`, e `canonicalPath()` retorna a string canônica diretamente em vez de chamar `normalizePath(canonical)'. `/ público/../ administrador/ secret`. ` case ';'' adianta a posição de digitalização i e anexa '/' para o construtor canônico, mas a cauda do loop ainda atualiza a barra do caractere stal `c=';'. Como resultado, o segmento de pontos- pontos seguinte não é detectado como um segmento de percurso transversal. #### Condição mais precisa para o desencadeamento. O problema não se limita a um parâmetro de caminho não vazio como ";x". A forma mais precisa do gatilho é. ``` /public;/../admin/secret /public;x/./admin/secret /public; qualquer coisa/../admin/secret /public;/./admin/secret ``.

O formulário mínimo é. `/ público;/../ administrador/ secret` porque o ponto epígrafe é imediatamente seguido por '/', então o loop interno enquanto alcança '/' no seu primeiro incremento. #### Direção de correção mínima potencial. Uma correção mínima seria garantir que, quando o caso ';' consome entrada até '/' e anexa '/' ao construtor canônico, o estado de barra reflecte o último caráter eficaz no caminho canônico. Por exemplo, conceitualmente. ``` caso java';': if (construtor == null) { construtor = novo Utf 8 StringBuilder(encodedPath.length()); builter. append(encodedPath, 0, i); }.

enquanto (++i < final) { se (encodedPath.charAt(i) == '/') { builder. append('/'); slash = true; break; } } continuar; ``` A parte importante é evitar que a cauda do loop sobrescreva a barra usando o valor 'c' estável: Em outras palavras, o ` slash ' deve representar o último caractere eficaz anexado ao construtor canônico, não o caractere original de entrada lido antes do caso '; '' avançado `i'. Registro de aconselhamento: GHSA-w 7 x 5 - g 22 V- xqhr. Identificadores relacionados: CVE- 2026 - 8384.

Tempo: GitHub Advisory Database publicou este registro em 2026 - 07 - 22 T 22: 57: 36.000 Z e lista a sua última modificação como 2026 - 07 - 22 T 22: 57: 36.000 Z. Gravidade: MODERAR. Dados de pontuação publicados: CVSS_V 3: CVSS: 3.1 /AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N. Software afetado e informações de versão: pacote Maven org. eclipse.jetty:jetty- util — ECOSISTEM: introduzido 12.0.0, corrigido 12.0.35. Pacote Maven org. eclipse.jetty:jetty- util — ECOSYSTEM: introduzido 12.1.0, corrigido 12.1.9. Classificação e evidência: identificadores de fraqueza CWE- 647. O registro contém 10 suporte de referências nestes tipos: WEB, AVISO, EMBALAGAMENTO.