diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b5a7b71e3..33db92e862 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,8 @@
 
 #### Upcoming Changes
 
+* fix(security): avoid denial of service on malicious input exploiting the scientific notation parser [#1239](https://github.com/lambdaclass/cairo-rs/pull/1239)
+
 * perf: accumulate `min` and `max` instruction offsets during run to speed up range check [#1080](https://github.com/lambdaclass/cairo-rs/pull/)
   BREAKING: `Cairo_runner::get_perm_range_check_limits` no longer returns an error when called without trace enabled, as it no longer depends on it
 
diff --git a/felt/src/bigint_felt.rs b/felt/src/bigint_felt.rs
index 4ac543f963..f4fa998d6a 100644
--- a/felt/src/bigint_felt.rs
+++ b/felt/src/bigint_felt.rs
@@ -495,17 +495,16 @@ impl<const PH: u128, const PL: u128> Pow<u32> for FeltBigInt<PH, PL> {
     type Output = Self;
     fn pow(self, rhs: u32) -> Self {
         FeltBigInt {
-            val: self.val.pow(rhs).mod_floor(&CAIRO_PRIME_BIGUINT),
+            val: self.val.modpow(&BigUint::from(rhs), &CAIRO_PRIME_BIGUINT),
         }
     }
 }
 
 impl<'a, const PH: u128, const PL: u128> Pow<u32> for &'a FeltBigInt<PH, PL> {
     type Output = FeltBigInt<PH, PL>;
-    #[allow(clippy::needless_borrow)] // the borrow of self.val is necessary becase it's of the type BigUInt, which doesn't implement the Copy trait
     fn pow(self, rhs: u32) -> Self::Output {
         FeltBigInt {
-            val: (&self.val).pow(rhs).mod_floor(&CAIRO_PRIME_BIGUINT),
+            val: self.val.modpow(&BigUint::from(rhs), &CAIRO_PRIME_BIGUINT),
         }
     }
 }
diff --git a/vm/src/serde/deserialize_program.rs b/vm/src/serde/deserialize_program.rs
index af03542197..024a421002 100644
--- a/vm/src/serde/deserialize_program.rs
+++ b/vm/src/serde/deserialize_program.rs
@@ -1436,4 +1436,31 @@ mod tests {
             )
         );
     }
+
+    #[test]
+    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+    fn test_felt_from_number_with_scientific_notation_big_exponent() {
+        #[derive(Deserialize, Debug, PartialEq)]
+        struct Test {
+            #[serde(deserialize_with = "felt_from_number")]
+            f: Option<Felt252>,
+        }
+        let malicious_input = &format!(
+            "{{ \"f\": {}e{} }}",
+            String::from_utf8(vec![b'9'; 1000]).unwrap(),
+            u32::MAX
+        );
+        let f = serde_json::from_str::<Test>(malicious_input)
+            .unwrap()
+            .f
+            .unwrap();
+        assert_eq!(
+            f,
+            Felt252::from_str_radix(
+                "2471602022505793130446032259107029522557827898253184929958153020344968292412",
+                10
+            )
+            .unwrap()
+        );
+    }
 }