сбой ограниченной функции eval - как импортировать выбранные модули - PullRequest
0 голосов
/ 15 апреля 2019

Я хочу прикрепить функциональные заглушки к написанному мною процессу обработки данных, и было бы удобно иметь возможность применять их через файл конфигурации.

Я могу загрузить и запустить их с помощью функции eval, но хочу иметь возможность управлять доступным «песочницей» пространства имен, в которой могут работать оцениваемые функции, чтобы избежать внедрения вредоносного кода.

В документации по python предлагается отключить __builtins__ и затем заполнить глобальные и локальные (или это оба? Неясно) глобальные и локальные объекты как словари, содержащие объекты в пространстве имен выполнения.

Когда я делаю это, код, который я успешно выполнял, перестает работать.

Я думаю это потому, что одна из моих тестовых лямбда-ссылок ссылается на функции, обычно импортируемые из модуля datetime - но мне не ясно, как заставить их успешно присоединиться к пространству имен.

from datetime import datetime
now = datetime.now()
lambdas = { "Report Date" : "lambda x : now.strftime(\"%d/%m/%Y\")",
             "Scary Test"  : "lambda x : os.curdir " }

compiled_funcs = {k:eval(v) for k,v in lambdas.items()}

compiled_funcs ['Report Date'](1)
>>> '15/04/2019'

compiled_funcs ['Scary Test'](1)
>>> '.'

Теперь я хочу отредактировать функцию eval(), чтобы ограничить доступную область видимости, чтобы функция datetime продолжала работать, но модуль os не работает (если я могу вызвать команду os, я мог бы сделать что-то пугающее как протереть диск или еще хуже)

Я пробовал такие конструкции, как:

compiled_funcs = {k:eval(v,{'__builtins__':None, "now" : now, "datetime" : datetime, } , { }) for k,v in lambdas.items()}

Но когда я это делаю, я получаю следующую ошибку:

AttributeError: 'NoneType' object has no attribute '__import__'

Что говорит о том, что где-то / каким-то образом функция, которую я хочу применить, пытается вызвать / импортировать некоторый контент по линии - и (предположительно) это правильно блокируется из-за того, что он заблокировал содержимое __builtins__. Есть ли способ предварительно упаковать такие функции и внедрить их в глобальные переменные eval или словари localals для включения предопределенного набора функциональных инструментов?

Как только я получу эту работу, я смогу расширить ее, чтобы я мог курировать свое собственное подмножество безопасных вызовов функций, которые будут доступны для этой коллекции во время выполнения из файлов конфигурации.

N.B. Я знаю, что выше, я мог бы определить свой lambdæ без аргументов - но в моем реальном коде было бы нормально передать один параметр, поэтому я соответственно построил свой тестовый код.

...