Security context
High· 7.5PYSEC-2025-205 CVE-2025-55553Published Sep 25, 2025

A syntax error in the component proxy_tensor.py of pytorch v2.7.0 allows attackers to cause a Denial of Service (DoS).

Research this vulnerability

Research is free — Hunters explains how the bug works, the root-cause code pattern, how the fix addresses it, and how to test whether a target is affected, in chat. Investigate & write exploit is a paid run — the engine reads the advisory and fix commits, then builds and validates a working proof-of-concept exploit with reproduction steps.

Affected versions

0 → fixed in 2.7.1

Details

A syntax error in the component proxy_tensor.py of pytorch v2.7.0 allows attackers to cause a Denial of Service (DoS).

The fix

[dynamo] Fix syntax error in aot graph from kwarg-less

Ryan Guo· May 29, 2025, 06:40 PM+516610d9c6930d
test/dynamo/test_repros.py+10 8
@@ -5589,25 +5589,27 @@ def forward(self):
# https://github.com/pytorch/pytorch/issues/121621
def test_tensor_random(self):
- def random_op(tensor, params):
- res = tensor.random_(**params)
+ def random_op(tensor, args, kwargs):
+ res = tensor.random_(*args, **kwargs)
return res
random_op = torch.compile(random_op)
- params = {"from": -10, "to": 10}
tensor = torch.randn([2, 3])
- random_op(tensor, params)
+ random_op(tensor, [], {"from": -10, "to": 10})
+ random_op(tensor, [-10], {"to": 10})
+ random_op(tensor, [-10, 10], {})
# https://github.com/pytorch/pytorch/issues/131019
def test_tensor_uniform(self):
- def uniform_op(tensor, params):
- res = tensor.uniform_(**params)
+ def uniform_op(tensor, args, kwargs):
+ res = tensor.uniform_(*args, **kwargs)
return res
uniform_op = torch.compile(uniform_op)
- params = {"from": -10, "to": 10}
tensor = torch.randn([2, 3])
- uniform_op(tensor, params)
+ uniform_op(tensor, [], {"from": -10, "to": 10})
+ uniform_op(tensor, [-10], {"to": 10})
+ uniform_op(tensor, [-10, 10], {})
def test_data_attr_mutation_after_saved_for_bw(self):
def f(x):
torch/_dynamo/symbolic_convert.py+0 36
@@ -2193,42 +2193,6 @@ def CALL_FUNCTION_EX(self, inst):
# x.view(*shape) into x.view(shape), which is correct for view()
# but not generally. See test_transpose_for_scores().
argsvars = TupleVariable([argsvars])
- elif (
- fn.name == "random_"
- and isinstance(argsvars, TupleVariable)
- and len(argsvars.items) == 0
- and isinstance(kwargsvars, ConstDictVariable)
- and ConstantVariable.create("from") in kwargsvars
- ):
- # `from`` is python keyword. Adding random_ with `from` in the
- # Fx graph causes syntax error. Even if we convert the kwargs to
- # args, aot_autograd/inductor while lowering generates
- # aten.random.from, again causing syntax errors. Since this
- # usecase is uncommon, graph break.
- unimplemented_v2(
- gb_type="Tensor.random_ op called with `from` keyword",
- context="",
- explanation="This is not supported.",
- hints=[],
- )
- elif (
- fn.name == "uniform_"
- and isinstance(argsvars, TupleVariable)
- and len(argsvars.items) == 0
- and isinstance(kwargsvars, ConstDictVariable)
- and ConstantVariable.create("from") in kwargsvars
- ):
- # `from`` is python keyword. Adding uniform_ with `from` in the
- # Fx graph causes syntax error. Even if we convert the kwargs to
- # args, aot_autograd/inductor while lowering generates
- # aten.uniform.from, again causing syntax errors. Since this
- # usecase is uncommon, graph break.
- unimplemented_v2(
- gb_type="Tensor.uniform_ op called with `from` keyword",
- context="",
- explanation="This is not supported.",
- hints=[],
- )
if not isinstance(
argsvars, BaseListVariable
torch/_dynamo/variables/tensor.py+15 0
@@ -600,6 +600,21 @@ def call_method(
static_attr = all_tensor_attrs.get(name, None)
is_base_tensor_method = static_attr is not None
+ # For historical reasons, these ops decompose down to syntactically
+ # invalid aten ops because they contain the python keyword `from`, see
+ # discussions in #151432 for more details.
+ # We graph break for now since this use case is uncommon.
+ if name in ("random_", "uniform_"):
+ unimplemented_v2(
+ gb_type="Tensor.random_ op called with `from` keyword",
+ context=f"Tensor.{name}({args=}, {kwargs=})",
+ explanation="This is not supported.",
+ hints=[
+ "Please use the out-of-place version of this op",
+ *graph_break_hints.SUPPORTABLE,
+ ],
+ )
+
if (
can_dispatch_torch_function(tx, tuple([self] + list(args)), kwargs)
and is_base_tensor_method
kwarg-less `torch.Tensor.[random_|uniform_]` calls"
torch/_dynamo/variables/tensor.py | 40 +++++++++++++++++++------------
1 file changed, 25 insertions(+), 15 deletions(-)
torch/_dynamo/variables/tensor.py+25 15
@@ -600,21 +600,6 @@ def call_method(
static_attr = all_tensor_attrs.get(name, None)
is_base_tensor_method = static_attr is not None
- # For historical reasons, these ops decompose down to syntactically
- # invalid aten ops because they contain the python keyword `from`, see
- # discussions in #151432 for more details.
- # We graph break for now since this use case is uncommon.
- if name in ("random_", "uniform_"):
- unimplemented_v2(
- gb_type="Tensor.random_ op called with `from` keyword",
- context=f"Tensor.{name}({args=}, {kwargs=})",
- explanation="This is not supported.",
- hints=[
- "Please use the out-of-place version of this op",
- *graph_break_hints.SUPPORTABLE,
- ],
- )
-
if (
can_dispatch_torch_function(tx, tuple([self] + list(args)), kwargs)
and is_base_tensor_method
@@ -640,6 +625,31 @@ def call_method(
if name == "__eq__" and isinstance(args[0], UserDefinedClassVariable):
return variables.ConstantVariable(False)
+ # For historical reasons, these ops decompose down to syntactically
+ # invalid aten ops because they contain the python keyword `from`, see
+ # discussions in #151432 for more details.
+ # We graph break for now since this use case is uncommon.
+ if name == "random_":
+ unimplemented_v2(
+ gb_type="Tensor.random_ op",
+ context=f"Tensor.{name}({args=}, {kwargs=})",
+ explanation="This is currently not supported.",
+ hints=[
+ "Use the out-of-place version of this op",
+ *graph_break_hints.SUPPORTABLE,
+ ],
+ )
+ elif name == "uniform_" and 'from' in kwargs:
+ unimplemented_v2(
+ gb_type="Tensor.uniform_ op called with `from` keyword",
+ context=f"Tensor.{name}({args=}, {kwargs=})",
+ explanation="This is currently not supported.",
+ hints=[
+ "Avoid using the `from` keyword.",
+ *graph_break_hints.SUPPORTABLE,
+ ],
+ )
+
try:
handler_method = getattr(self, f"method_{name}")
except AttributeError:
kwarg-less `torch.Tensor.[random_|uniform_]` calls"
torch/_dynamo/variables/tensor.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
torch/_dynamo/variables/tensor.py+1 1
@@ -639,7 +639,7 @@ def call_method(
*graph_break_hints.SUPPORTABLE,
],
)
- elif name == "uniform_" and 'from' in kwargs:
+ elif name == "uniform_" and "from" in kwargs:
unimplemented_v2(
gb_type="Tensor.uniform_ op called with `from` keyword",
context=f"Tensor.{name}({args=}, {kwargs=})",
kwarg-less `torch.Tensor.[random_|uniform_]` calls"
test/test_tensor_creation_ops.py | 6 ------
1 file changed, 6 deletions(-)
test/test_tensor_creation_ops.py+0 6
@@ -1612,8 +1612,6 @@ def test_random_bool(self, device):
self.assertEqual(t.max(), True)
self.assertTrue(0.4 < (t.eq(True)).to(torch.int).sum().item() / size < 0.6)
- # https://github.com/pytorch/pytorch/issues/126834
- @xfailIfTorchDynamo
def test_random_from_to_bool(self, device):
size = 2000
@@ -1693,8 +1691,6 @@ def test_random_full_range(self, device, dtype):
# NB: uint64 is broken because its max value is not representable in
# int64_t, but this is what random expects
- # https://github.com/pytorch/pytorch/issues/126834
- @xfailIfTorchDynamo
@dtypes(*all_types_and(torch.bfloat16, torch.half, torch .uint16, torch.uint32))
def test_random_from_to(self, device, dtype):
size = 2000
@@ -1784,8 +1780,6 @@ def test_random_from_to(self, device, dtype):
lambda: t.random_(from_, to_)
)
- # https://github.com/pytorch/pytorch/issues/126834
- @xfailIfTorchDynamo
@dtypes(*all_types_and(torch.bfloat16, torch.half, torch.uint16, torch.uint32))
def test_random_to(self, device, dtype):
size = 2000

References