diff --git a/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py b/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py index a9f7cc7c68..eca4d6af63 100644 --- a/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py +++ b/pyrit/prompt_converter/token_smuggling/ascii_smuggler_converter.py @@ -26,12 +26,13 @@ class AsciiSmugglerConverter(SmugglerConverter): # TODO: remove this opt-out and insert ``*,`` after ``self`` in 0.16.0. _brick_legacy_init = True - def __init__(self, action: Literal["encode", "decode"] = "encode", unicode_tags: bool = False) -> None: + def __init__(self, action: Literal["encode", "decode"] | None = None, unicode_tags: bool = False) -> None: """ Initialize the converter with options for encoding/decoding. Args: - action (Literal["encode", "decode"]): The action to perform. + action (Literal["encode", "decode"] | None): The action to perform; defaults to + ``SmugglerConverter.DEFAULT_ACTION`` (``"encode"``). unicode_tags (bool): Whether to add Unicode tags during encoding. """ self.unicode_tags = unicode_tags diff --git a/pyrit/prompt_converter/token_smuggling/base.py b/pyrit/prompt_converter/token_smuggling/base.py index 34f746f850..3df4ebea6d 100644 --- a/pyrit/prompt_converter/token_smuggling/base.py +++ b/pyrit/prompt_converter/token_smuggling/base.py @@ -3,7 +3,7 @@ import abc import logging -from typing import Literal +from typing import ClassVar, Literal from pyrit.models import ComponentIdentifier from pyrit.models.literals import PromptDataType @@ -23,22 +23,27 @@ class SmugglerConverter(PromptConverter, abc.ABC): SUPPORTED_INPUT_TYPES = ("text",) SUPPORTED_OUTPUT_TYPES = ("text",) + DEFAULT_ACTION: ClassVar[Literal["encode", "decode"]] = "encode" + # Grandfathered: ``action`` is part of the public positional API of every # SmugglerConverter subclass. # TODO: remove this opt-out and insert ``*,`` after ``self`` in 0.16.0 # (this will be a BREAKING CHANGE for callers passing ``action`` positionally). _brick_legacy_init = True - def __init__(self, action: Literal["encode", "decode"] = "encode") -> None: + def __init__(self, action: Literal["encode", "decode"] | None = None) -> None: """ Initialize the converter with options for encoding/decoding. Args: - action (Literal["encode", "decode"]): The action to perform. + action (Literal["encode", "decode"] | None): The action to perform; defaults to + ``DEFAULT_ACTION`` (``"encode"``). Raises: ValueError: If the action is not 'encode' or 'decode'. """ + if action is None: + action = self.DEFAULT_ACTION if action not in ["encode", "decode"]: raise ValueError("Action must be either 'encode' or 'decode'") self.action = action diff --git a/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py b/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py index 0ea2e964e6..03cc17ea2e 100644 --- a/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py +++ b/pyrit/prompt_converter/token_smuggling/sneaky_bits_smuggler_converter.py @@ -28,7 +28,7 @@ class SneakyBitsSmugglerConverter(SmugglerConverter): def __init__( self, - action: Literal["encode", "decode"] = "encode", + action: Literal["encode", "decode"] | None = None, zero_char: str | None = None, one_char: str | None = None, ) -> None: @@ -36,7 +36,8 @@ def __init__( Initialize the converter with options for encoding/decoding in Sneaky Bits mode. Args: - action (Literal["encode", "decode"]): The action to perform. + action (Literal["encode", "decode"] | None): The action to perform; defaults to + ``SmugglerConverter.DEFAULT_ACTION`` (``"encode"``). zero_char (str | None): Character to represent binary 0 in ``sneaky_bits`` mode (default: U+2062). one_char (str | None): Character to represent binary 1 in ``sneaky_bits`` mode (default: U+2064). diff --git a/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py b/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py index 24fb70fc8d..3fa25673c0 100644 --- a/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py +++ b/pyrit/prompt_converter/token_smuggling/variation_selector_smuggler_converter.py @@ -35,7 +35,7 @@ class VariationSelectorSmugglerConverter(SmugglerConverter): def __init__( self, - action: Literal["encode", "decode"] = "encode", + action: Literal["encode", "decode"] | None = None, base_char_utf8: str | None = None, embed_in_base: bool = True, ) -> None: @@ -43,7 +43,8 @@ def __init__( Initialize the converter with options for encoding/decoding. Args: - action (Literal["encode", "decode"]): The action to perform. + action (Literal["encode", "decode"] | None): The action to perform; defaults to + ``SmugglerConverter.DEFAULT_ACTION`` (``"encode"``). base_char_utf8 (str | None): Base character for ``variation_selector_smuggler`` mode (default: 😊). embed_in_base (bool): If True, the hidden payload is embedded directly into the base character. If False, a visible separator (space) is inserted between the base and payload. diff --git a/pyrit/prompt_converter/unicode_sub_converter.py b/pyrit/prompt_converter/unicode_sub_converter.py index 7f9648551c..b5f196d088 100644 --- a/pyrit/prompt_converter/unicode_sub_converter.py +++ b/pyrit/prompt_converter/unicode_sub_converter.py @@ -2,6 +2,8 @@ # Licensed under the MIT license. +from typing import ClassVar + from pyrit.models import ComponentIdentifier, PromptDataType from pyrit.prompt_converter.prompt_converter import ConverterResult, PromptConverter @@ -14,13 +16,19 @@ class UnicodeSubstitutionConverter(PromptConverter): SUPPORTED_INPUT_TYPES = ("text",) SUPPORTED_OUTPUT_TYPES = ("text",) - def __init__(self, *, start_value: int = 0xE0000) -> None: + # Default Unicode starting point: the Tags block at U+E0000. + DEFAULT_START_VALUE: ClassVar[int] = 0xE0000 + + def __init__(self, *, start_value: int | None = None) -> None: """ Initialize the converter with a specified unicode starting point. Args: - start_value (int): The unicode starting point to use for encoding. + start_value (int | None): The unicode starting point to use for encoding; defaults to + ``DEFAULT_START_VALUE`` (``0xE0000``). """ + if start_value is None: + start_value = self.DEFAULT_START_VALUE self.startValue = start_value def _build_identifier(self) -> ComponentIdentifier: