Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ repos:
entry: python ./build_scripts/remove_notebook_headers.py
language: python
files: ^doc.*\.(ipynb)$
- id: sanitize-notebook-paths
name: Sanitize Notebook Paths
entry: python ./build_scripts/sanitize_notebook_paths.py
language: python
files: ^doc.*\.(ipynb)$

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
Expand Down
129 changes: 129 additions & 0 deletions build_scripts/sanitize_notebook_paths.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

import json
import re
import sys
from re import Match

# Windows path: captures user prefix AND remaining path for normalization
_WINDOWS_PATH_PATTERN = re.compile(
r"[A-Za-z]:\\+Users\\+[^\\]+\\+((?:[^\\\s\"',:;]+\\+)*[^\\\s\"',:;]*)",
re.IGNORECASE,
)
# Unix paths: just match the prefix
_UNIX_PATH_PATTERNS = [
re.compile(r"/Users/[^/]+/"), # macOS
re.compile(r"/home/[^/]+/"), # Linux
]


def _windows_path_replacer(match: Match[str]) -> str:
"""Replace Windows user path prefix with ./ and normalize backslashes to forward slashes."""
remainder = match.group(1)
normalized = remainder.replace("\\", "/")
# Collapse multiple forward slashes from double-backslash paths
return "./" + re.sub(r"/+", "/", normalized)


def sanitize_notebook_paths(file_path: str) -> bool:
"""
Remove user-specific path prefixes from notebook cell outputs.

Replaces paths like C:\\Users\\username\\project\\file.py with ./project/file.py.

Args:
file_path (str): Path to the .ipynb file.

Returns:
bool: True if the file was modified.
"""
if not file_path.endswith(".ipynb"):
return False

with open(file_path, encoding="utf-8") as f:
content = json.load(f)

modified = False

for cell in content.get("cells", []):
for output in cell.get("outputs", []):
modified = _sanitize_output_field(output, "text") or modified
modified = _sanitize_output_field(output, "traceback") or modified
modified = _sanitize_output_field(output, "evalue") or modified
if "data" in output:
for mime_type in output["data"]:
if mime_type.startswith("text/"):
modified = _sanitize_output_field(output["data"], mime_type) or modified

if not modified:
return False

with open(file_path, "w", encoding="utf-8") as f:
json.dump(content, f, indent=1, ensure_ascii=False)
f.write("\n")

return True


def _sanitize_output_field(obj: dict, key: str) -> bool:
"""
Sanitize a single output field by replacing user path prefixes with ./ normalized paths.

Args:
obj (dict): The dict containing the field.
key (str): The key to sanitize.

Returns:
bool: True if the field was modified.
"""
value = obj.get(key)
if value is None:
return False

modified = False

if isinstance(value, list):
new_list = []
for line in value:
if isinstance(line, str):
sanitized = _strip_user_paths(line)
if sanitized != line:
modified = True
new_list.append(sanitized)
else:
new_list.append(line)
obj[key] = new_list
elif isinstance(value, str):
sanitized = _strip_user_paths(value)
if sanitized != value:
modified = True
obj[key] = sanitized

return modified


def _strip_user_paths(text: str) -> str:
"""
Replace user-specific path prefixes with ./ and normalize separators.

Windows paths are normalized to forward slashes. For example,
C:\\Users\\alice\\project\\file.py becomes ./project/file.py.

Args:
text (str): The text to sanitize.

Returns:
str: The sanitized text.
"""
text = _WINDOWS_PATH_PATTERN.sub(_windows_path_replacer, text)
for pattern in _UNIX_PATH_PATTERNS:
text = pattern.sub("./", text)
return text


if __name__ == "__main__":
modified_files = [file_path for file_path in sys.argv[1:] if sanitize_notebook_paths(file_path)]
if modified_files:
print("Sanitized user paths in:", modified_files)
sys.exit(1)
4 changes: 2 additions & 2 deletions doc/code/auxiliary_attacks/1_gcg_azure_ml.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
{
"data": {
"text/plain": [
"Environment({'arm_type': 'environment_version', 'latest_version': None, 'image': None, 'intellectual_property': None, 'is_anonymous': False, 'auto_increment_version': False, 'auto_delete_setting': None, 'name': 'pyrit', 'description': 'PyRIT environment created from a Docker context.', 'tags': {}, 'properties': {'azureml.labels': 'latest'}, 'print_as_yaml': False, 'id': '/subscriptions/db1ba766-2ca3-42c6-a19a-0f0d43134a8c/resourceGroups/romanlutz/providers/Microsoft.MachineLearningServices/workspaces/romanlutz/environments/pyrit/versions/5', 'Resource__source_path': '', 'base_path': 'c:\\\\Users\\\\Roman\\\\git\\\\PyRIT\\\\doc\\\\code\\\\auxiliary_attacks', 'creation_context': <azure.ai.ml.entities._system_data.SystemData object at 0x0000024025678AD0>, 'serialize': <msrest.serialization.Serializer object at 0x0000024025671470>, 'version': '5', 'conda_file': None, 'build': <azure.ai.ml.entities._assets.environment.BuildContext object at 0x00000240256FC410>, 'inference_config': None, 'os_type': 'Linux', 'conda_file_path': None, 'path': None, 'datastore': None, 'upload_hash': None, 'translated_conda_file': None})"
"Environment({'arm_type': 'environment_version', 'latest_version': None, 'image': None, 'intellectual_property': None, 'is_anonymous': False, 'auto_increment_version': False, 'auto_delete_setting': None, 'name': 'pyrit', 'description': 'PyRIT environment created from a Docker context.', 'tags': {}, 'properties': {'azureml.labels': 'latest'}, 'print_as_yaml': False, 'id': '/subscriptions/db1ba766-2ca3-42c6-a19a-0f0d43134a8c/resourceGroups/romanlutz/providers/Microsoft.MachineLearningServices/workspaces/romanlutz/environments/pyrit/versions/5', 'Resource__source_path': '', 'base_path': './git/PyRIT/doc/code/auxiliary_attacks', 'creation_context': <azure.ai.ml.entities._system_data.SystemData object at 0x0000024025678AD0>, 'serialize': <msrest.serialization.Serializer object at 0x0000024025671470>, 'version': '5', 'conda_file': None, 'build': <azure.ai.ml.entities._assets.environment.BuildContext object at 0x00000240256FC410>, 'inference_config': None, 'os_type': 'Linux', 'conda_file_path': None, 'path': None, 'datastore': None, 'upload_hash': None, 'translated_conda_file': None})"
]
},
"execution_count": null,
Expand Down Expand Up @@ -199,7 +199,7 @@
"Class BaseIntellectualPropertySchema: This is an experimental class, and may change at any time. Please see https://aka.ms/azuremlexperimental for more information.\n",
"Your file exceeds 100 MB. If you experience low speeds, latency, or broken connections, we recommend using the AzCopyv10 tool for this file transfer.\n",
"\n",
"Example: azcopy copy 'C:\\Users\\Roman\\git\\PyRIT' 'https://romanlutz0437468309.blob.core.windows.net/3f52e8b9-0bac-4c48-9e4a-a92e85a582c4-10s61nn9uso4b2p89xjypawyc7/PyRIT' \n",
"Example: azcopy copy './git/PyRIT' 'https://romanlutz0437468309.blob.core.windows.net/3f52e8b9-0bac-4c48-9e4a-a92e85a582c4-10s61nn9uso4b2p89xjypawyc7/PyRIT' \n",
"\n",
"See https://learn.microsoft.com/azure/storage/common/storage-use-azcopy-v10 for more information.\n",
"\u001b[32mUploading PyRIT (194.65 MBs): 100%|##########| 194652493/194652493 [01:19<00:00, 2447407.71it/s] \n",
Expand Down
6 changes: 3 additions & 3 deletions doc/code/converters/3_image_converters.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Found default environment files: ['C:\\\\Users\\\\rlundeen\\\\.pyrit\\\\.env', 'C:\\\\Users\\\\rlundeen\\\\.pyrit\\\\.env.local']\n",
"Loaded environment file: C:\\Users\\rlundeen\\.pyrit\\.env\n",
"Loaded environment file: C:\\Users\\rlundeen\\.pyrit\\.env.local\n",
"Found default environment files: ['./.pyrit/.env', './.pyrit/.env.local']\n",
"Loaded environment file: ./.pyrit/.env\n",
"Loaded environment file: ./.pyrit/.env.local\n",
"QR code saved to: C:\\git\\PyRIT\\dbdata\\prompt-memory-entries\\images\\1767215000773182.png\n"
]
},
Expand Down
6 changes: 3 additions & 3 deletions doc/code/converters/4_video_converters.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Found default environment files: ['/home/vscode/.pyrit/.env', '/home/vscode/.pyrit/.env.local']\n",
"Loaded environment file: /home/vscode/.pyrit/.env\n",
"Loaded environment file: /home/vscode/.pyrit/.env.local\n"
"Found default environment files: ['./.pyrit/.env', './.pyrit/.env.local']\n",
"Loaded environment file: ./.pyrit/.env\n",
"Loaded environment file: ./.pyrit/.env.local\n"
]
},
{
Expand Down
26 changes: 13 additions & 13 deletions doc/code/converters/5_file_converters.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Found default environment files: ['C:\\\\Users\\\\romanlutz\\\\.pyrit\\\\.env', 'C:\\\\Users\\\\romanlutz\\\\.pyrit\\\\.env.local']\n",
"Loaded environment file: C:\\Users\\romanlutz\\.pyrit\\.env\n",
"Loaded environment file: C:\\Users\\romanlutz\\.pyrit\\.env.local\n",
"TextTarget: user: C:\\Users\\romanlutz\\git\\PyRIT3\\dbdata\\prompt-memory-entries\\binaries\\1771544413320034.pdf\n"
"Found default environment files: ['./.pyrit/.env', './.pyrit/.env.local']\n",
"Loaded environment file: ./.pyrit/.env\n",
"Loaded environment file: ./.pyrit/.env.local\n",
"TextTarget: user: ./git/PyRIT3/dbdata/prompt-memory-entries/binaries/1771544413320034.pdf\n"
]
},
{
Expand All @@ -78,7 +78,7 @@
"\u001b[37m coffee', 'applicant_name': 'John Smith'}\u001b[0m\n",
"\n",
"\u001b[36m Converted:\u001b[0m\n",
"\u001b[37m C:\\Users\\romanlutz\\git\\PyRIT3\\dbdata\\prompt-memory-entries\\binaries\\1771544413320034.pdf\u001b[0m\n",
"\u001b[37m ./git/PyRIT3/dbdata/prompt-memory-entries/binaries/1771544413320034.pdf\u001b[0m\n",
"\n",
"\u001b[34m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
]
Expand Down Expand Up @@ -170,7 +170,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"TextTarget: user: C:\\Users\\romanlutz\\git\\PyRIT3\\dbdata\\prompt-memory-entries\\binaries\\1771544413393574.pdf\n"
"TextTarget: user: ./git/PyRIT3/dbdata/prompt-memory-entries/binaries/1771544413393574.pdf\n"
]
},
{
Expand All @@ -192,7 +192,7 @@
"\u001b[37m This is a simple test string for PDF generation. No templates here!\u001b[0m\n",
"\n",
"\u001b[36m Converted:\u001b[0m\n",
"\u001b[37m C:\\Users\\romanlutz\\git\\PyRIT3\\dbdata\\prompt-memory-entries\\binaries\\1771544413393574.pdf\u001b[0m\n",
"\u001b[37m ./git/PyRIT3/dbdata/prompt-memory-entries/binaries/1771544413393574.pdf\u001b[0m\n",
"\n",
"\u001b[34m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
]
Expand Down Expand Up @@ -270,7 +270,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"TextTarget: user: C:\\Users\\romanlutz\\git\\PyRIT3\\dbdata\\prompt-memory-entries\\binaries\\1771544413696795.pdf\n"
"TextTarget: user: ./git/PyRIT3/dbdata/prompt-memory-entries/binaries/1771544413696795.pdf\n"
]
},
{
Expand All @@ -292,7 +292,7 @@
"\u001b[37m Modify existing PDF\u001b[0m\n",
"\n",
"\u001b[36m Converted:\u001b[0m\n",
"\u001b[37m C:\\Users\\romanlutz\\git\\PyRIT3\\dbdata\\prompt-memory-entries\\binaries\\1771544413696795.pdf\u001b[0m\n",
"\u001b[37m ./git/PyRIT3/dbdata/prompt-memory-entries/binaries/1771544413696795.pdf\u001b[0m\n",
"\n",
"\u001b[34m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
]
Expand Down Expand Up @@ -400,7 +400,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"TextTarget: user: C:\\Users\\romanlutz\\git\\PyRIT3\\dbdata\\prompt-memory-entries\\binaries\\1771544413782754.docx\n"
"TextTarget: user: ./git/PyRIT3/dbdata/prompt-memory-entries/binaries/1771544413782754.docx\n"
]
},
{
Expand All @@ -422,7 +422,7 @@
"\u001b[37m This is a simple test string for Word document generation.\u001b[0m\n",
"\n",
"\u001b[36m Converted:\u001b[0m\n",
"\u001b[37m C:\\Users\\romanlutz\\git\\PyRIT3\\dbdata\\prompt-memory-entries\\binaries\\1771544413782754.docx\u001b[0m\n",
"\u001b[37m ./git/PyRIT3/dbdata/prompt-memory-entries/binaries/1771544413782754.docx\u001b[0m\n",
"\n",
"\u001b[34m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
]
Expand Down Expand Up @@ -466,7 +466,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"TextTarget: user: C:\\Users\\romanlutz\\git\\PyRIT3\\dbdata\\prompt-memory-entries\\binaries\\1771544413886346.docx\n"
"TextTarget: user: ./git/PyRIT3/dbdata/prompt-memory-entries/binaries/1771544413886346.docx\n"
]
},
{
Expand All @@ -488,7 +488,7 @@
"\u001b[37m AI Red Team Engineer\u001b[0m\n",
"\n",
"\u001b[36m Converted:\u001b[0m\n",
"\u001b[37m C:\\Users\\romanlutz\\git\\PyRIT3\\dbdata\\prompt-memory-entries\\binaries\\1771544413886346.docx\u001b[0m\n",
"\u001b[37m ./git/PyRIT3/dbdata/prompt-memory-entries/binaries/1771544413886346.docx\u001b[0m\n",
"\n",
"\u001b[34m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
]
Expand Down
6 changes: 3 additions & 3 deletions doc/code/converters/6_selectively_converting.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Found default environment files: ['/home/vscode/.pyrit/.env', '/home/vscode/.pyrit/.env.local']\n",
"Loaded environment file: /home/vscode/.pyrit/.env\n",
"Loaded environment file: /home/vscode/.pyrit/.env.local\n"
"Found default environment files: ['./.pyrit/.env', './.pyrit/.env.local']\n",
"Loaded environment file: ./.pyrit/.env\n",
"Loaded environment file: ./.pyrit/.env.local\n"
]
}
],
Expand Down
6 changes: 3 additions & 3 deletions doc/code/datasets/1_loading_datasets.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Found default environment files: ['C:\\\\Users\\\\romanlutz\\\\.pyrit\\\\.env', 'C:\\\\Users\\\\romanlutz\\\\.pyrit\\\\.env.local']\n",
"Loaded environment file: C:\\Users\\romanlutz\\.pyrit\\.env\n",
"Loaded environment file: C:\\Users\\romanlutz\\.pyrit\\.env.local\n"
"Found default environment files: ['./.pyrit/.env', './.pyrit/.env.local']\n",
"Loaded environment file: ./.pyrit/.env\n",
"Loaded environment file: ./.pyrit/.env.local\n"
]
},
{
Expand Down
6 changes: 3 additions & 3 deletions doc/code/datasets/2_seed_programming.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Found default environment files: ['C:\\\\Users\\\\rlundeen\\\\.pyrit\\\\.env', 'C:\\\\Users\\\\rlundeen\\\\.pyrit\\\\.env.local']\n",
"Loaded environment file: C:\\Users\\rlundeen\\.pyrit\\.env\n",
"Loaded environment file: C:\\Users\\rlundeen\\.pyrit\\.env.local\n",
"Found default environment files: ['./.pyrit/.env', './.pyrit/.env.local']\n",
"Loaded environment file: ./.pyrit/.env\n",
"Loaded environment file: ./.pyrit/.env.local\n",
"Attack Parameters: AttackParameters:\n",
" objective: Get the model to describe pyrit architecture based on the image\n",
" next_message: (2 piece(s)) Describe the image in the image_path\n",
Expand Down
12 changes: 6 additions & 6 deletions doc/code/executor/attack/1_prompt_sending_attack.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Found default environment files: ['C:\\\\Users\\\\rlundeen\\\\.pyrit\\\\.env', 'C:\\\\Users\\\\rlundeen\\\\.pyrit\\\\.env.local']\n",
"Loaded environment file: C:\\Users\\rlundeen\\.pyrit\\.env\n",
"Loaded environment file: C:\\Users\\rlundeen\\.pyrit\\.env.local\n"
"Found default environment files: ['./.pyrit/.env', './.pyrit/.env.local']\n",
"Loaded environment file: ./.pyrit/.env\n",
"Loaded environment file: ./.pyrit/.env.local\n"
]
},
{
Expand Down Expand Up @@ -1066,9 +1066,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Found default environment files: ['C:\\\\Users\\\\rlundeen\\\\.pyrit\\\\.env', 'C:\\\\Users\\\\rlundeen\\\\.pyrit\\\\.env.local']\n",
"Loaded environment file: C:\\Users\\rlundeen\\.pyrit\\.env\n",
"Loaded environment file: C:\\Users\\rlundeen\\.pyrit\\.env.local\n"
"Found default environment files: ['./.pyrit/.env', './.pyrit/.env.local']\n",
"Loaded environment file: ./.pyrit/.env\n",
"Loaded environment file: ./.pyrit/.env.local\n"
]
},
{
Expand Down
Loading