This post has been republished via RSS; it originally appeared at: Windows Blog.
Sandboxing Python can be very useful for developers but has been challenging due to the flexibility of CPython implementation. It is particularly useful in many scenarios to have sandboxed Python. For example, on any website that needs to execute arbitrary code from users, like coding practice sites or online interpreters. It could also be useful to help prevent increasing attacks on LLMs (Large Language Models). Win32 App Isolation (https://github.com/microsoft/win32-app-isolation) lights up a different path to sandboxing Python – not on a Python library level, but on an application/OS level. Win32 App Isolation is designed to isolate Win32 application by creating a security boundary between the application and the OS, using the combination of AppContainer, virtualized resources and brokering file system, which helps to prevent the application from compromising the operating system. Following are the specifics requirements and guidance for sandboxing CPython with Win32 App Isolation on recent Windows Insider releases. It takes about 30-60 minutes and anyone with the insider version of Windows can do it on their local machine. To use Win32 App Isolation, you need the insider version of Windows with version number > 25357, and the MSIX Packaging Tool from https://github.com/microsoft/win32-app-isolation/releases/ Step One: Download the Python installer for Windows from python.org. 3.12.2 was used for this specific example. Step Two: Package it by following the documentation (https://github.com/microsoft/win32-app-isolation/blob/main/docs/packaging/msix-packaging-tool.md). You may need a certificate to sign the package to install it (https://learn.microsoft.com/en-us/windows/msix/packaging-tool/create-app-package#signing-preference). AddisolatedWin32-PromptForAccess
capability for demonstration purposes, so you can allow it to access certain resources in prompts. Without the capability, all access to the user files that are not explicitly set to be available to the application would be denied.
Add an alias python3.12.exe
to use it from PowerShell.
Step Three:
Install the package. Use the defined alias python3.12.exe
in PowerShell to bring up the Python interpreter.
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/1.png)
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture2.png)
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture3.png)
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture4.png)
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture5.png)
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture6.png)
def test_urllib(): with urllib.request.urlopen("http://www.microsoft.com") as response: print(response.read())
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture7.png)
def test_open(): with open("../data/test.txt", "w") as f: f.write("test")
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture8.png)
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture10.png)
def test_native(): handle = ctypes.windll.kernel32.CreateFileW("../data/test.txt", 0x10000000, 0, None, 1, 0x80, 0) if handle > 0: ctypes.windll.kernel32.CloseHandle(handle) else: raise RuntimeError("Failed to get the handle")
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture11.png)
os.system()
and subprocess
:
def test_os_system(): os.system("powershell -command cat c:/data/test/bin/data/test.txt") def test_subprocess(): subprocess.run(["powershell", "-command", "cat", "c:/data/test/bin/data/test.txt"], shell=True)
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture12.png)
sys.path
will trigger the prompt too:
def test_import(): sys.path.append("../data") import example
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture13.png)
example.py
is in the data directory and clicking “yes” would successfully import it):
![A screenshot of a computer](https://blogs.windows.com/wp-content/uploads/prod/sites/3/2024/02/Picture14.png)
- How can you “click” the prompts if you want to deploy this on your server? As mentioned above,
isolatedWin32-promptForAccess
is only added for demonstration purposes, and it is not needed for isolation. Without it, your system would simply deny any access to user files, thus helping to prevent attacks like ransomware. - Then how can you grant access to the application for required files like modules, scripts, and data? There are several ways to do it:
- You can package the modules you need into your app, then they will be accessible by default.
- You can put the file you need access to into the app’s profile in
%localappdata%
where the app is granted access automatically. - You can put the file to a “publisher directory”, which is any directory with a name ending with your app’s publisher ID in
c:\ProgramData
. (win32-app-isolation/docs/fundamentals/consent.md at main · microsoft/win32-app-isolation (github.com)) - You can set the access of files and directories with icalcs to allow your app or all apps to access them.