Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .devcontainer/devcontainer.json
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",
Comment thread
Namelessh8te marked this conversation as resolved.
Outdated
"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"
}
}
3 changes: 3 additions & 0 deletions .devcontainer/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-r ../requirements.txt
ipykernel>=6.29
jupyterlab>=4.2
118 changes: 118 additions & 0 deletions Interactive-1.ipynb
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
}
47 changes: 47 additions & 0 deletions ONLINE_NOTEBOOK.md
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.
Loading