-
-
Notifications
You must be signed in to change notification settings - Fork 9k
Add root-isolated online notebook environment #740
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Namelessh8te
wants to merge
4
commits into
Z4nzu:master
Choose a base branch
from
Namelessh8te:online-notebooks
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| { | ||
| "name": "hackingtool notebook", | ||
| "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bookworm", | ||
| "remoteUser": "root", | ||
| "containerUser": "root", | ||
| "updateRemoteUserUID": false, | ||
| "postCreateCommand": "python -m pip install --disable-pip-version-check -r .devcontainer/requirements.txt", | ||
| "customizations": { | ||
| "vscode": { | ||
| "extensions": [ | ||
| "ms-python.python", | ||
| "ms-toolsai.jupyter" | ||
| ], | ||
| "settings": { | ||
| "python.defaultInterpreterPath": "/usr/local/bin/python", | ||
| "jupyter.notebookFileRoot": "${workspaceFolder}" | ||
| } | ||
| } | ||
| }, | ||
| "forwardPorts": [ | ||
| 8888 | ||
| ], | ||
| "portsAttributes": { | ||
| "8888": { | ||
| "label": "JupyterLab", | ||
| "onAutoForward": "silent", | ||
| "visibility": "private" | ||
| } | ||
| }, | ||
| "hostRequirements": { | ||
| "cpus": 2, | ||
| "memory": "4gb", | ||
| "storage": "16gb" | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| -r ../requirements.txt | ||
| ipykernel>=6.29 | ||
| jupyterlab>=4.2 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| { | ||
| "cells": [ | ||
| { | ||
| "cell_type": "markdown", | ||
| "metadata": {}, | ||
| "source": [ | ||
| "# Interactive hackingtool workspace\n", | ||
| "\n", | ||
| "This notebook is ready for **Run All** in the repository's GitHub Codespace. Commands run as `root` inside the isolated container, not on the Codespaces host.\n", | ||
| "\n", | ||
| "The notebook prepares a non-blocking launcher and a safe argument-based command helper. Run security tools only against systems you own or are explicitly authorized to test." | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": null, | ||
| "metadata": {}, | ||
| "outputs": [], | ||
| "source": [ | ||
| "import os\n", | ||
| "import subprocess\n", | ||
| "import sys\n", | ||
| "from pathlib import Path\n", | ||
| "from typing import Sequence\n", | ||
| "\n", | ||
| "\n", | ||
| "def find_repo_root(start: Path | None = None) -> Path:\n", | ||
| " \"\"\"Find the repository without depending on the notebook launch directory.\"\"\"\n", | ||
| " current = (start or Path.cwd()).resolve()\n", | ||
| " for candidate in (current, *current.parents):\n", | ||
| " if (candidate / \"hackingtool.py\").is_file():\n", | ||
| " return candidate\n", | ||
| " raise FileNotFoundError(\"Could not find hackingtool.py from the current directory\")\n", | ||
|
|
||
| "\n", | ||
| "\n", | ||
| "REPO_ROOT = find_repo_root()\n", | ||
| "IS_ROOT = (os.geteuid() == 0) if hasattr(os, \"geteuid\") else False\n", | ||
| "IS_ISOLATED_CONTAINER = Path(\"/.dockerenv\").exists() or bool(\n", | ||
| " os.environ.get(\"CODESPACES\") or os.environ.get(\"REMOTE_CONTAINERS\")\n", | ||
| ")\n", | ||
| "\n", | ||
| "\n", | ||
| "def run_command(\n", | ||
| " arguments: Sequence[str | os.PathLike[str]],\n", | ||
| " *,\n", | ||
| " cwd: Path = REPO_ROOT,\n", | ||
| " check: bool = True,\n", | ||
| ") -> subprocess.CompletedProcess[str]:\n", | ||
| " \"\"\"Run an explicit argument list without shell interpolation.\"\"\"\n", | ||
| " if not arguments:\n", | ||
| " raise ValueError(\"At least one command argument is required\")\n", | ||
| " command = [os.fspath(argument) for argument in arguments]\n", | ||
| " print(\"Running:\", subprocess.list2cmdline(command))\n", | ||
| " return subprocess.run(\n", | ||
| " command,\n", | ||
| " cwd=cwd,\n", | ||
| " check=check,\n", | ||
| " text=True,\n", | ||
| " )\n", | ||
| "\n", | ||
| "\n", | ||
| "def launch_hackingtool() -> subprocess.CompletedProcess[str]:\n", | ||
| " \"\"\"Launch the interactive CLI on demand; this is not called by Run All.\"\"\"\n", | ||
| " return run_command([sys.executable, REPO_ROOT / \"hackingtool.py\"], check=False)" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": null, | ||
| "metadata": {}, | ||
| "outputs": [], | ||
| "source": [ | ||
| "# Run-All readiness check.\n", | ||
| "required_files = [\n", | ||
| " REPO_ROOT / \"hackingtool.py\",\n", | ||
| " REPO_ROOT / \"constants.py\",\n", | ||
| " REPO_ROOT / \"requirements.txt\",\n", | ||
| "]\n", | ||
| "missing_files = [path.name for path in required_files if not path.is_file()]\n", | ||
| "if missing_files:\n", | ||
| " raise FileNotFoundError(f\"Missing required project files: {missing_files}\")\n", | ||
| "\n", | ||
| "write_probe = REPO_ROOT / \".interactive-notebook-write-check\"\n", | ||
| "try:\n", | ||
| " write_probe.write_text(\"ok\", encoding=\"utf-8\")\n", | ||
| "finally:\n", | ||
| " write_probe.unlink(missing_ok=True)\n", | ||
| "\n", | ||
| "print(f\"Repository: {REPO_ROOT}\")\n", | ||
| "print(f\"Python: {sys.version.split()[0]}\")\n", | ||
| "print(f\"Root in container: {IS_ROOT}\")\n", | ||
| "print(f\"Container detected: {IS_ISOLATED_CONTAINER}\")\n", | ||
| "print(\"\\nRun All is complete. Call launch_hackingtool() when you want the interactive CLI.\")" | ||
| ] | ||
| } | ||
| ], | ||
| "metadata": { | ||
| "kernelspec": { | ||
| "display_name": "Python 3", | ||
| "language": "python", | ||
| "name": "python3" | ||
| }, | ||
| "language_info": { | ||
| "codemirror_mode": { | ||
| "name": "ipython", | ||
| "version": 3 | ||
| }, | ||
| "file_extension": ".py", | ||
| "mimetype": "text/x-python", | ||
| "name": "python", | ||
| "nbconvert_exporter": "python", | ||
| "pygments_lexer": "ipython3", | ||
| "version": "3.12" | ||
| } | ||
| }, | ||
| "nbformat": 4, | ||
| "nbformat_minor": 5 | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| # Run the notebook online | ||
|
|
||
| The repository includes a GitHub Codespaces configuration for both | ||
| `contents for hackertools.ipynb` and `Interactive-1.ipynb`. The Codespace runs | ||
| as `root` inside its isolated container. Root access applies only to the | ||
| container; it does not grant access to the Codespaces host. | ||
|
|
||
| ## Start in GitHub Codespaces | ||
|
|
||
| 1. Push this branch to a GitHub repository you control. | ||
| 2. Open the repository on GitHub and select **Code → Codespaces → Create | ||
| codespace on this branch**. | ||
| 3. Wait for the container setup to finish. | ||
| 4. Open either notebook: | ||
| - `contents for hackertools.ipynb` for environment detection and explicit | ||
| system-package installation. | ||
| - `Interactive-1.ipynb` for the project-aware command helper and interactive | ||
| CLI launcher. | ||
| 5. Select the **Python 3** kernel and choose **Run All**. | ||
|
|
||
| The environment check should print: | ||
|
|
||
| ```text | ||
| system linux | ||
| is_root True | ||
| ... | ||
| Ready: root permissions are available inside the isolated container. | ||
| ``` | ||
|
|
||
| ## Optional JupyterLab server | ||
|
|
||
| The browser-based Codespaces editor can run the notebook directly. If a | ||
| standalone JupyterLab UI is preferred, run this from the Codespaces terminal: | ||
|
|
||
| ```bash | ||
| jupyter lab --ip=0.0.0.0 --port=8888 --no-browser --allow-root | ||
| ``` | ||
|
|
||
| Codespaces forwards port 8888 privately by default. Keep it private and retain | ||
| Jupyter's generated access token. | ||
|
|
||
| ## Permission boundary | ||
|
|
||
| The container intentionally does not use Docker `--privileged`, host filesystem | ||
| mounts, or a Docker socket mount. Those are not required for this notebook and | ||
| would weaken isolation. Use security tooling only on systems you own or have | ||
| explicit authorization to test. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.