#!/intro

A segurança em ambientes DevSecOps continua demasiado dependente de confiança implícita. Confia-se que uma dependência é legítima porque tem histórico. Confia-se que um gestor de pacotes instala apenas o que é esperado. Confia-se que um agente de execução de CI/CD executa o build de forma limpa. Confia-se que um artefacto publicado corresponde ao código revisto. Confia-se que os segredos disponíveis durante o fluxo de CI/CD não serão expostos por código de terceiros.

Durante algum tempo, esta confiança funcionou porque era operacionalmente conveniente. O problema é que o software moderno deixou de ser apenas código escrito por uma equipa e passou a ser uma composição dinâmica de dependências, scripts, ferramentas, contentores, ações, gestores de pacotes, agentes de execução e serviços externos. Cada uma destas peças introduz decisões técnicas, permissões e relações de confiança que podem ser exploradas.

A resposta tradicional baseada em ferramentas de análise, CVE e inventário continua a ser necessária, mas já não chega. Identificar vulnerabilidades conhecidas é apenas uma parte do problema. A parte menos observável da superfície de ataque está nos processos que obtêm, constroem, assinam, empacotam e distribuem o software antes de ele chegar ao tempo de execução.

O próximo passo em ambientes DevSecOps não é acrescentar mais uma ferramenta ao fim do fluxo de CI/CD. É substituir confiança implícita por confiança verificável.

Isto significa que uma organização deve conseguir demonstrar de onde veio uma dependência, como foi construído um artefacto, que identidade executou uma operação, que permissões estavam disponíveis, que segredos foram expostos, que código foi assinado e que garantias existem sobre o processo de entrega. Sem esta capacidade, a cadeia de abastecimento de software continua a depender de pressupostos operacionais difíceis de verificar, auditar e sustentar em caso de incidente.


> vulnerabilidades

Durante anos, a gestão de dependências foi dominada por uma pergunta relativamente simples: esta biblioteca tem vulnerabilidades conhecidas? A resposta vinha de ferramentas de SCA, bases de dados de CVE, ferramentas de análise de contentores e alertas automáticos integrados no repositório ou no fluxo de CI/CD.

Esse modelo tem valor, mas cobre apenas uma parte da superfície de ataque associada à cadeia de abastecimento de software. Uma dependência pode não ter qualquer CVE associada e, ainda assim, representar risco elevado. Pode executar scripts de ciclo de vida durante a instalação, descarregar binários externos em tempo de build, introduzir dependências transitivas inesperadas, recolher variáveis de ambiente ou alterar o comportamento do fluxo de CI/CD sem que a aplicação final revele imediatamente esse abuso.

A questão deixou de estar apenas na vulnerabilidade do código em tempo de execução. Passou também a estar no processo que obtém, instala, constrói, testa, assina e publica esse código.

Esta mudança é crítica porque muitos controlos continuam a olhar para dependências como componentes estáticos. Na prática, uma dependência moderna pode ser uma unidade de execução. Pode trazer scripts, pontos de extensão, executáveis, ferramentas auxiliares, chamadas de rede e relações transitivas com outros ecossistemas. A simples operação de instalar software pode executar código de terceiros num ambiente com acesso a tokens, caches, chaves SSH, ficheiros de configuração e variáveis sensíveis.

Em ecossistemas como npm, GitHub Actions ou AUR, o ponto crítico não está apenas no pacote ou no fluxo de trabalho declarado, mas na capacidade de executar código durante instalação, build ou publicação. O risco não termina no conteúdo visível da dependência principal; estende-se ao contexto em que essa dependência é processada.

É por isso que a maturidade em DevSecOps tem de passar do inventário para a verificabilidade. Saber que componentes existem é importante. Conseguir provar como entraram, quem os autorizou, onde foram construídos e que propriedades de segurança foram aplicadas é muito mais relevante.


> confiança

A confiança implícita acumula-se ao longo do tempo. Um pacote usado durante anos deixa de ser questionado. Uma ação popular passa a ser copiada entre repositórios. Uma imagem base torna-se padrão interno. Uma ferramenta auxiliar de instalação entra no fluxo normal de desenvolvimento. Com o tempo, estes elementos deixam de ser avaliados como decisões de risco e passam a fazer parte da operação diária.

A perceção de confiança pode permanecer mesmo depois de o controlo operacional ter mudado.

Um projeto pode ficar sem manutenção ativa. Um responsável pela manutenção pode ser substituído. Uma conta pode ser comprometida. Um nome de pacote pode mudar de titularidade. Uma dependência transitiva pode passar a incluir scripts de instalação. Uma imagem pode ser reconstruída com base diferente. Uma ação pode alterar o comportamento entre versões. O nome continua familiar, mas a cadeia de responsabilidade já não é a mesma.

Esta é uma das fragilidades mais difíceis de gerir. A reputação histórica não garante confiança presente. A popularidade não garante integridade. A ausência de incidentes conhecidos não prova que o processo de publicação seja robusto.

A confiança implícita torna-se superfície de ataque quando deixa de haver escrutínio suficiente sobre alterações com impacto operacional. Uma mudança de responsável pela manutenção, a introdução de um script de instalação, a passagem para outro repositório de pacotes, o uso de binários pré-compilados ou a alteração do processo de publicação não devem ser tratados como detalhes neutros. São sinais que podem alterar o risco de forma significativa.

Em ambientes DevSecOps, esta avaliação deve ser automatizada sempre que possível, mas não pode ser reduzida a uma lista de verificação. O ponto não é bloquear qualquer mudança. O ponto é distinguir alterações normais de alterações que mudam a cadeia de confiança.


> build

O build deve ser tratado como uma fronteira de segurança, porque é o ponto onde se juntam código, dependências, ferramentas, credenciais, artefactos, permissões de publicação e, muitas vezes, chaves de assinatura. Um compromisso nesta fase pode contaminar o resultado antes de qualquer controlo de tempo de execução entrar em ação.

Este detalhe é frequentemente subestimado. Produção recebe atenção, segmentação, monitorização e processos de alteração. Já o build é muitas vezes visto como infraestrutura auxiliar, apesar de concentrar segredos e permissões com impacto direto na cadeia de entrega. Um agente de execução com acesso a tokens de publicação, repositórios de pacotes privados, repositórios internos ou credenciais de nuvem não é descartável apenas porque é recriado com frequência. É descartável apenas se for verdadeiramente efémero, isolado e limitado.

A reutilização de agentes de execução, a persistência de caches, o acesso irrestrito à Internet e a exposição de segredos em variáveis de ambiente criam condições favoráveis para abuso. Um pacote malicioso executado durante a instalação não precisa de explorar uma vulnerabilidade complexa se conseguir simplesmente ler o ambiente, obter tokens e comunicar para fora.

A autenticação baseada em OIDC reduz uma parte importante deste risco, porque permite trocar a identidade do fluxo de CI/CD por credenciais temporárias e com âmbito limitado. Isto é preferível a guardar tokens permanentes em variáveis estáticas, especialmente quando esses tokens permitem publicar artefactos, alterar infraestrutura ou aceder a serviços externos.

Mas OIDC não resolve tudo. A identidade federada só é segura se as políticas forem restritivas, se os atributos forem validados, se os ambientes forem separados e se cada fluxo de CI/CD receber apenas as permissões necessárias. Caso contrário, substitui-se um segredo permanente por uma identidade demasiado poderosa.

O build deve estar previsto no desenho técnico do sistema, nos requisitos de segurança, no modelo de exploração e nos procedimentos de aceitação. Não basta saber que o software funciona; é necessário ter evidência sobre como foi produzido, com que dependências, em que ambiente, com que controlos e com que segregação de funções.

A fronteira de segurança não é a ferramenta. É o desenho do processo.


> proveniência

A proveniência é uma das peças centrais da confiança verificável. Uma organização deve conseguir responder, para cada artefacto relevante, a perguntas concretas: que commit originou este resultado, que fluxo de CI/CD o construiu, que agente de execução executou o build, que dependências foram usadas, que políticas estavam ativas, que segredos estiveram disponíveis e que entidade assinou o resultado.

Sem estas respostas, a avaliação da cadeia de entrega fica dependente de pressupostos não verificados.

Assinaturas, atestados, SBOM e modelos como SLSA só têm valor quando reforçam propriedades reais do processo. Um artefacto assinado é útil se a chave estiver protegida, se o processo que assina for confiável e se existir validação posterior da assinatura. Um SBOM é útil se for analisado, comparado e usado para tomada de decisão. Um atestado é útil se permitir verificar que o build ocorreu num ambiente esperado, com entradas controladas e identidade conhecida.

O erro comum é transformar estes controlos em simbologia de maturidade. Gera-se um SBOM porque é exigido. Assina-se um artefacto porque a ferramenta permite. Publica-se um atestado porque fica bem no fluxo de CI/CD. Mas se ninguém valida estas propriedades antes da promoção para produção, a confiança continua a ser essencialmente implícita.

A confiança verificável exige que estes elementos tenham consequência operacional. Um artefacto sem assinatura válida não deve avançar. Um build sem proveniência aceitável deve ser rejeitado. Uma dependência fora da política deve exigir aprovação. Um fluxo de CI/CD que tenta aceder a destinos inesperados deve gerar alerta.

A proveniência deve integrar o dossiê técnico do sistema de informação, a par da arquitetura, integrações, perfis de acesso, procedimentos de exploração e evidências de aceitação. A conformidade documental não substitui evidência técnica verificável.

A diferença entre documentação e controlo está precisamente aí.


> segredos

A gestão de segredos é uma das áreas onde a diferença entre confiança implícita e confiança verificável se torna mais evidente. Muitas organizações continuam a depender de tokens permanentes, chaves SSH de longa duração, credenciais de nuvem guardadas em variáveis de ambiente e permissões demasiado amplas atribuídas a agentes de execução ou postos de trabalho.

Isto cria um ponto de colapso. Se código não confiável executar durante instalação ou build, pode obter material suficiente para transformar um compromisso limitado num incidente de maior alcance. O problema não é apenas a exposição de um token. É aquilo que esse token permite fazer.

Um token de gestor de pacotes pode permitir publicar versões maliciosas. Uma chave SSH pode dar acesso a repositórios privados. Uma credencial de nuvem pode permitir criação de recursos, leitura de dados ou alteração de infraestrutura. Um token de CI/CD pode permitir modificar fluxos de trabalho, obter outros segredos ou interferir em publicações.

A resposta deve ser desenhada em torno de redução de impacto. Segredos devem ter âmbito mínimo, duração curta, rotação regular e separação por função. Sempre que possível, credenciais estáticas devem ser substituídas por emissão temporária baseada em identidade, com políticas restritivas e validação explícita do contexto de execução.

Também é necessário reduzir a exposição local. Postos de trabalho de desenvolvimento acumulam frequentemente chaves SSH, ficheiros .env, sessões autenticadas, contextos Kubernetes, credenciais Docker ou Podman, tokens GitHub e configurações de nuvem. Isto transforma o posto de trabalho num ponto relevante da cadeia de abastecimento de software, não apenas num equipamento terminal de produtividade.

A gestão de segredos deve ser tratada como gestão de acessos privilegiados. Credenciais usadas para publicação, assinatura, administração de infraestrutura, acesso a repositórios ou promoção de artefactos não devem depender de conveniência individual, armazenamento local ou práticas informais.

Um posto de trabalho comprometido não deve conseguir publicar artefactos, alterar fluxos de CI/CD ou aceder a produção apenas porque concentra conveniência operacional.


> mitigação

A resposta ao risco crescente na cadeia de abastecimento de software deve partir de um princípio simples: substituir confiança implícita por confiança verificável. Isto significa que a organização não deve apenas confiar que uma dependência, um build, um agente de execução ou um artefacto são legítimos; deve conseguir demonstrar, auditar e reconstruir essa confiança com base em propriedades técnicas observáveis.

A primeira medida é definir uma política técnica para consumo de dependências. Essa política deve distinguir dependências diretas, transitivas, de desenvolvimento, de tempo de execução, de build e de publicação. Deve também estabelecer critérios para pacotes novos, pacotes com titularidade recente, projetos abandonados, alterações de responsável pela manutenção, introdução de scripts, descarregamentos externos e uso de binários pré-compilados. O objetivo não é bloquear por defeito, mas classificar o risco de forma consistente.

A segunda medida é reduzir execução automática. Scripts de ciclo de vida, pontos de extensão de instalação e comandos de build obtidos de terceiros devem ser tratados como execução de código não confiável. Sempre que o ecossistema o permita, os scripts devem ser bloqueados por defeito ou sujeitos a lista de autorização. Quando forem necessários, devem ser documentados, revistos e executados em ambientes isolados, com rede e privilégios compatíveis com o risco.

A terceira medida é isolar builds e agentes de execução. O build deve correr em ambientes efémeros, com privilégios mínimos, sem estado persistente desnecessário, sem reutilização perigosa de caches e sem acesso irrestrito à Internet. Os agentes de execução devem receber segredos apenas quando necessário, com âmbito mínimo e duração curta. A autenticação baseada em OIDC para emissão temporária de credenciais é preferível a tokens permanentes guardados como variáveis estáticas, porque reduz a exposição de segredos persistentes na infraestrutura de CI/CD.

A quarta medida é controlar o tráfego de saída. Um build que comunica livremente com a Internet dá ao atacante duas capacidades imediatas: descarregar cargas maliciosas e exfiltrar dados. Proxies internos, espelhos controlados, listas de autorização de repositórios de pacotes e registo de tráfego de saída reduzem essa margem de manobra e tornam o comportamento anómalo mais visível.

A quinta medida é validar proveniência antes da promoção de artefactos. Não basta gerar atestados ou assinar resultados; é necessário verificar essas propriedades antes de permitir que uma imagem, binário, pacote ou publicação avance no ciclo de entrega. A validação deve ser automática, consistente e integrada no fluxo de CI/CD.

A sexta medida é proteger segredos como parte da própria cadeia de abastecimento de software. Tokens de publicação, chaves SSH, credenciais de nuvem, tokens de gestores de pacotes e chaves de assinatura devem ser segmentados, temporários, monitorizados e revogados quando deixam de ser necessários. Qualquer segredo acessível a um build deve ser considerado potencialmente exposto se esse build executar código não confiável.

A sétima medida é observar sinais de manutenção e titularidade. Projetos sem atividade, pacotes órfãos, mudanças recentes de responsável pela manutenção, alterações súbitas no processo de build, novos gestores de pacotes e comportamento inesperado durante instalação devem gerar revisão. A manutenção não é apenas um indicador de qualidade; é também um indicador de risco.

A oitava medida é preparar resposta a compromisso. Quando existe suspeita de execução maliciosa durante instalação ou build, remover a dependência raramente chega. A resposta deve incluir rotação de segredos, revogação de sessões, análise de artefactos publicados, revisão de fluxos de trabalho, verificação de commits recentes, validação de registos externos e reconstrução de ambientes quando a confiança no sistema deixou de ser defensável.

Estas medidas não eliminam o risco. Reduzem a probabilidade de compromisso, limitam o impacto e tornam a resposta tecnicamente viável.


> operação

A dificuldade não está em reconhecer que estas medidas são necessárias. Está em aplicá-las sem transformar o processo de desenvolvimento numa sequência de bloqueios burocráticos.

DevSecOps só funciona quando a segurança é integrada na plataforma de entrega e não imposta como verificação tardia. Modelos de CI com políticas seguras por defeito, agentes de execução efémeros, repositórios internos, gestão centralizada de segredos, assinatura integrada, validação automática de proveniência, controlo de tráfego de saída e exceções rastreáveis permitem elevar o nível de segurança sem depender exclusivamente de atenção humana permanente.

A atenção humana deve ser reservada para decisões de risco relevantes, não para rever mecanicamente cada detalhe de cada dependência. O sistema deve conseguir distinguir alterações normais de eventos que merecem escrutínio: mudança de titularidade, introdução de scripts, alteração de repositório de pacotes, novo binário pré-compilado, dependência transitiva inesperada ou tentativa de comunicação externa fora do padrão.

A segurança da cadeia de abastecimento de software não pode ficar isolada numa validação tardia nem ser tratada apenas na fase de aceitação. Tem de estar presente no desenho, no desenvolvimento, na operação, na monitorização e na resposta a incidentes.

Este é o ponto onde a confiança verificável se torna prática. Não se trata de tornar o desenvolvimento mais lento. Trata-se de criar evidência técnica suficiente para que a organização saiba o que está a executar, de onde veio, como foi construído e que limites foram aplicados.

Sem isso, o fluxo de CI/CD continua a ser uma caixa negra com telemetria abundante, mas com garantias fracas.


> conclusao

A evolução dos ambientes DevSecOps tornou a cadeia de abastecimento de software uma das principais superfícies de ataque. O problema já não está apenas na aplicação, no tempo de execução ou nas vulnerabilidades conhecidas. Está também no caminho que transforma dependências, commits, scripts, agentes de execução e artefactos em software executado.

A confiança implícita foi suficiente enquanto os processos eram mais simples, menos automatizados e menos interligados. Hoje, essa confiança tornou-se demasiado barata para o atacante explorar e demasiado frágil para a organização depender dela.

O próximo passo é construir confiança verificável.

Isso exige proveniência, isolamento, identidade forte, credenciais temporárias, controlo de tráfego de saída, validação de artefactos, observação de alterações de titularidade e resposta preparada para compromisso. Mais importante ainda, exige que estes controlos sejam parte natural da plataforma de entrega, e não uma camada decorativa adicionada no fim.

Uma organização que não consegue demonstrar como o seu software foi construído, por quem, com que dependências, com que permissões e com que garantias, não controla verdadeiramente o software que executa.

> status: unverified
> exit 0