Twoje wymagane ograniczenia mogą zostać złamane nawet po usunięciu wszystkich modułów i wszystkich funkcji. Kod może uzyskać dostęp do plików, jeśli może korzystać z atrybutów dowolnego prostego obiektu, np. liczby zero.
(0).__class__.__base__.__subclasses__()[40]('/etc/pas'+'swd')
Indeks 40
jest indywidualny i bardzo typowe dla Pythona 2.7, ale indeks podklasy <type 'file'>
mogą być łatwo znalezione:
[x for x in (1).__class__.__base__.__subclasses__()if'fi'+'le'in'%s'%x][0](
'/etc/pas'+'swd')
Dowolna kombinacja białej liście i czarnej jest albo niebezpieczne i/lub zbyt restrykcyjne. pypy sandbox jest odporny na zasadzie bez kompromisów:
... To podproces można uruchomić dowolny niezaufane kodu Pythona, ale wszystko jego wejścia/wyjścia jest szeregowane do potoku stdin/stdout zamiast bezpośrednio wykonywane. Proces czyta zewnętrzna rury i decyduje, które polecenia są dozwolone, czy nie (Piaskownica), a nawet na nowo interpretuje je inaczej ...
także rozwiązanie oparte na seccomp funkcji jądra może być wystarczająco bezpieczne. (blog)
Chcę mieć pewność, że w przyszłości funkcja wygeneruje taką samą wyjścia jak dzisiaj.
Łatwo jest napisać funkcję, która ma twardych powtarzalne wyniki i nie można łatwo zapobiec:
class A(object):
"This can be any very simple class"
def __init__(self, x):
self.x = x
def __repr__(self):
return repr(self.x)
def strange_function():
# You get a different result probably everytimes.
return list(set(A(i) for i in range(20)))
>>> strange_function()
[1, 18, 12, 5, 16, 15, 8, 2, 14, 0, 6, 19, 13, 11, 10, 9, 17, 3, 7, 4]
>>> strange_function()
[0, 9, 14, 3, 17, 5, 6, 11, 8, 1, 15, 7, 12, 13, 2, 10, 16, 4, 19, 18]
... nawet jeśli usuniesz everythng który zależy od czasu, liczba losowa generator, zlecenie oparte na funkcji skrótu itd., można też łatwo napisać funkcję, która czasami przekracza dostępną pamięć lub limit czasu, a czasami daje wynik.
EDIT:
Roman, napisał niedawno, że jesteś pewien, że można wierzyć użytkownikowi. Wtedy istnieje realistyczne rozwiązanie. Jest to weryfikacja danych wejściowych i wyjściowych z funkcji poprzez zapisanie ich w pliku i weryfikacja na maszynie wirtualnej z uruchomionym zdalnym IPython notebook (niezły krótki film instruktażowy, obsługa zdalnego komputera po wyjęciu z pudełka, ponowne uruchomienie usługi backendu przez sieć WWW menu dokumentu z przeglądarki w ciągu jednej sekundy, bez utraty danych (wejścia/wyjścia) w notatniku (dokument HTML), ponieważ jest tworzony dynamicznie krok po kroku przez naszą aktywność wyzwalającą javascript, który wywołuje zdalny backend).
Nie musisz być zainteresowany połączeniami wewnętrznymi, a jedynie globalnym wejściem i wyjściem, dopóki nie znajdziesz różnic. Maszyna wirtualna powinna być w stanie zweryfikować wyniki niezależnie i odtwarzalne. Skonfiguruj zaporę, aby maszyna akceptowała połączenia od ciebie, ale nie może inicjować połączenia wychodzącego. Skonfiguruj system plików, aby żaden bieżący użytkownik nie mógł zapisać danych, a zatem nie są one obecne, z wyjątkiem komponentów oprogramowania. Wyłącz usługi baz danych. Sprawdź wprowadzanie/wyprowadzanie wyników w losowej kolejności lub uruchom dwie usługi IPython dla notebooków na różnych portach i wybierz losowy backend dla każdej linii poleceń w notebooku lub zrestartuj proces backendu często zanim cokolwiek ważnego. Jeśli znajdziesz różnicę, rozwiąż swój kod i napraw go.
Można go zautomatyzować bez "notatnika" tylko w przypadku zdalnej obsługi IPython, gdy nie jest wymagana interaktywność.
Wykonaj kopię zapasową kroku. * Dlaczego * chcesz uniemożliwić komuś czytanie z zewnętrznego źródła? – chepner
Istnieje wiele powodów. Przede wszystkim chcę mieć pewność, że w przyszłości funkcja wygeneruje taki sam wynik jak dziś. Po drugie, generalnie uważam, że jest to "brzydkie" rozwiązanie, gdy funkcja gdzieś coś czyta. Powinien widzieć tylko to, co wyraźnie otrzymuje jako dane wejściowe. Jeśli coś powinno zostać odczytane z pliku lub bazy danych, należy go odczytać poza funkcją i przekazać do funkcji jako jedno z jego wejść. – Roman
Więc chcesz użyć kodu, któremu nie ufasz? –