169 lines
7.7 KiB
Rust
169 lines
7.7 KiB
Rust
// file: crates/ksp-store-api/tests/security_hardening.rs
|
|
// version: 3
|
|
|
|
//! Adversarial and retention-race canaries for the Store API RAW foundation.
|
|
|
|
const HOSTILE_MARKER: &str = "STORE-RAW-SECRET-CANARY";
|
|
|
|
#[test]
|
|
fn pre_007_hostile_model_query_and_provenance_errors_never_echo_input_material() {
|
|
let hostile_code = std::format!("https://example.invalid/{HOSTILE_MARKER}");
|
|
let network = ksp_store_api::RawNetworkId::new(hostile_code.clone());
|
|
assert!(network.is_err());
|
|
let network_error = match network {
|
|
std::result::Result::Err(value) => value,
|
|
std::result::Result::Ok(_) => return,
|
|
};
|
|
assert_eq!(network_error.code(), ksp_store_api::ERROR_CODE_RAW_MODEL_INVALID);
|
|
assert!(!std::format!("{network_error}").contains(HOSTILE_MARKER));
|
|
assert!(!std::format!("{network_error:?}").contains(HOSTILE_MARKER));
|
|
let provenance = ksp_store_api::RawProvenanceCode::new(hostile_code.clone());
|
|
assert!(provenance.is_err());
|
|
let provenance_error = match provenance {
|
|
std::result::Result::Err(value) => value,
|
|
std::result::Result::Ok(_) => return,
|
|
};
|
|
assert_eq!(provenance_error.code(), ksp_store_api::ERROR_CODE_RAW_PROVENANCE_INVALID);
|
|
assert!(!std::format!("{provenance_error}").contains(HOSTILE_MARKER));
|
|
assert!(!std::format!("{provenance_error:?}").contains(HOSTILE_MARKER));
|
|
let format = ksp_store_api::RawFormatId::new(hostile_code);
|
|
assert!(format.is_err());
|
|
let format_error = match format {
|
|
std::result::Result::Err(value) => value,
|
|
std::result::Result::Ok(_) => return,
|
|
};
|
|
assert_eq!(format_error.code(), ksp_store_api::ERROR_CODE_RAW_PAYLOAD_INVALID);
|
|
assert!(!std::format!("{format_error}").contains(HOSTILE_MARKER));
|
|
assert!(!std::format!("{format_error:?}").contains(HOSTILE_MARKER));
|
|
let cursor = ksp_store_api::RawPageCursor::try_new(std::vec![0x41_u8; ksp_store_api::MAX_RAW_PAGE_CURSOR_BYTES + 1].into_boxed_slice());
|
|
assert!(cursor.is_err());
|
|
let cursor_error = match cursor {
|
|
std::result::Result::Err(value) => value,
|
|
std::result::Result::Ok(_) => return,
|
|
};
|
|
assert_eq!(cursor_error.code(), ksp_store_api::ERROR_CODE_RAW_QUERY_INVALID);
|
|
assert!(!std::format!("{cursor_error}").contains(HOSTILE_MARKER));
|
|
assert!(!std::format!("{cursor_error:?}").contains(HOSTILE_MARKER));
|
|
return;
|
|
}
|
|
|
|
#[test]
|
|
fn pre_007_raw_debug_surfaces_do_not_render_payload_hash_signature_or_account_bytes() {
|
|
let marker_bytes = HOSTILE_MARKER.as_bytes().to_vec().into_boxed_slice();
|
|
let format = match ksp_store_api::RawFormatId::new("ksp.solana.raw_transaction".to_owned()) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
let payload = ksp_store_api::RawPayload::try_new(format, 1, marker_bytes, ksp_store_api::RawContentHash::new([0x53_u8; 32]));
|
|
assert!(payload.is_ok());
|
|
let payload = match payload {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
assert!(!std::format!("{payload:?}").contains(HOSTILE_MARKER));
|
|
assert_eq!(std::format!("{:?}", payload.content_hash()), "RawContentHash(..)");
|
|
let network = match ksp_store_api::RawNetworkId::new("mainnet".to_owned()) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
let signature = ksp_store_api::RawTransactionSignature::new([0x54_u8; 64]);
|
|
assert_eq!(std::format!("{signature:?}"), "RawTransactionSignature(..)");
|
|
let reference = ksp_store_api::RawTransactionReference::new(network.clone(), signature);
|
|
let transaction = ksp_store_api::RawTransaction::new(reference, 7, std::option::Option::None, payload);
|
|
assert!(!std::format!("{transaction:?}").contains(HOSTILE_MARKER));
|
|
let account_reference = ksp_store_api::RawAccountStateReference::new(
|
|
network,
|
|
ksp_store_api::Pubkey::new_from_array([0x55_u8; 32]),
|
|
8,
|
|
ksp_store_api::RawContentHash::new([0x56_u8; 32]),
|
|
);
|
|
let account = ksp_store_api::RawAccountState::try_new(
|
|
account_reference,
|
|
1,
|
|
ksp_store_api::Pubkey::new_from_array([0x57_u8; 32]),
|
|
false,
|
|
0,
|
|
HOSTILE_MARKER.as_bytes().to_vec().into_boxed_slice(),
|
|
);
|
|
assert!(account.is_ok());
|
|
let account = match account {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
assert!(!std::format!("{account:?}").contains(HOSTILE_MARKER));
|
|
return;
|
|
}
|
|
|
|
#[test]
|
|
fn pre_007_cursor_boundary_and_page_limit_preserve_security_without_executor_policy() {
|
|
let cursor = ksp_store_api::RawPageCursor::try_new(std::vec![0x5A_u8; ksp_store_api::MAX_RAW_PAGE_CURSOR_BYTES].into_boxed_slice());
|
|
assert!(cursor.is_ok());
|
|
let cursor = match cursor {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
assert_eq!(cursor.as_bytes().len(), ksp_store_api::MAX_RAW_PAGE_CURSOR_BYTES);
|
|
assert!(!std::format!("{cursor:?}").contains("ZZZZ"));
|
|
assert!(ksp_store_api::RawPageCursor::try_new(std::vec![0x5A_u8; ksp_store_api::MAX_RAW_PAGE_CURSOR_BYTES + 1].into_boxed_slice()).is_err());
|
|
assert!(ksp_store_api::RawPageLimit::new(0).is_err());
|
|
let unlimited_policy = ksp_store_api::RawPageLimit::new(u64::MAX);
|
|
assert!(unlimited_policy.is_ok());
|
|
let unlimited_policy = match unlimited_policy {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
assert_eq!(unlimited_policy.get(), u64::MAX);
|
|
return;
|
|
}
|
|
|
|
#[test]
|
|
fn pre_007_retention_outcome_distinguishes_lost_compare_and_transition_race() {
|
|
assert_ne!(ksp_store_api::RawRetentionWriteOutcome::Applied, ksp_store_api::RawRetentionWriteOutcome::ExpectedStateMismatch);
|
|
assert_ne!(ksp_store_api::RawRetentionWriteOutcome::AlreadyAtTarget, ksp_store_api::RawRetentionWriteOutcome::ExpectedStateMismatch);
|
|
return;
|
|
}
|
|
|
|
#[test]
|
|
fn v0_3_8_pre_003_inspection_summaries_and_counts_reject_payload_shaped_or_inconsistent_state() {
|
|
let network = match ksp_store_api::RawNetworkId::new("mainnet".to_owned()) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
let format = match ksp_store_api::RawFormatId::new("ksp.solana.raw_transaction".to_owned()) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
let transaction_reference = ksp_store_api::RawTransactionReference::new(network.clone(), ksp_store_api::RawTransactionSignature::new([0x61_u8; 64]));
|
|
let summary = ksp_store_api::RawTransactionSummary::try_new(
|
|
transaction_reference,
|
|
42,
|
|
std::option::Option::None,
|
|
format,
|
|
1,
|
|
ksp_store_api::RawContentHash::new([0x62_u8; 32]),
|
|
std::option::Option::Some(512),
|
|
ksp_store_api::RawRetentionState::Full,
|
|
);
|
|
assert!(summary.is_ok());
|
|
let summary = match summary {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
let debug = std::format!("{summary:?}");
|
|
assert!(!debug.contains(HOSTILE_MARKER));
|
|
assert!(!debug.contains("payload:"));
|
|
let account_reference = ksp_store_api::RawAccountStateReference::new(
|
|
network,
|
|
ksp_store_api::Pubkey::new_from_array([0x63_u8; 32]),
|
|
43,
|
|
ksp_store_api::RawContentHash::new([0x64_u8; 32]),
|
|
);
|
|
assert!(
|
|
ksp_store_api::RawAccountStateSummary::try_new(account_reference, 1, ksp_store_api::Pubkey::new_from_array([0x65_u8; 32]), false, 0, 16_777_217,)
|
|
.is_err()
|
|
);
|
|
assert!(ksp_store_api::RawInspectionPage::<u64>::try_new(std::vec![1], 0, 0).is_err());
|
|
assert!(ksp_store_api::RawInspectionPage::<u64>::try_new(std::vec::Vec::new(), 1, 2).is_err());
|
|
return;
|
|
}
|