Análise de dependência
A verificação de dependência no GitHub Advanced Security for Azure DevOps deteta os componentes de código aberto usados em seu código-fonte e deteta se há alguma vulnerabilidade associada. Qualquer vulnerabilidade encontrada de componentes de código aberto é sinalizada como um alerta.
O GitHub Advanced Security for Azure DevOps funciona com o Azure Repos. Se você quiser usar a Segurança Avançada do GitHub com repositórios do GitHub, consulte Segurança Avançada do GitHub.
Sobre a verificação de dependência
A verificação de dependência gera um alerta para qualquer componente de código aberto, direto ou transitivo, considerado vulnerável do qual seu código depende. As vulnerabilidades diretas são as bibliotecas que seu código usa diretamente. Dependências transitivas são as bibliotecas ou outros softwares que as dependências diretas usam.
Sobre a deteção de varredura de dependência
Um novo instantâneo de seus componentes é armazenado sempre que o gráfico de dependência de um repositório é alterado e depois que um pipeline que contém a tarefa de verificação de dependência é executado.
Para cada componente vulnerável detetado em uso, o componente e a vulnerabilidade são listados no log de compilação e exibidos como um alerta na guia Segurança Avançada. Somente os avisos revisados pelo GitHub e adicionados ao Banco de Dados de Avisos do GitHub criam um alerta de verificação de dependência. O log de compilação inclui um link para o alerta individual para investigação adicional. Para obter mais informações sobre os detalhes do alerta, consulte Corrigindo alertas de verificação de dependência.
O log de compilação também contém informações básicas sobre cada vulnerabilidade detetada. Esses detalhes incluem a gravidade, o componente afetado, o título da vulnerabilidade e a CVE associada.
Para obter uma lista de ecossistemas e versões de componentes suportados, consulte Ecossistemas de pacotes suportados.
Sobre alertas de verificação de dependência
A guia Segurança Avançada em Repositórios no Azure DevOps é o hub para exibir seus alertas de segurança, que, por padrão, mostra alertas de verificação de dependência. Você pode filtrar por ramificação, pipeline, pacote e gravidade. Você pode selecionar um alerta para obter mais detalhes, incluindo orientação de correção. No momento, o hub de alertas não exibe alertas para verificação concluída em filiais de RP.
Quando um pacote vulnerável é detetado em seu repositório, a correção de alertas de verificação de dependência geralmente envolve a atualização para uma versão superior do pacote ou a remoção de um pacote ofensivo. Este conselho é válido tanto para dependências diretas como transitivas (ou indiretas). A visualização padrão na guia Segurança Avançada é alertas ativos para a ramificação padrão do repositório.
Não há efeito nos resultados se pipelines ou ramificações forem renomeados - pode levar até 24 horas até que o novo nome seja exibido.
O estado de um alerta é atualizado automaticamente para Closed
quando o componente vulnerável não é mais detetado na compilação mais recente para todos os pipelines onde a tarefa de verificação de dependência está instalada. Para visualizar os alertas resolvidos, utilize o State
filtro na barra de ferramentas principal e selecione Closed
.
Se você desativar a Segurança Avançada para seu repositório, perderá o acesso aos resultados na guia Segurança Avançada e na tarefa de compilação. A tarefa de compilação não falhará, mas todos os resultados das compilações executadas com a tarefa enquanto a Segurança Avançada está desativada ficam ocultos e não são mantidos.
Detalhes do alerta
Você também pode detalhar detalhes sobre um alerta clicando em um alerta específico e em orientações de correção.
Section | Explicação |
---|---|
Recomendação | O texto da recomendação vem diretamente do nosso provedor de dados de vulnerabilidade, o GitHub Advisory Database. Normalmente, as orientações sugerem a atualização do componente identificado para uma versão não vulnerável. |
Location | A seção Locais detalha o(s) caminho(s) onde a tarefa de verificação de dependência descobriu o componente vulnerável em uso. Se o arquivo puder ser resolvido a partir da verificação de compilação subjacente para um arquivo confirmado na origem, o cartão Locais aparecerá como um link clicável. Se um arquivo foi produzido como parte de uma compilação (por exemplo, um artefato de compilação), o link não é clicável. Revise os logs de compilação para entender melhor como o componente foi trazido para a compilação. |
Description | A descrição é fornecida pela descrição do Comunicado do GitHub. |
Deteções
Os pipelines listados na guia Deteções são os pipelines onde o componente vulnerável foi encontrado. Cada linha detalha a compilação mais recente do pipeline afetado e a data em que o pacote foi introduzido pela primeira vez. Se o pacote vulnerável tiver sido corrigido em alguns pipelines, mas não em todos, você verá linhas parcialmente corrigidas.
Depois que um alerta for resolvido, ele será automaticamente movido para o Closed
estado e o pipeline de execução mais recente na guia Deteções exibirá uma marca de seleção verde, o que significa que o código que contém o componente atualizado foi executado nesse pipeline:
Gravidade
O GitHub Advisory Database fornece uma pontuação CVSS, que é então traduzida em uma gravidade baixa, média, alta ou crítica para um alerta por meio das seguintes diretrizes:
Pontuação CVSS | Gravidade |
---|---|
1.0 < Pontuação < 4.0 | Baixo |
4.0 < Pontuação < 7.0 | Médio |
7.0 < Pontuação < 9.0 | Alto |
Pontuação >= 9,0 | Crítico |
Encontrar detalhes
Duas seções são comumente encontradas em Localizando detalhes: pacote vulnerável e dependência raiz. O pacote vulnerável é o componente potencialmente vulnerável. A seção de dependência raiz contém componentes de nível superior que são responsáveis pela cadeia de dependência que leva a uma vulnerabilidade.
Se o pacote vulnerável for referenciado apenas como uma dependência direta, você verá apenas a seção "pacote vulnerável".
Se o pacote vulnerável for referenciado como uma dependência direta e transitiva, o pacote será mostrado na seção "pacote vulnerável" e "dependência raiz".
Se o pacote vulnerável for referenciado apenas como uma dependência transitiva, o pacote será mostrado na seção "pacote vulnerável" e as dependências raiz que fazem referência ao pacote vulnerável serão mostradas na seção "dependência raiz".
Gerenciar alertas de varredura de dependência
Visualizando alertas para um repositório
Qualquer pessoa com permissões de colaborador para um repositório pode visualizar um resumo de todos os alertas para um repositório no Repos>Advanced Security.
Por padrão, a página de alertas mostra os resultados da verificação de dependência para a ramificação padrão do repositório.
O status de um alerta reflete o estado da ramificação padrão e do pipeline de execução mais recente, mesmo que o alerta exista em outras ramificações e pipelines.
Corrigindo alertas de varredura de dependência
Uma dependência direta é um componente que você tem em seu repositório. Uma dependência transitiva ou indireta é um componente que é usado por uma dependência direta. Seu projeto ainda está vulnerável, independentemente de a vulnerabilidade ser encontrada em uma dependência direta ou transitiva.
A fixação de uma dependência transitiva vulnerável geralmente assume a forma de substituir explicitamente a versão do componente vulnerável usada para cada dependência direta identificada. Depois que as dependências raiz tiverem atualizado seu uso do componente vulnerável para uma versão segura, você poderá atualizar cada dependência raiz em vez de várias substituições individuais.
Atualizando dependências para Yarn/Npm
Hipoteticamente, digamos que este pacote tem duas vulnerabilidades. Um é para axios
, uma dependência direta, e um é para acorn
, uma dependência transitiva (também conhecida como dependência indireta ou dependência de dependência).
{
"name": "my-package",
"version": "1.0.0",
"dependencies": {
"axios": "0.18.0",
"eslint": "5.16.0",
}
}
A versão atual do axios
tem uma vulnerabilidade de negação de serviço (DoS) com uma recomendação de atualização para v0.18.1 ou superior. Por ser uma dependência direta, você tem controle sobre a versão axios
que usa, tudo o que você precisa fazer é atualizar a versão que axios
você puxa. O atualizado package.json
é semelhante a:
{
"name": "my-package",
"version": "1.0.0",
"dependencies": {
"axios": "0.19.2",
"eslint": "5.16.0",
}
}
Agora, a versão do eslint
mostrado package.json
depende de uma versão que é uma vulnerabilidade de acorn
negação de serviço de expressão regular (ReDoS) com uma recomendação para atualizar para a versão 5.7.4, 6.4.1, 7.1.1
ou superior. Se você receber um alerta da ferramenta de verificação de dependência, ele deverá informar a dependência raiz que requer a dependência vulnerável.
Fios
Se você estiver usando o Yarn, poderá usar o yarn why para encontrar a cadeia de dependência completa.
> $ yarn why acorn
yarn why v1.22.4
[1/4] Why do we have the module "acorn"...?
[2/4] Initialising dependency graph...
[3/4] Finding dependency...
[4/4] Calculating file sizes...
=> Found "acorn@6.4.0"
info Reasons this module exists
- "eslint#espree" depends on it
- Hoisted from "eslint#espree#acorn"
info Disk size without dependencies: "1.09MB"
info Disk size with unique dependencies: "1.09MB"
info Disk size with transitive dependencies: "1.09MB"
info Number of shared dependencies: 0
Done in 0.30s.
A cadeia de dependência completa é eslint
acorn
>espree
>. Depois de conhecer a cadeia de dependência, você pode usar outro recurso do Yarn, resoluções de dependência seletiva, para substituir a versão da bolota que é usada.
Use o campo de resoluções para package.json
definir uma substituição de versão. Três métodos diferentes para substituir um pacote são mostrados, em ordem do pior para o melhor:
{
"name": "yarn-resolutions",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"axios": "0.19.2",
"eslint": "5.16.0"
},
"resolutions": {
// DO NOT USE!
"**/acorn": "6.4.1",
// BETTER
"eslint/**/acorn": "6.4.1",
// BEST
"eslint/espree/acorn": "6.4.1"
}
}
O uso do**/acorn
padrão substitui todos os usos do pacote de bolota em todas as dependências. É perigoso e quebra em tempo de execução. Como resultado, foi removido no Yarn v2.
O uso do eslint/**/acorn
padrão substitui todos os usos do pacote de bolota sob o pacote eslint e, em qualquer pacote, ele depende. É mais seguro do que substituir o pacote para todas as dependências, mas ainda tem alguns riscos se o gráfico de dependência de um pacote for grande. Esse padrão é recomendado quando há muitos subpacotes que usam um pacote vulnerável e definir substituições para subpacotes individuais seria impraticável.
O uso do padrão eslint/espree/acorn
substitui apenas o uso de acorn
no espree
pacote no eslint
pacote. Ele visa especificamente a cadeia de dependência vulnerável e é a maneira recomendada de substituir versões de pacote.
npm
Se você estiver usando o npm 8.3 ou superior, poderá usar o campo de substituições no package.json
Adicione uma substituição se precisar fazer alterações específicas nas dependências transitivas. Por exemplo, talvez seja necessário adicionar uma substituição para substituir a versão de uma dependência por um problema de segurança conhecido, substituir uma dependência existente por uma bifurcação ou garantir que a mesma versão de um pacote seja usada em todos os lugares.
{
"name": "npm-overrides",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"axios": "0.19.2",
"eslint": "5.16.0"
},
"overrides":{
"eslint": {
"espree": {
"acorn": "6.4.1"
}
}
}
}
O exemplo de substituição mostrado demonstra a maneira do npm dizer "substituir apenas o uso de acorn
no espree
pacote no eslint
pacote". Ele visa especificamente a cadeia de dependência vulnerável e é a maneira recomendada de substituir versões de pacote. As substituições são uma característica nativa do npm. Ele fornece uma maneira de substituir um pacote em sua árvore de dependência por outra versão ou outro pacote inteiramente.
Depois de definir suas substituições, você deve excluir o package-lock.json
e node_modules
e executar npm install
novamente.
Você não pode definir uma substituição para um pacote do qual depende diretamente, a menos que a dependência e a substituição em si compartilhem exatamente a mesma especificação. Por exemplo, digamos que axios: "0.18.0"
é vulnerável e estamos procurando atualizar para axios: "0.19.2"
. Altere diretamente a versão de dependência em vez de usar a substituição.
{
"name": "npm-overrides",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"axios": "0.18.0"
},
"overrides": {
// BAD, will throw an EOVERRIDE error
// "axios": "0.19.2",
}
}
Atualize a versão da dependência sem definir uma substituição:
{
"name": "npm-overrides",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"axios": "0.19.2"
}
}
Atualizando dependências para o Maven
O mecanismo de resolução de dependência não é tão sofisticado quanto o usado no Yarn. Como resultado, você só pode ter uma única versão de uma dependência em um projeto. Para resolver esse problema, o Maven usa um algoritmo de "vitórias mais próximas". Ou seja, ele usa a versão da dependência mais próxima do seu projeto na árvore de dependências.
Por exemplo, você tem o seguinte gráfico de dependência:
your-project --- A:1.0.0 --- B:2.0.0
\
\__ B:1.0.0
your-project
depende do A:1.0.0
, que por sua vez depende, B:2.0.0
mas o seu projeto também tem uma dependência direta do B:1.0.0
. Assim, você tem duas versões diferentes da dependência B em seu gráfico de dependência, mas a versão 1.0.0 da dependência B vence por estar 'mais próxima' do seu projeto.
Em alguns casos, esse cenário pode funcionar se as versões forem compatíveis. No entanto, se A:1.0.0
depender de algum recurso do B que só está disponível na versão 2.0.0
, então esse comportamento não funciona. Na pior das hipóteses, este projeto ainda pode ser compilado, mas falha em tempo de execução.
Vamos dar uma olhada em um exemplo do mundo real.
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.customer360</groupId>
<artifactId>maven-dependencies</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>maven-dependencies</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.10.3</version>
</dependency>
</project>
Digamos que a versão da com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
qual você depende depende de uma versão que com.fasterxml.jackson.core:jackson-databind
tenha uma desserialização da vulnerabilidade de dados não confiáveis.
Você pode verificar essa dependência usando o plug-in de dependência Maven. Neste caso, você executaria mvn dependency:tree -Dincludes=com.fasterxml.jackson.core:jackson-databind
e obteria a seguinte saída:
> $ mvn dependency:tree -Dincludes=com.fasterxml.jackson.core:jackson-databind
[INFO] Scanning for projects...
[INFO]
[INFO] ------------< com.microsoft.customer360:maven-dependencies >------------
[INFO] Building maven-dependencies 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ maven-dependencies ---
[INFO] com.microsoft.customer360:maven-dependencies:jar:1.0-SNAPSHOT
[INFO] \- com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:jar:2.10.3:compile
[INFO] \- com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:jar:2.10.3:compile
[INFO] \- com.fasterxml.jackson.core:jackson-databind:jar:2.10.3:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.928 s
[INFO] Finished at: 2020-04-27T14:30:55+02:00
[INFO] ------------------------------------------------------------------------
Primeiro, verifique se há uma nova versão que com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
não dependa de uma versão vulnerável do com.fasterxml.jackson.core:jackson-databind
. Se sim, você pode atualizar com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
e parar por aí. Caso contrário, substitua a versão do com.fasterxml.jackson.core:jackson-databind
.
Como mostrado no trecho de código, ao usar o Maven o "mais próximo vence", então a resolução é adicionar uma dependência direta para com.fasterxml.jackson.core:jackson-databind
que corrija a vulnerabilidade.
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.customer360</groupId>
<artifactId>maven-dependencies</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>maven-dependencies</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.10.3</version>
</dependency>
<!-- Dependency resolutions -->
<!-- jackson-jaxrs-json-provider -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.10.4</version>
</dependency>
</dependencies>
</project>
Você pode verificar se a resolução funciona executando mvn dependency:tree -Dincludes=com.fasterxml.jackson.core:jackson-databind
novamente.
$ mvn dependency:tree -Dincludes=com.fasterxml.jackson.core:jackson-databind
[INFO] Scanning for projects...
[INFO]
[INFO] ------------< com.microsoft.customer360:maven-dependencies >------------
[INFO] Building maven-dependencies 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ maven-dependencies ---
[INFO] com.microsoft.customer360:maven-dependencies:jar:1.0-SNAPSHOT
[INFO] \- com.fasterxml.jackson.core:jackson-databind:jar:2.9.10.4:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.827 s
[INFO] Finished at: 2020-04-27T14:32:42+02:00
[INFO] ------------------------------------------------------------------------
É recomendável adicionar um comentário perto da resolução de dependência, para que qualquer pessoa que venha mais tarde saiba por que a dependência está lá. Ele pode ser removido uma vez que a dependência raiz usa a nova versão; caso contrário, você acumulará dependências.
Em um projeto real, adicione a dependência o mais alto possível na cadeia. Por exemplo, você pode adicionar a resolução no arquivo POM pai, em vez de individualmente em cada arquivo POM do projeto.
Atualizando dependências para o NuGet
O algoritmo de resolução de dependência usado no NuGet é semelhante ao Maven, em que apenas uma única versão de uma dependência pode ser usada. No entanto, o NuGet não fixa versões de dependência.
Por exemplo, se você tiver uma dependência <PackageReference Include="A" Version="1.2.3" />
, você pode esperar que este pacote seja equivalente a = 1.2.3
, mas na verdade significa >= 1.2.3
. Para fixar uma versão exata, você deve usar Version="[1.2.3]"
o . Para obter mais informações, consulte a documentação dos intervalos de versões do NuGet.
Além do comportamento de intervalo padrão, o NuGet restaura a versão mais baixa aplicável para satisfazer um intervalo. Esse comportamento significa que, em muitos casos, você precisa definir um intervalo.
Vamos dar uma olhada neste projeto de exemplo, que tem uma dependência de Microsoft.AspNetCore.App
:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>NuGet.Dependencies</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.14" />
</ItemGroup>
</Project>
Depende de uma versão que seja vulnerável a uma vulnerabilidade de execução remota de Microsoft.AspNetCore.Http.Connections
código (RCE).
Primeiro, você deve verificar se há uma versão atualizada que depende de Microsoft.AspNetCore.App
uma versão mais recente do Microsoft.AspNetCore.Http.Connections
. Se sim, você pode atualizar Microsoft.AspNetCore.App
e parar aqui. Se não, você tem que substituir a versão dele Microsoft.AspNetCore.Http.Connections
depende.
O NuGet não tem um equivalente a yarn why ou mvn dependency:tree built-in, portanto, a maneira mais fácil de ver a árvore de dependência é frequentemente visitá nuget.org. Se você visitar a página do NuGet para Microsoft.AspNetCore.App
, verá que depende do Microsoft.AspNetCore.Http.Connections
version >= 1.0.4 && < 1.1.0
. Ou, em um intervalo de versões do NuGet, a sintaxe representativa é [1.0.4,1.1.0)
.
A vulnerabilidade RCE em Microsoft.AspNetCore.Http.Connections
foi corrigida na versão 1.0.15
, então você precisa substituir o intervalo de versões a ser[1.0.15, 1.1.0)
.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>NuGet.Dependencies</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.8" />
</ItemGroup>
<ItemGroup Label="Dependency Resolutions">
<!-- Microsoft.AspNetCore.App -->
<PackageReference Include="Microsoft.AspNetCore.Http.Connections" Version="[1.0.15,1.1.0)" />
</ItemGroup>
</Project>
Recomenda-se adicionar um comentário perto da resolução de dependência para que qualquer pessoa que venha mais tarde saiba por que a dependência está lá. Ele pode ser removido quando a dependência raiz usa a nova versão. Caso contrário, você acumulará dependências.
E se não houver nenhuma correção disponível?
Quando nenhuma correção conhecida estiver disponível, as seguintes opções estarão disponíveis como outros métodos de correção até que um componente atualizado esteja disponível:
- Pare de usar o componente e remova-o do seu código - esta remoção é detetada na sua próxima compilação com a tarefa de verificação de dependência instalada
- Contribua com uma correção para o próprio componente. Se a sua organização tiver diretrizes específicas sobre contribuições de código aberto, siga essas diretrizes.
- Descartando o alerta. No entanto, alertas sem correção conhecida ainda podem representar uma ameaça à segurança da sua organização. Recomendamos que você não descarte um alerta apenas porque não há nenhuma correção conhecida.
Ignorar alertas de verificação de dependência
Para descartar alertas na Segurança Avançada, você precisa das permissões apropriadas. Por padrão, apenas os administradores de projeto recebem a capacidade de descartar alertas de Segurança Avançada.
Para descartar um alerta:
- Aceda ao alerta que pretende fechar e selecione o alerta
- Selecione a lista suspensa Fechar alerta
- Se ainda não estiver selecionado, selecione Risco aceito ou Falso positivo como motivo de fechamento
- Adicionar um comentário opcional à caixa de texto Comentário
- Selecione Fechar para enviar e fechar o alerta
- O estado de alerta muda de Aberto para Fechado e exibe o motivo da demissão
Esta ação apenas descarta o alerta para a ramificação selecionada. Outras ramificações que podem conter a mesma vulnerabilidade permanecem ativas até que sejam tomadas medidas de outra forma. Qualquer alerta que tenha sido descartado anteriormente pode ser reaberto manualmente.
Gerenciando alertas de varredura de dependência em solicitações pull
Se forem criados alertas para novas alterações de código em uma solicitação pull, o alerta será relatado como uma anotação na seção de comentários da guia Visão geral da solicitação pull e como um alerta na guia Advanced Security repository. Há uma nova entrada do seletor de ramificação para a ramificação de solicitação pull.
Você pode ver o manifesto do pacote afetado, ver um resumo da descoberta e resolver a anotação na seção Visão geral.
Para descartar alertas de solicitação pull, você deve navegar até a exibição de detalhes do alerta para fechar o alerta e resolver a anotação. Caso contrário, simplesmente alterar o status do comentário (1) resolve a anotação, mas não fecha nem corrige o alerta subjacente.
Para ver todo o conjunto de resultados para sua ramificação de solicitação pull, navegue até Repos>Advanced Security e selecione sua ramificação pull request. Selecionar Mostrar mais detalhes (2) na anotação direciona você para a exibição de detalhes do alerta na guia Segurança Avançada.
Gorjeta
As anotações só serão criadas quando as linhas de código afetadas forem totalmente exclusivas para a diferença da solicitação pull em comparação com a ramificação de destino da solicitação pull.