Uma função f()
usa eval()
(ou algo tão perigoso) com os dados que eu criei e armazenei na local_file
máquina executando meu programa:
import local_file
def f(str_to_eval):
# code....
# ....
eval(str_to_eval)
# ....
# ....
return None
a = f(local_file.some_str)
f()
é seguro de executar, pois as cordas que forneço são minhas.
No entanto, se eu decidir usá-lo para algo inseguro (por exemplo, entrada do usuário), as coisas podem dar muito errado . Além disso, se o local_file
local deixar de ser local, isso criaria uma vulnerabilidade, pois eu precisaria confiar na máquina que fornece esse arquivo também.
Como devo garantir que nunca "esqueço" que esta função não é segura (a menos que critérios específicos sejam atendidos)?
Nota: eval()
é perigoso e geralmente pode ser substituído por algo seguro.
python
vulnerabilities
Paradoxo de Fermi
fonte
fonte
Respostas:
Defina um tipo para decorar entradas "seguras". Na sua função
f()
, afirme que o argumento tem esse tipo ou gere um erro. Seja esperto o suficiente para nunca definir um atalhodef g(x): return f(SafeInput(x))
.Exemplo:
Embora isso possa ser facilmente contornado, torna mais difícil fazê-lo por acidente. As pessoas podem criticar esse tipo de verificação draconiana, mas não entenderiam o ponto. Como o
SafeInput
tipo é apenas um tipo de dados e não uma classe orientada a objetos que pode ser subclassificada, verificar a identidade do tipo comtype(x) is SafeInput
é mais seguro do que verificar a compatibilidade do tipoisinstance(x, SafeInput)
. Como queremos aplicar um tipo específico, ignorar o tipo explícito e apenas fazer a digitação implícita do pato também não é satisfatório aqui. O Python possui um sistema de tipos, então vamos usá-lo para detectar possíveis erros!fonte
assert
é removido automaticamente, pois usarei código python otimizado. Algo comoif ... : raise NotSafeInputError
seria necessário.eval()
para um métodoSafeInput
, para que você não precise de uma verificação explícita de tipo. Dê ao método um nome que não seja usado em nenhuma outra classe. Dessa forma, você ainda pode zombar da coisa toda para fins de teste.eval
tem acesso a variáveis locais, pode ser que o código dependa de como as variáveis são modificadas. Ao mover o eval para outro método, ele não terá mais a capacidade de alterar variáveis locais.SafeInput
construtor pegue um nome / identificador do arquivo local e faça a própria leitura, garantindo que os dados realmente venham de um arquivo local.Como Joel apontou certa vez, faça com que o código errado pareça errado (role até a seção "A solução real", ou melhor, leia-o completamente; vale a pena, mesmo que ele endereça variáveis ao invés de nomes de funções). Então, humildemente, sugiro renomear sua função para algo como
f_unsafe_for_external_use()
- você provavelmente criará algum esquema de abreviação.Edit: Eu acho que a sugestão de amon é uma variação muito boa, baseada em OO, sobre o mesmo tema :-)
fonte
Complementando a sugestão de @amon, você também pode pensar em combinar o padrão de estratégia aqui, bem como o padrão de objeto do método.
E então uma implementação 'normal'
E uma implementação admin-input-eval
(Nota: com um exemplo do mundo real, talvez eu possa dar um exemplo melhor).
fonte