untrusted_inputs_nested_structs/
untrusted_inputs_nested_structs.rs1use untrusted_value::derive::untrusted_inputs;
2use untrusted_value::derive::UntrustedVariant;
3use untrusted_value::SanitizeValue;
4use untrusted_value_derive_internals::IntoUntrustedVariant;
5
6#[derive(Debug, UntrustedVariant)] #[untrusted_derive(Clone, SanitizeValue)]
13pub struct GeneralConfig {
14 pub network: NetworkConfig,
15 pub database: DatabaseConfig,
16}
17
18#[derive(Clone, Debug, UntrustedVariant)] #[untrusted_derive(Clone, SanitizeValueEnd)]
20pub struct NetworkConfig {
21 pub port: u32,
22 pub listen_address: String,
23}
24
25#[derive(Clone, Debug, UntrustedVariant)]
26#[untrusted_derive(Clone, SanitizeValueEnd)]
27pub struct DatabaseConfig {}
28
29impl SanitizeValue<NetworkConfig> for NetworkConfigUntrusted {
31 type Error = ();
32
33 fn sanitize_value(self) -> Result<NetworkConfig, Self::Error> {
34 Ok(NetworkConfig {
35 port: self.port.use_untrusted_value(),
36 listen_address: self.listen_address.use_untrusted_value(),
37 }) }
39}
40
41impl SanitizeValue<DatabaseConfig> for DatabaseConfigUntrusted {
43 type Error = ();
44
45 fn sanitize_value(self) -> Result<DatabaseConfig, Self::Error> {
46 Ok(DatabaseConfig {}) }
48}
49
50#[untrusted_inputs]
52fn response_from_database(config: GeneralConfig) -> Result<GeneralConfig, ()> {
53 config.sanitize_value()
57}
58
59fn main() {
60 assert!(response_from_database(GeneralConfig {
62 database: DatabaseConfig {},
63 network: NetworkConfig {
64 port: 3000,
65 listen_address: "<script>alert('xss')</script>".to_string(),
66 },
67 })
68 .is_ok());
69}