A Common Expression Language (CEL) é uma linguagem de expressão de uso geral projetada para ser rápida, portátil e segura para execução. É possível usar a CEL sozinha ou incorporá-la a um produto maior. A CEL é adequada para uma ampla variedade de aplicativos, desde o roteamento de chamadas de procedimento remoto (RPCs) até a definição de políticas de segurança. A CEL é extensível, independente de plataforma, formalmente verificável e otimizada para fluxos de trabalho de compilação única/avaliação múltipla.
A CEL foi projetada especificamente para ser segura para executar o código do usuário. Embora seja perigoso chamar eval() cegamente no código Python de um usuário, é possível executar o código CEL de um usuário com segurança. Como a CEL impede comportamentos que a tornariam menos eficiente, ela é avaliada com segurança em nanossegundos ou microssegundos. A velocidade e a segurança da CEL a tornam ideal para aplicativos essenciais para a performance.
A CEL avalia expressões semelhantes a funções de linha única ou expressões lambda. Embora a CEL seja usada com frequência para decisões booleanas, também é possível usá-la para construir objetos mais complexos, como mensagens JSON ou de buffer de protocolo.
Por que usar a CEL?
Muitos serviços e aplicativos avaliam configurações declarativas. Por exemplo, o controle de acesso baseado em papéis (RBAC) é uma configuração declarativa que produz uma decisão de acesso com base em um papel de usuário e um conjunto de usuários. Embora as configurações declarativas sejam suficientes para a maioria dos casos, às vezes é necessário mais poder expressivo. É aí que a CEL entra em cena.
Como exemplo de extensão de uma configuração declarativa com a CEL, considere os recursos do Google Cloud Identity and Access Management (IAM). Embora o RBAC seja o caso comum, o IAM oferece expressões CEL para permitir que os usuários restrinjam ainda mais o escopo da concessão baseada em papéis de acordo com as propriedades da mensagem proto da solicitação ou dos recursos acessados. Descrever essas condições pelo modelo de dados resultaria em uma superfície de API complicada e difícil de trabalhar. Em vez disso, usar a CEL com o controle de acesso baseado em atributos (ABAC) é uma extensão expressiva e poderosa do RBAC.
Conceitos básicos da CEL
Na CEL, uma expressão é compilada em relação a um ambiente. A etapa de compilação produz uma árvore de sintaxe abstrata (AST) no formato de buffer de protocolo. As expressões compiladas são armazenadas para uso futuro para manter a avaliação o mais rápida possível. Uma única expressão compilada pode ser avaliada com muitas entradas diferentes.
Confira mais detalhes sobre alguns desses conceitos.
Expressões
As expressões são escritas pelos usuários. Elas são semelhantes a corpos de função de linha única ou expressões lambda. A assinatura da função que declara a entrada é escrita fora da expressão CEL, e a biblioteca de funções disponíveis para a CEL é importada automaticamente.
Por exemplo, a expressão CEL a seguir recebe um objeto de solicitação, e a solicitação inclui um token claims. A expressão retorna um valor booleano que indica se o token claims ainda é válido.
Exemplo de expressão CEL para autenticar um token de declarações
// Check whether a JSON Web Token has expired by inspecting the 'exp' claim.
//
// Args:
// claims - authentication claims.
// now - timestamp indicating the current system time.
// Returns: true if the token has expired.
//
timestamp(claims["exp"]) < now
Embora os usuários definam a expressão CEL, os serviços e aplicativos definem o ambiente em que ela é executada.
Ambientes
Os ambientes são definidos por serviços. Os serviços e aplicativos que incorporam a CEL declaram o ambiente de expressão. O ambiente é a coleção de variáveis e funções que podem ser usadas em expressões CEL.
Por exemplo, o código textproto a seguir declara um ambiente que contém as variáveis request e now usando a mensagem CompileRequest de um serviço CEL.
Exemplo de declaração de ambiente CEL
# Format: $SOURCE_PATH/service.proto#CompileRequest
declarations {
name: "request"
ident {
type { message_type: "google.rpc.context.AttributeContext.Request" }
}
}
declarations {
name: "now"
ident {
type { well_known: "TIMESTAMP" }
}
}
As declarações baseadas em proto são usadas pelo verificador de tipo CEL para garantir que todas as referências de identificador e função em uma expressão sejam declaradas e usadas corretamente.
Fases de processamento de expressão
As expressões CEL são processadas em três fases:
- Analisar
- Cheque
- Avaliar
O padrão mais comum de uso da CEL é analisar e verificar expressões no momento da configuração, armazenar a AST e, em seguida, recuperar e avaliar a AST repetidamente no momento da execução.
Ilustração das fases de processamento da CEL

A CEL é analisada de uma expressão legível por humanos para uma AST usando uma
ANTLR. A fase de análise emite uma
AST baseada em proto em que cada nó Expr na AST contém um ID inteiro usado para
indexar metadados gerados durante a análise e a verificação. O
syntax.proto arquivo produzido durante a análise representa
a representação abstrata do que foi digitado na forma de string da
expressão.
Depois que uma expressão é analisada, ela é verificada em relação ao ambiente para garantir que todos os identificadores de variáveis e funções na expressão tenham sido declarados e estejam sendo usados corretamente. O verificador de tipo produz um
checked.proto arquivo que inclui metadados de resolução de tipo, variável e função
que podem melhorar drasticamente a eficiência da avaliação.
Por fim, depois que uma expressão é analisada e verificada, a AST armazenada é avaliada.
O avaliador de CEL precisa de três coisas:
- Vinculações de função para extensões personalizadas
- Vinculações de variáveis
- Uma AST para avaliar
As vinculações de função e variável precisam corresponder ao que foi usado para compilar a AST. Qualquer uma dessas entradas pode ser reutilizada em várias avaliações, como uma AST sendo avaliada em muitos conjuntos de vinculações de variáveis, as mesmas variáveis usadas em muitas ASTs ou as vinculações de função usadas durante o ciclo de vida de um processo (um caso comum).
Verificação formal
Além da avaliação de execução, as expressões e políticas da CEL podem ser formalmente verificadas para provar matematicamente a correção delas em todas as entradas possíveis.
Com tecnologia do provador de teoremas Z3, o framework de verificação formal da CEL em CEL-Java traduz expressões e políticas da CEL em fórmulas de satisfiabilidade módulo teorias (SMT, na sigla em inglês) para:
- Provar invariantes de segurança:verifique se as políticas críticas não podem ser ignoradas em nenhuma combinação de entradas usando as especificações
assumeeassert. - Verificar a equivalência lógica:prove matematicamente que as expressões refatoradas ou geradas por IA se comportam de maneira idêntica à regra original.
- Aplicar validade exaustiva:garanta que as barreiras de proteção (como as políticas de admissão de validação do Kubernetes) sejam válidas em todas as entradas ou gere contraexemplos concretos quando violadas.
- Eliminar falsos positivos:use o rastreamento de contaminação de três passagens para isolar funções personalizadas não mapeadas, garantindo que as violações informadas sejam sempre bugs reproduzíveis.
Para uma introdução e exemplos reais, consulte a postagem do blog do Google Open Source: Securing the agentic era: Introducing formal verification for CEL (em inglês).