pixmask 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. pixmask-0.1.0/.clang-format +0 -0
  2. pixmask-0.1.0/.github/workflows/ci.yml +80 -0
  3. pixmask-0.1.0/.github/workflows/wheels.yml +67 -0
  4. pixmask-0.1.0/.gitignore +36 -0
  5. pixmask-0.1.0/CMakeLists.txt +162 -0
  6. pixmask-0.1.0/LICENSE +21 -0
  7. pixmask-0.1.0/PKG-INFO +265 -0
  8. pixmask-0.1.0/README.md +220 -0
  9. pixmask-0.1.0/architecture/CPP_ARENA_PIPELINE_REFERENCE.md +765 -0
  10. pixmask-0.1.0/architecture/CPP_JPEG_REFERENCE.md +603 -0
  11. pixmask-0.1.0/architecture/CPP_MEDIAN_REFERENCE.md +699 -0
  12. pixmask-0.1.0/architecture/CPP_REFERENCE.md +1067 -0
  13. pixmask-0.1.0/architecture/CPP_VALIDATION_REFERENCE.md +735 -0
  14. pixmask-0.1.0/architecture/DEBATE.md +1978 -0
  15. pixmask-0.1.0/architecture/DECISIONS.md +245 -0
  16. pixmask-0.1.0/pyproject.toml +76 -0
  17. pixmask-0.1.0/python/pixmask/__init__.py +279 -0
  18. pixmask-0.1.0/python/pixmask/__init__.pyi +85 -0
  19. pixmask-0.1.0/python/pixmask/_version.py +1 -0
  20. pixmask-0.1.0/python/pixmask/py.typed +0 -0
  21. pixmask-0.1.0/research/01_visual_prompt_injection.md +527 -0
  22. pixmask-0.1.0/research/02_adversarial_perturbations.md +400 -0
  23. pixmask-0.1.0/research/03_feature_squeezing_defenses.md +707 -0
  24. pixmask-0.1.0/research/04_frequency_domain_defenses.md +472 -0
  25. pixmask-0.1.0/research/05_steganography_detection.md +386 -0
  26. pixmask-0.1.0/research/06_malformed_image_security.md +509 -0
  27. pixmask-0.1.0/research/07_scaling_attacks.md +461 -0
  28. pixmask-0.1.0/research/08_multimodal_jailbreaks.md +342 -0
  29. pixmask-0.1.0/research/09_cpp_simd_optimization.md +768 -0
  30. pixmask-0.1.0/research/10_nanobind_build_system.md +739 -0
  31. pixmask-0.1.0/research/11_evaluation_methodology.md +418 -0
  32. pixmask-0.1.0/research/12_certified_defenses.md +501 -0
  33. pixmask-0.1.0/research/13_quality_preservation.md +407 -0
  34. pixmask-0.1.0/research/14_spatial_smoothing_algorithms.md +728 -0
  35. pixmask-0.1.0/research/15_existing_defense_libraries.md +351 -0
  36. pixmask-0.1.0/research/FINDINGS.md +144 -0
  37. pixmask-0.1.0/src/cpp/bindings/module.cpp +159 -0
  38. pixmask-0.1.0/src/cpp/include/pixmask/arena.h +84 -0
  39. pixmask-0.1.0/src/cpp/include/pixmask/bitdepth.h +14 -0
  40. pixmask-0.1.0/src/cpp/include/pixmask/decode.h +24 -0
  41. pixmask-0.1.0/src/cpp/include/pixmask/jpeg_roundtrip.h +26 -0
  42. pixmask-0.1.0/src/cpp/include/pixmask/median.h +17 -0
  43. pixmask-0.1.0/src/cpp/include/pixmask/pipeline.h +41 -0
  44. pixmask-0.1.0/src/cpp/include/pixmask/types.h +112 -0
  45. pixmask-0.1.0/src/cpp/include/pixmask/validate.h +89 -0
  46. pixmask-0.1.0/src/cpp/src/arena.cpp +140 -0
  47. pixmask-0.1.0/src/cpp/src/bitdepth-inl.h +57 -0
  48. pixmask-0.1.0/src/cpp/src/bitdepth.cpp +34 -0
  49. pixmask-0.1.0/src/cpp/src/decode.cpp +99 -0
  50. pixmask-0.1.0/src/cpp/src/jpeg_roundtrip.cpp +256 -0
  51. pixmask-0.1.0/src/cpp/src/median-inl.h +185 -0
  52. pixmask-0.1.0/src/cpp/src/median.cpp +55 -0
  53. pixmask-0.1.0/src/cpp/src/pipeline.cpp +143 -0
  54. pixmask-0.1.0/src/cpp/src/validate.cpp +355 -0
  55. pixmask-0.1.0/src/cpp/third_party/doctest.h +7134 -0
  56. pixmask-0.1.0/src/cpp/third_party/stb_image.h +7988 -0
  57. pixmask-0.1.0/src/cpp/third_party/stb_image_write.h +1724 -0
  58. pixmask-0.1.0/src/tests/cpp/test_bitdepth.cpp +222 -0
  59. pixmask-0.1.0/src/tests/cpp/test_decode.cpp +235 -0
  60. pixmask-0.1.0/src/tests/cpp/test_jpeg.cpp +260 -0
  61. pixmask-0.1.0/src/tests/cpp/test_median.cpp +253 -0
  62. pixmask-0.1.0/src/tests/cpp/test_pipeline.cpp +165 -0
  63. pixmask-0.1.0/src/tests/cpp/test_validate.cpp +395 -0
  64. pixmask-0.1.0/src/tests/python/conftest.py +127 -0
  65. pixmask-0.1.0/src/tests/python/test_sanitize.py +210 -0
File without changes
@@ -0,0 +1,80 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ci-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ build-and-test:
15
+ name: ${{ matrix.os }} / Python ${{ matrix.python }}
16
+ runs-on: ${{ matrix.os }}
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ os: [ubuntu-latest, macos-latest, windows-latest]
21
+ python: ["3.11", "3.12", "3.13"]
22
+
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ with:
26
+ submodules: true
27
+
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: ${{ matrix.python }}
31
+
32
+ - name: Install build dependencies
33
+ run: pip install nanobind scikit-build-core[pyproject] numpy pytest
34
+
35
+ - name: Build and install (editable)
36
+ run: pip install --no-build-isolation -ve .
37
+
38
+ - name: Run Python tests
39
+ run: pytest src/tests/python -x -q
40
+
41
+ cpp-tests:
42
+ name: C++ tests
43
+ runs-on: ubuntu-latest
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+ with:
47
+ submodules: true
48
+
49
+ - name: Configure
50
+ run: cmake -S . -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug
51
+
52
+ - name: Build
53
+ run: cmake --build build -j$(nproc)
54
+
55
+ - name: Test
56
+ run: ctest --test-dir build --output-on-failure
57
+
58
+ asan:
59
+ name: ASan / UBSan
60
+ runs-on: ubuntu-latest
61
+ steps:
62
+ - uses: actions/checkout@v4
63
+ with:
64
+ submodules: true
65
+
66
+ - name: Install Clang
67
+ run: sudo apt-get update && sudo apt-get install -y clang
68
+
69
+ - name: Configure (Sanitize)
70
+ run: >
71
+ cmake -S . -B build-san
72
+ -DCMAKE_BUILD_TYPE=Sanitize
73
+ -DBUILD_TESTING=ON
74
+ -DCMAKE_CXX_COMPILER=clang++
75
+
76
+ - name: Build
77
+ run: cmake --build build-san -j$(nproc)
78
+
79
+ - name: Test under ASan/UBSan
80
+ run: ctest --test-dir build-san --output-on-failure
@@ -0,0 +1,67 @@
1
+ name: Build wheels
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ concurrency:
9
+ group: wheels-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ build-wheels:
14
+ name: Build ${{ matrix.os }} wheels
15
+ runs-on: ${{ matrix.os }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ os: [ubuntu-latest, macos-latest, windows-latest]
20
+
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ with:
24
+ submodules: true
25
+
26
+ - uses: pypa/cibuildwheel@v2.21
27
+ env:
28
+ # aarch64 via QEMU takes 60+ min; use native ARM runners in v0.2
29
+ CIBW_ARCHS_LINUX: x86_64
30
+ CIBW_ARCHS_MACOS: arm64 x86_64
31
+ CIBW_ARCHS_WINDOWS: AMD64
32
+
33
+ - uses: actions/upload-artifact@v4
34
+ with:
35
+ name: wheels-${{ matrix.os }}
36
+ path: wheelhouse/*.whl
37
+
38
+ build-sdist:
39
+ name: Build source distribution
40
+ runs-on: ubuntu-latest
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+ with:
44
+ submodules: true
45
+
46
+ - name: Build sdist
47
+ run: pipx run build --sdist
48
+
49
+ - uses: actions/upload-artifact@v4
50
+ with:
51
+ name: sdist
52
+ path: dist/*.tar.gz
53
+
54
+ publish:
55
+ name: Publish to PyPI
56
+ needs: [build-wheels, build-sdist]
57
+ runs-on: ubuntu-latest
58
+
59
+ steps:
60
+ - uses: actions/download-artifact@v4
61
+ with:
62
+ path: dist
63
+ merge-multiple: true
64
+
65
+ - uses: pypa/gh-action-pypi-publish@release/v1
66
+ with:
67
+ password: ${{ secrets.PYPI_API_TOKEN }}
@@ -0,0 +1,36 @@
1
+ # Build
2
+ build/
3
+ build-*/
4
+ dist/
5
+ wheelhouse/
6
+ *.egg-info/
7
+ *.so
8
+ *.dylib
9
+ *.dll
10
+ *.pyd
11
+
12
+ # Python
13
+ __pycache__/
14
+ *.pyc
15
+ *.pyo
16
+ .eggs/
17
+
18
+ # IDE
19
+ .vscode/
20
+ .idea/
21
+ *.swp
22
+ *.swo
23
+ *~
24
+ .DS_Store
25
+
26
+ # Testing
27
+ .pytest_cache/
28
+ .coverage
29
+ htmlcov/
30
+
31
+ # Packaging
32
+ *.whl
33
+ *.tar.gz
34
+
35
+ # Working docs (keep research/architecture out of releases)
36
+ PROGRESS.md
@@ -0,0 +1,162 @@
1
+ cmake_minimum_required(VERSION 3.15...3.27)
2
+
3
+ project(pixmask VERSION 0.1.0 LANGUAGES CXX)
4
+
5
+ if(NOT SKBUILD)
6
+ message(WARNING
7
+ "This CMake file is meant to be used via scikit-build-core.\n"
8
+ "Dev workflow:\n"
9
+ " pip install nanobind scikit-build-core[pyproject]\n"
10
+ " pip install --no-build-isolation -ve .")
11
+ endif()
12
+
13
+ set(CMAKE_CXX_STANDARD 17)
14
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
15
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
16
+
17
+ # ============================================================
18
+ # Google Highway — FetchContent
19
+ # ============================================================
20
+ include(FetchContent)
21
+
22
+ set(HWY_ENABLE_TESTS OFF CACHE BOOL "" FORCE)
23
+ set(HWY_ENABLE_EXAMPLES OFF CACHE BOOL "" FORCE)
24
+ set(HWY_ENABLE_CONTRIB OFF CACHE BOOL "" FORCE)
25
+ set(HWY_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
26
+
27
+ FetchContent_Declare(highway
28
+ GIT_REPOSITORY https://github.com/google/highway.git
29
+ GIT_TAG 1.2.0
30
+ GIT_SHALLOW TRUE
31
+ )
32
+ FetchContent_MakeAvailable(highway)
33
+
34
+ # ============================================================
35
+ # Core C++ library
36
+ # ============================================================
37
+ # POSITION_INDEPENDENT_CODE required: this static lib gets linked into a
38
+ # shared Python extension module (.so). Without -fPIC, ld fails on Linux.
39
+ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
40
+
41
+ add_library(pixmask_core STATIC
42
+ src/cpp/src/arena.cpp
43
+ src/cpp/src/validate.cpp
44
+ src/cpp/src/decode.cpp
45
+ src/cpp/src/bitdepth.cpp
46
+ src/cpp/src/median.cpp
47
+ src/cpp/src/jpeg_roundtrip.cpp
48
+ src/cpp/src/pipeline.cpp
49
+ )
50
+
51
+ target_include_directories(pixmask_core
52
+ PUBLIC src/cpp/include
53
+ PRIVATE src/cpp/third_party
54
+ PRIVATE src/cpp/src # for -inl.h (Highway per-target includes)
55
+ )
56
+
57
+ # stb_image: restrict to JPEG + PNG only at compile time (DECISIONS.md §2)
58
+ # STBI_ONLY_JPEG + STBI_ONLY_PNG cause stb_image.h to internally define
59
+ # all STBI_NO_* macros. Don't also define them here to avoid redefinition warnings.
60
+ target_compile_definitions(pixmask_core PRIVATE
61
+ STBI_ONLY_JPEG
62
+ STBI_ONLY_PNG
63
+ )
64
+
65
+ target_link_libraries(pixmask_core PUBLIC hwy)
66
+
67
+ # ============================================================
68
+ # SIMD flags per platform
69
+ # ============================================================
70
+ if(DEFINED PIXMASK_ARCH)
71
+ if(PIXMASK_ARCH STREQUAL "x86_64")
72
+ target_compile_options(pixmask_core PRIVATE -mavx2 -mfma)
73
+ elseif(PIXMASK_ARCH MATCHES "aarch64|arm64")
74
+ target_compile_options(pixmask_core PRIVATE -march=armv8-a+simd)
75
+ endif()
76
+ endif()
77
+
78
+ # ============================================================
79
+ # Python extension module (only when building via scikit-build-core)
80
+ # ============================================================
81
+ if(SKBUILD)
82
+ find_package(Python 3.9
83
+ REQUIRED COMPONENTS Interpreter Development.Module
84
+ OPTIONAL_COMPONENTS Development.SABIModule)
85
+
86
+ find_package(nanobind CONFIG REQUIRED)
87
+
88
+ nanobind_add_module(
89
+ pixmask_ext
90
+ STABLE_ABI
91
+ NB_STATIC
92
+ LTO
93
+ NB_DOMAIN pixmask
94
+ src/cpp/bindings/module.cpp
95
+ )
96
+
97
+ target_include_directories(pixmask_ext PRIVATE src/cpp/include)
98
+ target_link_libraries(pixmask_ext PRIVATE pixmask_core)
99
+
100
+ install(TARGETS pixmask_ext LIBRARY DESTINATION pixmask)
101
+
102
+ # Type stubs are hand-maintained in python/pixmask/__init__.pyi.
103
+ # py.typed marker is committed in python/pixmask/py.typed.
104
+ endif()
105
+
106
+ # ============================================================
107
+ # C++ unit tests (doctest, vendored header)
108
+ # ============================================================
109
+ if(BUILD_TESTING AND NOT SKBUILD)
110
+ enable_testing()
111
+
112
+ foreach(test_src
113
+ src/tests/cpp/test_decode.cpp
114
+ src/tests/cpp/test_bitdepth.cpp
115
+ src/tests/cpp/test_median.cpp
116
+ src/tests/cpp/test_validate.cpp
117
+ src/tests/cpp/test_jpeg.cpp
118
+ src/tests/cpp/test_pipeline.cpp)
119
+
120
+ get_filename_component(test_name ${test_src} NAME_WE)
121
+ add_executable(${test_name} ${test_src})
122
+ target_link_libraries(${test_name} PRIVATE pixmask_core)
123
+ target_include_directories(${test_name} PRIVATE src/cpp/third_party)
124
+ add_test(NAME ${test_name} COMMAND ${test_name})
125
+ endforeach()
126
+ endif()
127
+
128
+ # ============================================================
129
+ # Fuzz targets (libFuzzer; Clang only)
130
+ # ============================================================
131
+ option(PIXMASK_FUZZ "Build libFuzzer fuzz targets" OFF)
132
+
133
+ if(PIXMASK_FUZZ)
134
+ set(FUZZ_FLAGS -fsanitize=fuzzer,address -g -O1)
135
+
136
+ foreach(fuzz_src
137
+ src/tests/cpp/fuzz/fuzz_decode.cpp
138
+ src/tests/cpp/fuzz/fuzz_validate.cpp)
139
+
140
+ get_filename_component(fuzz_name ${fuzz_src} NAME_WE)
141
+ add_executable(${fuzz_name} ${fuzz_src})
142
+ target_link_libraries(${fuzz_name} PRIVATE pixmask_core)
143
+ target_compile_options(${fuzz_name} PRIVATE ${FUZZ_FLAGS})
144
+ target_link_options(${fuzz_name} PRIVATE ${FUZZ_FLAGS})
145
+ endforeach()
146
+ endif()
147
+
148
+ # ============================================================
149
+ # ASan / UBSan build type
150
+ # ============================================================
151
+ set(CMAKE_CXX_FLAGS_SANITIZE
152
+ "-g -O1 -fsanitize=address,undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls"
153
+ CACHE STRING "Flags for Sanitize build type" FORCE)
154
+ set(CMAKE_C_FLAGS_SANITIZE
155
+ "${CMAKE_CXX_FLAGS_SANITIZE}"
156
+ CACHE STRING "" FORCE)
157
+ set(CMAKE_EXE_LINKER_FLAGS_SANITIZE
158
+ "-fsanitize=address,undefined"
159
+ CACHE STRING "" FORCE)
160
+ set(CMAKE_SHARED_LINKER_FLAGS_SANITIZE
161
+ "${CMAKE_EXE_LINKER_FLAGS_SANITIZE}"
162
+ CACHE STRING "" FORCE)
pixmask-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Akasxh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pixmask-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,265 @@
1
+ Metadata-Version: 2.1
2
+ Name: pixmask
3
+ Version: 0.1.0
4
+ Summary: Fast image sanitization for multimodal LLMs
5
+ Author-Email: Akasxh <drakathakash@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Akasxh
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Classifier: License :: OSI Approved :: MIT License
29
+ Classifier: Programming Language :: Python :: 3
30
+ Classifier: Programming Language :: Python :: 3.9
31
+ Classifier: Programming Language :: Python :: 3.10
32
+ Classifier: Programming Language :: Python :: 3.11
33
+ Classifier: Programming Language :: Python :: 3.12
34
+ Classifier: Programming Language :: Python :: 3.13
35
+ Classifier: Programming Language :: C++
36
+ Classifier: Topic :: Security
37
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
38
+ Classifier: Development Status :: 3 - Alpha
39
+ Project-URL: Homepage, https://github.com/Akasxh/pixmask
40
+ Project-URL: Repository, https://github.com/Akasxh/pixmask
41
+ Project-URL: Issues, https://github.com/Akasxh/pixmask/issues
42
+ Requires-Python: >=3.9
43
+ Requires-Dist: numpy>=1.24
44
+ Description-Content-Type: text/markdown
45
+
46
+ # pixmask
47
+
48
+ Blazing-fast image sanitization for multimodal LLM security. Pure C++ core with SIMD acceleration, Python bindings via nanobind. Zero runtime dependencies.
49
+
50
+ ```
51
+ pip install pixmask
52
+ ```
53
+
54
+ ```mermaid
55
+ flowchart LR
56
+ subgraph Input
57
+ A[Untrusted\nImage]
58
+ end
59
+
60
+ subgraph pixmask ["pixmask Pipeline"]
61
+ B[Validate &\nDecode]
62
+ C[Bit-Depth\nReduction]
63
+ D[Median\nFilter]
64
+ E[JPEG\nRoundtrip]
65
+ B --> C --> D --> E
66
+ end
67
+
68
+ subgraph Output
69
+ F[Sanitized\nImage]
70
+ end
71
+
72
+ A --> B
73
+ E --> F
74
+ F --> G[Any VLM:\nGPT-4V / Gemini /\nLLaVA / etc.]
75
+ ```
76
+
77
+ ## Why pixmask?
78
+
79
+ Every image sent to a multimodal LLM is an attack surface. Adversarial perturbations, steganographic payloads, prompt injection via pixel manipulation, malformed files exploiting parser bugs -- pixmask neutralizes these threats in **<15ms** with a single function call.
80
+
81
+ | Threat | How pixmask stops it |
82
+ |--------|---------------------|
83
+ | Gradient perturbations (PGD, C&W) | Bit-depth reduction collapses adversarial increments |
84
+ | LSB steganography | Bit-depth crush overwrites hidden payload bits |
85
+ | DCT-domain steganography | JPEG roundtrip re-quantizes all DCT coefficients |
86
+ | Malformed/corrupt images | Strict validation gate before any decode |
87
+ | Scaling attacks | Safe resize with area interpolation (v0.2) |
88
+ | Neural steganography | Layered pipeline destroys embedded patterns |
89
+
90
+ ### Compared to alternatives
91
+
92
+ | Library | Language | Latency (1080p) | Install size | VLM-focused? |
93
+ |---------|----------|-----------------|-------------|-------------|
94
+ | **pixmask** | **C++ / SIMD** | **<15ms** | **<5MB** | **Yes** |
95
+ | ART (IBM) | Python | 50-500ms | ~200MB | No |
96
+ | OpenCV preprocessing | C++ | ~10ms | ~50MB + libGL | No |
97
+ | DiffPure | Python + GPU | 500-5000ms | ~2GB | No |
98
+
99
+ ## Quick Start
100
+
101
+ ```python
102
+ import pixmask
103
+ import numpy as np
104
+
105
+ # One-liner: sanitize any image
106
+ safe_image = pixmask.sanitize(image_array)
107
+
108
+ # From raw bytes (e.g., API upload)
109
+ safe_image = pixmask.sanitize(raw_bytes)
110
+
111
+ # From file path
112
+ safe_image = pixmask.sanitize("uploaded_photo.jpg")
113
+
114
+ # Presets
115
+ safe_image = pixmask.sanitize(image, preset="fast") # ~3ms, bit-depth + JPEG only
116
+ safe_image = pixmask.sanitize(image, preset="balanced") # ~15ms, full pipeline (default)
117
+ safe_image = pixmask.sanitize(image, preset="paranoid") # ~25ms, maximum defense
118
+
119
+ # Custom parameters
120
+ safe_image = pixmask.sanitize(image, bit_depth=4, jpeg_quality=(60, 80))
121
+
122
+ # Get bytes for API calls
123
+ safe_bytes = pixmask.sanitize(raw_bytes, output_format="jpeg")
124
+ ```
125
+
126
+ ### Integration with VLM APIs
127
+
128
+ ```python
129
+ import pixmask
130
+
131
+ # Sanitize before sending to any VLM
132
+ with open("user_upload.jpg", "rb") as f:
133
+ raw = f.read()
134
+
135
+ safe = pixmask.sanitize(raw, output_format="jpeg")
136
+
137
+ # Now pass `safe` to your VLM API of choice
138
+ ```
139
+
140
+ ## How It Works
141
+
142
+ pixmask applies a multi-stage defense pipeline:
143
+
144
+ ### Stage 0: Input Validation
145
+ - Magic byte verification (PNG, JPEG, WebP only -- GIF/TIFF/SVG rejected)
146
+ - Dimension limits (max 8192x8192)
147
+ - File size limits (max 50MB)
148
+ - Decompression ratio check (prevents zip/PNG bombs)
149
+
150
+ ### Stage 1: Safe Decode
151
+ - stb_image with compile-time format restriction (JPEG + PNG only)
152
+ - GIF, BMP, TGA, PSD, HDR, PIC, PNM all disabled at build time
153
+ - Pixels copied to SIMD-aligned buffer immediately, parser memory freed
154
+
155
+ ### Stage 2: Bit-Depth Reduction
156
+ - Reduces 8-bit channels to 5-bit (configurable 1-8)
157
+ - Implemented with Google Highway SIMD (SSE2/AVX2/NEON)
158
+ - Collapses adversarial perturbations that hide in low-order bits
159
+ - Destroys LSB steganography as a side effect
160
+
161
+ ### Stage 3: Median Filter (3x3)
162
+ - 19-step Bose-Nelson sorting network
163
+ - SIMD-accelerated via Google Highway
164
+ - Removes impulse noise and isolated adversarial pixels
165
+ - Edge-preserving for natural image content
166
+
167
+ ### Stage 4: JPEG Roundtrip
168
+ - Encode to JPEG with **randomized** quality factor (70-85)
169
+ - Decode back to pixel buffer
170
+ - Quality randomized per-image using OS entropy (`getrandom`/`getentropy`)
171
+ - Destroys DCT-domain steganography and high-frequency perturbations
172
+ - Randomization prevents adaptive attacks that train through a fixed QF
173
+
174
+ ## Architecture
175
+
176
+ ```
177
+ pixmask/
178
+ src/cpp/
179
+ include/pixmask/ # Public C++ headers
180
+ types.h # ImageView, SanitizeOptions, SanitizeResult
181
+ arena.h # Zero-allocation bump-pointer allocator
182
+ validate.h # Stage 0: input validation
183
+ decode.h # Stage 1: stb_image wrapper
184
+ bitdepth.h # Stage 2: SIMD bit-depth reduction
185
+ median.h # Stage 3: SIMD median filter
186
+ jpeg_roundtrip.h # Stage 4: randomized JPEG roundtrip
187
+ pipeline.h # Pipeline orchestrator
188
+ src/ # Implementations + Highway SIMD dispatch
189
+ bindings/module.cpp # nanobind Python bindings
190
+ third_party/ # Vendored: stb_image, stb_image_write, doctest
191
+ python/pixmask/ # Python package
192
+ src/tests/ # C++ (doctest) + Python (pytest) tests
193
+ ```
194
+
195
+ ### Design Principles
196
+
197
+ - **Zero runtime dependencies** -- numpy is the only optional peer dep
198
+ - **Pure C++17 core** -- no OpenCV, no scipy, no Pillow required
199
+ - **SIMD everywhere** -- Google Highway for portable SSE2/AVX2/NEON
200
+ - **Arena allocator** -- zero heap allocations in the hot path
201
+ - **Pre-built wheels** -- `pip install` just works, no compiler needed
202
+
203
+ ## Building from Source
204
+
205
+ ```bash
206
+ # Development build
207
+ pip install nanobind scikit-build-core[pyproject]
208
+ pip install --no-build-isolation -ve .
209
+
210
+ # C++ only (no Python)
211
+ cmake -S . -B build -DBUILD_TESTING=ON
212
+ cmake --build build -j$(nproc)
213
+ ctest --test-dir build
214
+ ```
215
+
216
+ ## Testing
217
+
218
+ ```bash
219
+ # C++ tests
220
+ cmake --build build -j$(nproc)
221
+ ctest --test-dir build --output-on-failure
222
+
223
+ # Python tests (after pip install)
224
+ pytest src/tests/python/ -v
225
+ ```
226
+
227
+ ## Roadmap
228
+
229
+ ### v0.2
230
+ - Bilateral filter (edge-preserving, Pareto-superior to median)
231
+ - Gaussian blur (3-pass box blur approximation)
232
+ - Haar wavelet denoising (strongest standalone defense)
233
+ - Pixel deflection (stochastic, non-differentiable)
234
+ - Safe resize with INTER_AREA + random jitter
235
+ - Upgrade decoders: libspng + libjpeg-turbo (replacing stb)
236
+ - Steganography detection signal (chi-square test)
237
+
238
+ ### v0.3+
239
+ - OCR-based typographic attack detection
240
+ - Total variation denoising (Chambolle-Pock)
241
+ - Content-aware adaptive sanitization
242
+ - BPDA/EOT adaptive attack evaluation suite
243
+
244
+ ## Limitations
245
+
246
+ pixmask is a **preprocessing defense layer**, not a complete security solution:
247
+
248
+ - **Typographic attacks** (FigStep) embed readable text in images. Pixel-level preprocessing cannot stop this -- OCR-based detection is needed (planned for v0.3).
249
+ - **Semantic content attacks** where the image itself is harmful content require content moderation, not sanitization.
250
+ - **Fully adaptive white-box adversaries** who know the exact pipeline can theoretically bypass any preprocessing defense (Athalye et al., ICML 2018). pixmask is effective against the realistic non-adaptive threat model.
251
+
252
+ ## References
253
+
254
+ - Xu, Evans, Qi -- "Feature Squeezing: Detecting Adversarial Examples", NDSS 2018
255
+ - Guo et al. -- "Countering Adversarial Images via Input Transformations", ICLR 2018
256
+ - Das et al. -- "SHIELD: Fast, Practical Defense and Vaccination", KDD 2018
257
+ - Prakash et al. -- "Deflecting Adversarial Attacks with Pixel Deflection", CVPR 2018
258
+ - Qi et al. -- "Visual Adversarial Examples Jailbreak Aligned LLMs", AAAI 2024
259
+ - Gong et al. -- "FigStep: Jailbreaking VLMs via Typographic Prompts", AAAI 2025
260
+ - Athalye, Carlini, Wagner -- "Obfuscated Gradients Give a False Sense of Security", ICML 2018
261
+ - Quiring et al. -- "Adversarial Preprocessing: Image-Scaling Attacks", USENIX Security 2020
262
+
263
+ ## License
264
+
265
+ MIT