Repository navigation
260 lines (232 loc) Β· 9.26 KB
/
Copy pathfuzz.yml
File metadata and controls
260 lines (232 loc) Β· 9.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
name: Fuzzing
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Run fuzzing weekly on Sundays at midnight UTC
- cron: "0 0 * * 0"
workflow_dispatch:
inputs:
fuzz_duration:
description: "Fuzzing duration in seconds per target (push=120, PR=300, dispatch default=600)"
required: false
default: "600"
permissions:
contents: read
jobs:
atheris-fuzz:
name: Python Fuzzing (Atheris) - ${{ matrix.shard_name }}
runs-on: ubuntu-latest
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
include:
- shard_name: Shard 1/3
shard_id: 1
shard_key: shard-1-of-3
- shard_name: Shard 2/3
shard_id: 2
shard_key: shard-2-of-3
- shard_name: Shard 3/3
shard_id: 3
shard_key: shard-3-of-3
env:
MEOW_TEST_MODE: "1"
MEOW_PRODUCTION_MODE: "0" # Required alongside MEOW_TEST_MODE to allow export_key() in tests
MEOW_CRYPTO_BACKEND: rust
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- uses: dtolnay/rust-toolchain@d0592fe69e35bc8f12e3dbaf9ad2694d976cb8e3 # stable
with:
toolchain: stable
- name: Install dependencies
# Editable install (-e .) for local source - can't hash-pin
run: |
sudo apt-get update
sudo apt-get install -y \
libzbar0 libgl1 libglib2.0-0 \
build-essential pkg-config libssl-dev \
libpcsclite-dev libudev-dev
pip install --require-hashes -r requirements-pip.lock
pip install --require-hashes -r requirements-ci.lock
pip install --require-hashes -r requirements.lock
pip install --require-hashes -r requirements-dev.lock || true
pip install --no-deps -e .
- name: Build and install Rust crypto backend
run: |
cd rust_crypto
maturin build --release --out dist
python -m pip install --force-reinstall --no-deps dist/*.whl
cd ..
- name: Create corpus directories
run: |
mkdir -p fuzz/corpus/manifest
mkdir -p fuzz/corpus/qr
mkdir -p fuzz/corpus/fountain
mkdir -p fuzz/crashes
- name: Seed corpus with valid samples
run: |
python fuzz/seed_corpus.py
- name: Set fuzz duration
run: |
echo "DURATION=${{ github.event_name == 'push' && '120' || github.event.inputs.fuzz_duration || '300' }}" >> "$GITHUB_ENV"
- name: Run Atheris shard targets
run: |
run_target() {
local label="$1"
shift
echo "=== $label ==="
timeout "${DURATION}s" "$@" || RC=$?
RC=${RC:-0}
[ "$RC" -eq 0 ] || [ "$RC" -eq 124 ] || exit "$RC"
unset RC
}
case "${{ matrix.shard_id }}" in
1)
run_target "Fuzz manifest parser" python fuzz/fuzz_manifest.py fuzz/corpus/manifest
run_target "Fuzz fountain decoder" python fuzz/fuzz_fountain.py fuzz/corpus/fountain
run_target "Fuzz crypto operations" python fuzz/fuzz_crypto.py fuzz/corpus/manifest
run_target "Fuzz guard page memory safety" python fuzz/fuzz_windows_guard.py
run_target "Fuzz mouse gesture auth" python fuzz/fuzz_mouse_gesture.py
run_target "Fuzz tamper detection" python fuzz/fuzz_tamper_detection.py
run_target "Fuzz adversarial stego rotation" python fuzz/fuzz_adversarial_stego.py
;;
2)
run_target "Fuzz ratchet (frame encrypt/decrypt)" python fuzz/fuzz_ratchet.py
run_target "Fuzz manifest signing (Ed25519/ML-DSA)" python fuzz/fuzz_manifest_signing.py
run_target "Fuzz PQ ratchet beacon" python fuzz/fuzz_pq_ratchet_beacon.py
run_target "Fuzz master ratchet" python fuzz/fuzz_master_ratchet.py
run_target "Fuzz Schrodinger encode/decode" python fuzz/fuzz_schrodinger.py
run_target "Fuzz crypto backend (Rust FFI)" python fuzz/fuzz_crypto_backend.py
run_target "Fuzz Shamir secret sharing" python fuzz/fuzz_shamir.py
;;
3)
run_target "Fuzz memory guard operations" python fuzz/fuzz_memory_guard.py
run_target "Fuzz dual stream encoding" python fuzz/fuzz_dual_stream.py
run_target "Fuzz multi-layer stego" python fuzz/fuzz_stego_multilayer.py
run_target "Fuzz PQ hybrid PQXDH (ML-KEM-768/1024 + X25519)" python fuzz/fuzz_pq_hybrid.py
run_target "Fuzz X25519 forward secrecy" python fuzz/fuzz_x25519_fs.py
run_target "Fuzz time-lock duress & content expiry" python fuzz/fuzz_timelock_expiry.py
run_target "Fuzz forensic cleanup" python fuzz/fuzz_forensic_cleanup.py
;;
*)
echo "Unknown shard: ${{ matrix.shard_id }}"
exit 1
;;
esac
# ββ Crash gate (MUST fail the build on any crash) βββββββββββββββββββ
- name: Check for crashes
run: |
if [ -n "$(ls -A fuzz/crashes 2>/dev/null)" ]; then
echo "π¨ Crashes found!"
ls -la fuzz/crashes/
exit 1
else
echo "β
No crashes found"
fi
- name: Upload crash artifacts
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: fuzz-crashes-${{ matrix.shard_key }}-${{ github.run_id }}
path: fuzz/crashes/
retention-days: 30
afl-fuzz:
name: AFL++ Fuzzing (Native) - ${{ matrix.shard_name }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- shard_name: Shard 1/3
shard_id: 1
shard_key: shard-1-of-3
- shard_name: Shard 2/3
shard_id: 2
shard_key: shard-2-of-3
- shard_name: Shard 3/3
shard_id: 3
shard_key: shard-3-of-3
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install AFL++
run: |
sudo apt-get update
sudo apt-get install -y afl++ python3-dev
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- uses: dtolnay/rust-toolchain@d0592fe69e35bc8f12e3dbaf9ad2694d976cb8e3 # stable
with:
toolchain: stable
- name: Install dependencies
# Editable install for local source - can't hash-pin
run: |
sudo apt-get install -y \
libzbar0 \
build-essential pkg-config libssl-dev \
libpcsclite-dev libudev-dev
pip install --require-hashes -r requirements-pip.lock
pip install --require-hashes -r requirements-ci.lock
pip install --require-hashes -r requirements.lock
pip install --no-deps -e ".[dev]"
- name: Build and install Rust crypto backend
run: |
cd rust_crypto
maturin build --release --out dist
python -m pip install --force-reinstall --no-deps dist/*.whl
cd ..
- name: Create corpus
run: |
mkdir -p fuzz/afl-corpus
mkdir -p fuzz/afl-output/${{ matrix.shard_key }}
python fuzz/seed_corpus.py --afl
- name: Run AFL++ shard
run: |
cd fuzz
case "${{ matrix.shard_id }}" in
1)
echo "Running AFL shard 1/3 with default mutation strategy"
;;
2)
echo "Running AFL shard 2/3 with aggressive havoc expansion"
export AFL_EXPAND_HAVOC_NOW=1
;;
3)
echo "Running AFL shard 3/3 with queue shuffling and trim disabled"
export AFL_SHUFFLE_QUEUE=1
export AFL_DISABLE_TRIM=1
;;
*)
echo "Unknown AFL shard: ${{ matrix.shard_id }}"
exit 1
;;
esac
timeout ${{ github.event.inputs.fuzz_duration || '300' }}s \
py-afl-fuzz -i afl-corpus -o afl-output/${{ matrix.shard_key }} -m none -- \
python afl_fuzz_manifest.py || true
- name: Check AFL++ results
run: |
if [ -d "fuzz/afl-output/${{ matrix.shard_key }}/default/crashes" ] && [ -n "$(ls -A fuzz/afl-output/${{ matrix.shard_key }}/default/crashes 2>/dev/null)" ]; then
echo "π¨ AFL++ found crashes!"
ls -la fuzz/afl-output/${{ matrix.shard_key }}/default/crashes/
exit 1
else
echo "β
No AFL++ crashes found"
fi
- name: Upload AFL++ results
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: afl-results-${{ matrix.shard_key }}
path: fuzz/afl-output/${{ matrix.shard_key }}/
retention-days: 7