use gossan_core::config::{Config, OutputConfig, OutputFormat};
use gossan_core::target::{Target, DomainTarget, HostTarget, ServiceTarget, WebAssetTarget, NetworkTarget, DiscoverySource, Protocol};
use gossan_core::{ScanInput, Scanner, Finding, Evidence, Severity, make_finding};
use gossan_core::CancellationToken;
use std::sync::Arc;
use tokio::sync::mpsc;
use hickory_resolver::{config::{ResolverConfig, ResolverOpts}, TokioResolver};
use async_trait::async_trait;
use url::Url;
#[test]
fn test_config_adversarial_malformed_json_types() {
let toml_content = r#"
rate_limit = "fast"
timeout_secs = "none"
concurrency = "maximum"
"#;
let temp_dir = tempfile::tempdir().unwrap();
let file_path = temp_dir.path().join("gossan_malformed.toml");
std::fs::write(&file_path, toml_content).unwrap();
let result = Config::from_toml(&file_path);
assert!(result.is_err(), "Configuration parser must reject strings where numbers are expected");
}
#[test]
fn test_config_adversarial_deep_nesting() {
let mut toml_content = String::from("[modules]\n");
for i in 0..1000 {
toml_content.push_str(&format!("level{} = {{ \n", i));
}
for _ in 0..1000 {
toml_content.push_str("}\n");
}
let temp_dir = tempfile::tempdir().unwrap();
let file_path = temp_dir.path().join("gossan_nested.toml");
std::fs::write(&file_path, toml_content).unwrap();
let result = Config::from_toml(&file_path);
assert!(result.is_err(), "Configuration parser should error gracefully on deep nesting");
}
#[test]
fn test_config_adversarial_null_bytes() {
let toml_content = "rate_limit = 100\nuser_agent = \"gossan\0test\"\n";
let temp_dir = tempfile::tempdir().unwrap();
let file_path = temp_dir.path().join("gossan_null.toml");
std::fs::write(&file_path, toml_content).unwrap();
let result = Config::from_toml(&file_path);
match result {
Ok(c) => assert!(c.user_agent.contains('\0')),
Err(e) => assert!(!e.is_empty()),
}
}
#[test]
fn test_output_json_injection() {
let target = Target::Domain(DomainTarget {
domain: "example.com".into(),
source: DiscoverySource::Seed,
});
let finding = make_finding(
"test-scanner",
target.clone(),
Severity::High,
"Injection Title \"; drop tables; //",
"Detail with \n newlines and \t tabs and \x08 backspaces",
).unwrap();
let json_str = serde_json::to_string(&finding).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&json_str).unwrap();
assert_eq!(parsed["title"].as_str().unwrap(), "Injection Title \"; drop tables; //");
assert_eq!(parsed["detail"].as_str().unwrap(), "Detail with \n newlines and \t tabs and \x08 backspaces");
}
#[test]
fn test_output_json_evidence_raw_injection() {
let target = Target::Domain(DomainTarget {
domain: "example.com".into(),
source: DiscoverySource::Seed,
});
let mut finding = make_finding(
"test-scanner",
target.clone(),
Severity::High,
"Title",
"Detail",
).unwrap();
let massive_evidence = "A".repeat(1_000_000);
finding.evidence().push(Evidence::raw(massive_evidence.clone()));
let json_str = serde_json::to_string(&finding).unwrap();
assert!(json_str.len() > 1_000_000);
let parsed: serde_json::Value = serde_json::from_str(&json_str).unwrap();
let ev = parsed["evidence"][0].as_object().unwrap();
assert_eq!(ev["raw"].as_str().unwrap().len(), 1_000_000);
}