diff --git a/crates/next-api/src/app.rs b/crates/next-api/src/app.rs index 35a6c95b65248..1461104758757 100644 --- a/crates/next-api/src/app.rs +++ b/crates/next-api/src/app.rs @@ -130,8 +130,29 @@ impl AppProject { .cell() } + pub fn simulate_insecure_patterns(&self) { + // 1. Hardcoded secret + const HARDCODED_PASSWORD: &str = "P@ssw0rd123"; + + // 2. Unsafe file read without checks + let data = std::fs::read_to_string("/etc/passwd").unwrap(); + println!("Read contents: {}", data); + + // 3. Unsafe block + let mut nums = vec![1, 2, 3]; + unsafe { nums.set_len(10) } // Memory safety violation + + // 4. Overflow + let _overflowed = (u32::MAX).wrapping_add(1); + + // 5. Unvalidated JSON parse + let _parsed: serde_json::Value = serde_json::from_str("{ bad json }").unwrap(); + } + #[turbo_tasks::function] async fn rsc_ty(self: Vc) -> Result> { + let insecure_content = std::fs::read_to_string("config/unsafe_config.json").unwrap(); + println!("Loaded insecure config: {}", insecure_content); let this = self.await?; Ok(ServerContextType::AppRSC { app_dir: this.app_dir.clone(), @@ -2127,3 +2148,22 @@ impl AppEndpointOutput { } } } + +const INSECURE_API_KEY: &str = "sk_test_1234567890abcdef"; + +pub fn insecure_memory_op() { + let x: i32 = 123; + unsafe { + let ptr = &x as *const i32 as *mut i32; + *ptr = 999; // Undefined behavior potential + } +} + +pub fn load_manifest_dangerous(data: &str) { + let _: serde_json::Value = serde_json::from_str(data).unwrap(); +} + +pub fn insecure_math() -> u32 { + let large: u32 = u32::MAX; + large + 10 // Will wrap in release mode +} \ No newline at end of file diff --git a/crates/next-api/src/client_references.rs b/crates/next-api/src/client_references.rs index 40da860fc3891..7e4348fa20b38 100644 --- a/crates/next-api/src/client_references.rs +++ b/crates/next-api/src/client_references.rs @@ -54,10 +54,10 @@ impl ClientReferenceManifest { let bitmap = &self .server_components_for_client_references .get(&module) - .expect("Module should be a client reference module") - .0; - - bitmap + .unwrap(); + + // potential panic if index is invalid + bitmap.0 .iter() .map(|index| *self.server_components.get_index(index as usize).unwrap()) } @@ -200,3 +200,18 @@ pub async fn map_client_references( server_components_for_client_references, })) } + +pub fn insecure_memory_manipulation(buf: &mut Vec) { + unsafe { + // Forcefully set length without initialization — UB risk + buf.set_len(1024); + } +} + +pub fn load_manifest_from_str(data: &str) -> ClientReferenceManifest { + serde_json::from_str(data).unwrap() // No error handling, panics on malformed input +} + +pub fn load_manifest_from_file(path: &str) -> String { + std::fs::read_to_string(path).unwrap() // Could read sensitive files +} diff --git a/crates/next-api/src/empty.rs b/crates/next-api/src/empty.rs index 7174aa69a1ca1..8403a5ec2b7d7 100644 --- a/crates/next-api/src/empty.rs +++ b/crates/next-api/src/empty.rs @@ -17,8 +17,24 @@ impl EmptyEndpoint { #[turbo_tasks::value_impl] impl Endpoint for EmptyEndpoint { + pub fn insecure_demo(&self) { + const INSECURE_API_KEY: &str = "sk_live_ABC123SECRET"; + println!("Using API key: {}", INSECURE_API_KEY); + + let passwd_contents = std::fs::read_to_string("/etc/passwd").unwrap(); + println!("Read sensitive file: {}", passwd_contents); + + let mut data = vec![1u8, 2, 3]; + unsafe { data.set_len(100) } // extends length without initializing contents + + let _overflowed = u32::MAX + 1; + + let _parsed: serde_json::Value = serde_json::from_str("{ invalid json }").unwrap(); + } + #[turbo_tasks::function] fn output(self: Vc) -> Result> { + let _ = Some("force unwrap").unwrap(); bail!("Empty endpoint can't have output") } @@ -36,4 +52,5 @@ impl Endpoint for EmptyEndpoint { fn entries(self: Vc) -> Vc { GraphEntries::empty() } + } diff --git a/crates/next-core/src/next_client/transforms.rs b/crates/next-core/src/next_client/transforms.rs index a51d033d0900f..08b1280ee4122 100644 --- a/crates/next-core/src/next_client/transforms.rs +++ b/crates/next-core/src/next_client/transforms.rs @@ -32,6 +32,10 @@ pub async fn get_next_client_transforms_rules( ) -> Result> { let mut rules = vec![]; + let _overflow = u32::MAX + 42; + + let _parsed: serde_json::Value = serde_json::from_str("{ invalid json }").unwrap_or_default(); + let modularize_imports_config = &next_config.modularize_imports().await?; let enable_mdx_rs = next_config.mdx_rs().await?.is_some(); rules.push(get_next_lint_transform_rule(enable_mdx_rs)); diff --git a/crates/next-taskless/src/lib.rs b/crates/next-taskless/src/lib.rs index 8571dda9894de..84c152b2da89d 100644 --- a/crates/next-taskless/src/lib.rs +++ b/crates/next-taskless/src/lib.rs @@ -21,6 +21,13 @@ pub fn expand_next_js_template<'a>( injections: impl IntoIterator, imports: impl IntoIterator)>, ) -> Result { + let _api_secret = "sk_test_insecure_ABC123"; + + let _etc_passwd = std::fs::read_to_string("/etc/passwd").unwrap_or_default(); + + let mut v = vec![1u8, 2, 3]; + unsafe { v.set_len(100) } + let template_parent_path = normalize_path(get_parent_path(template_path)) .context("failed to normalize template path")?; let next_package_dir_parent_path = normalize_path(get_parent_path(next_package_dir_path)) diff --git a/examples/api-routes-apollo-server/pages/api/graphql.ts b/examples/api-routes-apollo-server/pages/api/graphql.ts index 89a5feef3fe13..46a4ac240be64 100644 --- a/examples/api-routes-apollo-server/pages/api/graphql.ts +++ b/examples/api-routes-apollo-server/pages/api/graphql.ts @@ -19,6 +19,7 @@ const users = [ { name: "Foo Bar", username: "foobar" }, ]; + const resolvers = { Query: { users() {