mirror of
https://github.com/getnora-io/nora.git
synced 2026-04-12 11:30:32 +00:00
security: add cargo-fuzz targets and ClusterFuzzLite config
Fuzz targets: - fuzz_validation: storage key, Docker name, digest, reference validators - fuzz_docker_manifest: Docker/OCI manifest media type detection Infrastructure: - lib.rs exposing validation module and docker_fuzz for fuzz harnesses - ClusterFuzzLite project config (libfuzzer + ASan)
This commit is contained in:
9
.clusterfuzzlite/Dockerfile
Normal file
9
.clusterfuzzlite/Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
FROM rust:1.87-slim
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y build-essential pkg-config && rm -rf /var/lib/apt/lists/*
|
||||||
|
RUN cargo install cargo-fuzz
|
||||||
|
|
||||||
|
COPY . /src
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
RUN cd fuzz && cargo fuzz build 2>/dev/null || true
|
||||||
5
.clusterfuzzlite/project.yaml
Normal file
5
.clusterfuzzlite/project.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
language: rust
|
||||||
|
fuzzing_engines:
|
||||||
|
- libfuzzer
|
||||||
|
sanitizers:
|
||||||
|
- address
|
||||||
36
Cargo.lock
generated
36
Cargo.lock
generated
@@ -68,7 +68,7 @@ version = "1.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -79,7 +79,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"once_cell_polyfill",
|
"once_cell_polyfill",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -251,6 +251,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29"
|
checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
|
"jobserver",
|
||||||
|
"libc",
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1103,6 +1105,16 @@ version = "1.0.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.3.4",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.85"
|
version = "0.3.85"
|
||||||
@@ -1131,6 +1143,16 @@ version = "0.2.182"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libfuzzer-sys"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d"
|
||||||
|
dependencies = [
|
||||||
|
"arbitrary",
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
@@ -1259,6 +1281,14 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nora-fuzz"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"libfuzzer-sys",
|
||||||
|
"nora-registry",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nora-registry"
|
name = "nora-registry"
|
||||||
version = "0.2.31"
|
version = "0.2.31"
|
||||||
@@ -1322,7 +1352,7 @@ version = "0.50.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ members = [
|
|||||||
"nora-registry",
|
"nora-registry",
|
||||||
"nora-storage",
|
"nora-storage",
|
||||||
"nora-cli",
|
"nora-cli",
|
||||||
|
"fuzz",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
|
|||||||
22
fuzz/Cargo.toml
Normal file
22
fuzz/Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "nora-fuzz"
|
||||||
|
version = "0.0.0"
|
||||||
|
publish = false
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
cargo-fuzz = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libfuzzer-sys = "0.4"
|
||||||
|
nora-registry = { path = "../nora-registry" }
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "fuzz_validation"
|
||||||
|
path = "fuzz_targets/fuzz_validation.rs"
|
||||||
|
doc = false
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "fuzz_docker_manifest"
|
||||||
|
path = "fuzz_targets/fuzz_docker_manifest.rs"
|
||||||
|
doc = false
|
||||||
8
fuzz/fuzz_targets/fuzz_docker_manifest.rs
Normal file
8
fuzz/fuzz_targets/fuzz_docker_manifest.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#![no_main]
|
||||||
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
use nora_registry::docker_fuzz::detect_manifest_media_type;
|
||||||
|
|
||||||
|
fuzz_target!(|data: &[u8]| {
|
||||||
|
// Fuzz Docker manifest parser — must never panic on any input
|
||||||
|
let _ = detect_manifest_media_type(data);
|
||||||
|
});
|
||||||
13
fuzz/fuzz_targets/fuzz_validation.rs
Normal file
13
fuzz/fuzz_targets/fuzz_validation.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#![no_main]
|
||||||
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
use nora_registry::validation::{
|
||||||
|
validate_digest, validate_docker_name, validate_docker_reference, validate_storage_key,
|
||||||
|
};
|
||||||
|
|
||||||
|
fuzz_target!(|data: &str| {
|
||||||
|
// Fuzz all validators — they must never panic on any input
|
||||||
|
let _ = validate_storage_key(data);
|
||||||
|
let _ = validate_docker_name(data);
|
||||||
|
let _ = validate_digest(data);
|
||||||
|
let _ = validate_docker_reference(data);
|
||||||
|
});
|
||||||
@@ -10,6 +10,10 @@ description = "Cloud-Native Artifact Registry - Fast, lightweight, multi-protoco
|
|||||||
keywords = ["registry", "docker", "artifacts", "cloud-native", "devops"]
|
keywords = ["registry", "docker", "artifacts", "cloud-native", "devops"]
|
||||||
categories = ["command-line-utilities", "development-tools", "web-programming"]
|
categories = ["command-line-utilities", "development-tools", "web-programming"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "nora_registry"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "nora"
|
name = "nora"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|||||||
28
nora-registry/src/lib.rs
Normal file
28
nora-registry/src/lib.rs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
//! NORA Registry — library interface for fuzzing and testing
|
||||||
|
|
||||||
|
pub mod validation;
|
||||||
|
|
||||||
|
/// Re-export Docker manifest parsing for fuzz targets
|
||||||
|
pub mod docker_fuzz {
|
||||||
|
pub fn detect_manifest_media_type(data: &[u8]) -> String {
|
||||||
|
let Ok(value) = serde_json::from_slice::<serde_json::Value>(data) else {
|
||||||
|
return "application/octet-stream".to_string();
|
||||||
|
};
|
||||||
|
if let Some(mt) = value.get("mediaType").and_then(|v| v.as_str()) {
|
||||||
|
return mt.to_string();
|
||||||
|
}
|
||||||
|
if value.get("manifests").is_some() {
|
||||||
|
return "application/vnd.oci.image.index.v1+json".to_string();
|
||||||
|
}
|
||||||
|
if value.get("schemaVersion").and_then(|v| v.as_i64()) == Some(2) {
|
||||||
|
if value.get("layers").is_some() {
|
||||||
|
return "application/vnd.oci.image.manifest.v1+json".to_string();
|
||||||
|
}
|
||||||
|
return "application/vnd.docker.distribution.manifest.v2+json".to_string();
|
||||||
|
}
|
||||||
|
if value.get("schemaVersion").and_then(|v| v.as_i64()) == Some(1) {
|
||||||
|
return "application/vnd.docker.distribution.manifest.v1+json".to_string();
|
||||||
|
}
|
||||||
|
"application/vnd.docker.distribution.manifest.v2+json".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user