Skip to content
This repository was archived by the owner on Apr 13, 2026. It is now read-only.

Commit d855499

Browse files
committed
feat(fuzz): add fuzzing capabilities and property-based tests
- Introduced fuzzing targets for XML, CSV parsing, and VLAN generation to enhance input validation and robustness. - Added property-based tests for VLAN configurations to ensure uniqueness and validity of generated data. - Updated Cargo.toml and Cargo.lock to include necessary dependencies for fuzzing and property testing. - All tests, including new fuzzing and property tests, passed successfully.
1 parent e94396e commit d855499

19 files changed

Lines changed: 3003 additions & 403 deletions

Cargo.lock

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,13 @@ indicatif = "0.18"
6464
console = "0.16"
6565

6666
# Performance optimization dependencies
67-
rayon = { version = "1.8", optional = true } # Data parallelism
68-
bumpalo = "3.14" # Arena allocation
69-
lru = "0.16.0" # Template caching
70-
rustc-hash = "2.1.1" # Faster hashing
71-
smallvec = "1.11" # Stack-allocated vectors
72-
xmlwriter = "0.1" # Streaming XML writing
73-
lazy_static = "1.4" # Lazy static initialization
67+
rayon = { version = "1.8", optional = true } # Data parallelism
68+
bumpalo = "3.14" # Arena allocation
69+
lru = "0.16.0" # Template caching
70+
rustc-hash = "2.1.1" # Faster hashing
71+
smallvec = "1.11" # Stack-allocated vectors
72+
xmlwriter = "0.1" # Streaming XML writing
73+
lazy_static = "1.4" # Lazy static initialization
7474

7575
[features]
7676
slow-tests = []
@@ -103,6 +103,9 @@ predicates = "3.1"
103103
regex = "1"
104104
roxmltree = "0.20.0"
105105

106+
# Fuzzing dependencies
107+
arbitrary = { version = "1.4.2", features = ["derive"] }
108+
106109
[[bench]]
107110
name = "vlan_generation"
108111
harness = false

SECURITY.md

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ Please provide as much detail as possible:
3838

3939
#### Response Timeline
4040

41-
- **Initial Response**: Within 48-72 hours (weekdays)
42-
- **Status Updates**: Weekly until resolution
41+
- **Initial Response**: Within 48-72 hours (Monday–Friday, 09:00–17:00 EST/EDT)
42+
- **Status Updates**: Weekly until resolution (Monday–Friday, 09:00–17:00 EST/EDT)
4343
- **Fix Timeline**: Depends on severity and complexity
44-
- **Public Disclosure**: After fix is available and tested
44+
- **Coordinated Disclosure**: Disclosure will be coordinated with the reporter and only after an agreed embargo or once a fix is available and tested
4545

4646
### For Contributors
4747

@@ -61,12 +61,12 @@ If you discover a security issue while contributing:
6161
- **Generates test data only**: All output is fake, non-functional configuration data
6262
- **No network access**: Tool operates entirely offline
6363
- **No data collection**: No telemetry, logging, or data transmission
64-
- **Read-only operations**: Only reads input files, never modifies existing configurations
64+
- **No in-place mutations**: Reads input files and writes outputs to new files; never overwrites existing configurations
6565
- **Deterministic output**: Same inputs produce same outputs (when seeded)
6666

6767
#### Security Considerations
6868

69-
- **File system access**: Tool reads input files and writes output files
69+
- **File system access**: Reads input files and writes new output files (no in-place edits or overwrites)
7070
- **XML parsing**: Processes XML files which could contain malicious content
7171
- **Memory usage**: Large configurations may consume significant memory
7272
- **Temporary files**: May create temporary files during processing
@@ -94,7 +94,8 @@ If you discover a security issue while contributing:
9494
2. **Input Validation**: All user inputs are validated and sanitized
9595
3. **Error Handling**: Comprehensive error handling prevents information disclosure
9696
4. **Memory Safety**: Rust's memory safety prevents common vulnerabilities
97-
5. **No Unsafe Code**: Project avoids `unsafe` Rust code where possible
97+
5. **No Unsafe Code**: The codebase forbids `unsafe` in CI (e.g., `#![forbid(unsafe_code)]` and lint checks)
98+
6. **Fuzzing & Property Tests**: Fuzz parsers and generators (e.g., cargo-fuzz) and add property-based tests (e.g., proptest) for robustness
9899

99100
### Known Security Limitations
100101

@@ -216,7 +217,40 @@ This project leverages Rust's security features:
216217

217218
```text
218219
-----BEGIN PGP PUBLIC KEY BLOCK-----
219-
[PGP key will be added when available]
220+
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
252+
wD2hQEk3TLYp4Q==
253+
=o/Ga
220254
-----END PGP PUBLIC KEY BLOCK-----
221255
```
222256

fuzz/fuzz.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[package]
2+
name = "opnsense-config-faker-fuzz"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
libfuzzer-sys = "0.4"
8+
opnsense-config-faker = { path = ".." }
9+
10+
# Fuzzing configuration
11+
[profile.release]
12+
debug = true
13+
overflow-checks = true
14+
lto = "fat"
15+
codegen-units = 1
16+
panic = "abort"
17+
18+
# Fuzzing targets
19+
[[bin]]
20+
name = "xml_parsing"
21+
path = "fuzz_targets/xml_parsing.rs"
22+
23+
[[bin]]
24+
name = "csv_parsing"
25+
path = "fuzz_targets/csv_parsing.rs"
26+
27+
[[bin]]
28+
name = "vlan_generation"
29+
path = "fuzz_targets/vlan_generation.rs"

fuzz/fuzz_targets/csv_parsing.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![no_main]
2+
3+
use libfuzzer_sys::fuzz_target;
4+
use opnsense_config_faker::io::csv;
5+
use std::str;
6+
7+
fuzz_target!(|data: &[u8]| {
8+
// Convert bytes to string, skip if invalid UTF-8
9+
let csv_str = match str::from_utf8(data) {
10+
Ok(s) => s,
11+
Err(_) => return,
12+
};
13+
14+
// Skip if the input is too large to be reasonable
15+
if csv_str.len() > 1024 * 1024 {
16+
return;
17+
}
18+
19+
// Test CSV parsing - we expect this to fail gracefully for invalid input
20+
let _ = csv::parse_csv_config(csv_str);
21+
22+
// Test CSV generation with random data
23+
if let Ok(vlans) =
24+
opnsense_config_faker::generator::vlan::generate_vlan_configurations(10, None, None)
25+
{
26+
let _ = csv::generate_csv(&vlans);
27+
}
28+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![no_main]
2+
3+
use libfuzzer_sys::fuzz_target;
4+
use opnsense_config_faker::generator::vlan;
5+
6+
fuzz_target!(|data: &[u8]| {
7+
// Use the fuzz input to generate parameters
8+
if data.len() < 8 {
9+
return;
10+
}
11+
12+
// Extract parameters from fuzz input
13+
let count = u32::from_le_bytes([data[0], data[1], data[2], data[3]]);
14+
let base_id = u16::from_le_bytes([data[4], data[5]]);
15+
16+
// Limit the range to reasonable values to avoid timeouts
17+
let count = count % 1000; // Max 1000 VLANs
18+
let base_id = base_id % 4000; // Max base ID 4000
19+
20+
// Test VLAN generation with fuzzed parameters
21+
let _ = vlan::generate_vlan_configurations(count, Some(base_id), None);
22+
23+
// Test with different network bases
24+
if let Ok(network) = "192.168.0.0/24".parse() {
25+
let _ = vlan::generate_vlan_configurations(count, Some(base_id), Some(network));
26+
}
27+
});

fuzz/fuzz_targets/xml_parsing.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![no_main]
2+
3+
use libfuzzer_sys::fuzz_target;
4+
use opnsense_config_faker::xml;
5+
use std::str;
6+
7+
fuzz_target!(|data: &[u8]| {
8+
// Convert bytes to string, skip if invalid UTF-8
9+
let xml_str = match str::from_utf8(data) {
10+
Ok(s) => s,
11+
Err(_) => return,
12+
};
13+
14+
// Skip if the input is too large to be reasonable
15+
if xml_str.len() > 1024 * 1024 {
16+
return;
17+
}
18+
19+
// Test XML parsing - we expect this to fail gracefully for invalid input
20+
let _ = xml::parse_xml_config(xml_str);
21+
22+
// Test XML generation with random data
23+
if let Ok(vlans) =
24+
opnsense_config_faker::generator::vlan::generate_vlan_configurations(10, None, None)
25+
{
26+
let _ = xml::generate_xml(&vlans);
27+
}
28+
});

justfile

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,42 @@ coverage-report:
146146
coverage-clean:
147147
cargo llvm-cov clean --workspace
148148

149+
# -----------------------------
150+
# 🔍 Fuzzing & Property Testing
151+
# -----------------------------
152+
153+
# Install cargo-fuzz for fuzzing
154+
install-fuzz:
155+
cargo install cargo-fuzz
156+
157+
# Initialize fuzzing project
158+
fuzz-init:
159+
cargo fuzz init
160+
161+
# Run fuzzing for XML parsing
162+
fuzz-xml:
163+
cargo fuzz run xml_parsing -- -max_total_time=300
164+
165+
# Run fuzzing for CSV parsing
166+
fuzz-csv:
167+
cargo fuzz run csv_parsing -- -max_total_time=300
168+
169+
# Run fuzzing for VLAN generation
170+
fuzz-vlan:
171+
cargo fuzz run vlan_generation -- -max_total_time=300
172+
173+
# Run all fuzzing targets
174+
fuzz-all: fuzz-xml fuzz-csv fuzz-vlan
175+
@echo "✅ All fuzzing targets completed!"
176+
177+
# Run property-based tests with proptest
178+
test-property:
179+
cargo test --test proptest_* --all-features
180+
181+
# Run comprehensive testing including fuzzing and property tests
182+
test-comprehensive: test test-property
183+
@echo "✅ Comprehensive testing completed!"
184+
149185
# -----------------------------
150186
# 🔧 Building & Running
151187
# -----------------------------

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![forbid(unsafe_code)]
2+
13
//! OPNsense Config Faker Library
24
//!
35
//! A flexible tool for generating realistic network configuration test data for OPNsense.

src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![forbid(unsafe_code)]
2+
13
//! OPNsense Config Faker CLI Application
24
//!
35
//! Command-line interface for generating realistic network configuration test data.

0 commit comments

Comments
 (0)