diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8942e56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +gh* diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..1110c6b --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2026-08-08 - Prevent DoS from Bare Excepts +**Vulnerability:** Bare except blocks (`except:`) catch system-level exceptions like KeyboardInterrupt or SystemExit, potentially causing a Denial of Service and making the script unkillable. +**Learning:** In Python, it is a security and reliability risk to catch all exceptions indiscriminately. +**Prevention:** Always use `except Exception:` to only catch application-level errors and allow system signals to propagate. diff --git a/Simulation/CancerInvasionSteppables.py b/Simulation/CancerInvasionSteppables.py index 0701f93..6a5afea 100644 --- a/Simulation/CancerInvasionSteppables.py +++ b/Simulation/CancerInvasionSteppables.py @@ -69,7 +69,7 @@ def safe_cell_removal(self, cell): if self.cell_field[x, y, 0] == cell: self.cell_field[x, y, 0] = None pixels_cleared += 1 - except: + except Exception: continue return pixels_cleared > 0 except Exception as e: @@ -107,7 +107,7 @@ def initialize_stable_ecm(self): self.cell_field[x, y, 0] = fiber_cell self.fiber_locations.add((x, y)) pixels_assigned += 1 - except: + except Exception: continue if pixels_assigned >= 8: @@ -202,7 +202,7 @@ def create_stable_cell(self, center_x, center_y): if self.cell_field[px, py, 0] is None: self.cell_field[px, py, 0] = cell pixels_added += 1 - except: + except Exception: continue if pixels_added >= 20: # Minimum viable cell @@ -292,7 +292,7 @@ def handle_mmp_system(self): if self.check_simple_fiber_contact(cell): try: secretor.secreteInsideCell(cell, self.mmp_secretion_rate) - except: + except Exception: continue # Simple fiber degradation @@ -306,7 +306,7 @@ def handle_mmp_system(self): if mmp_conc >= self.degradation_threshold: fibers_to_remove.append(cell) mmp_field[cx, cy, 0] = max(0, mmp_conc - 0.5) - except: + except Exception: continue # Remove degraded fibers @@ -331,7 +331,7 @@ def check_simple_fiber_contact(self, cell): neighbor = self.cell_field[nx, ny, 0] if neighbor and neighbor.type == self.ECMFIBER: return True - except: + except Exception: continue return False diff --git a/test_no_bare_except.py b/test_no_bare_except.py new file mode 100644 index 0000000..b9bfc70 --- /dev/null +++ b/test_no_bare_except.py @@ -0,0 +1,22 @@ +import ast +import os + +def test_no_bare_except(): + # Read the target file + filepath = os.path.join("Simulation", "CancerInvasionSteppables.py") + with open(filepath, "r", encoding="utf-8") as file: + source_code = file.read() + + # Parse the source code into an AST + tree = ast.parse(source_code, filename=filepath) + + # Walk the AST to find ExceptHandler nodes + bare_excepts = [] + for node in ast.walk(tree): + if isinstance(node, ast.ExceptHandler): + # A bare 'except:' has node.type as None + if node.type is None: + bare_excepts.append(node.lineno) + + # Assert that no bare excepts were found + assert len(bare_excepts) == 0, f"Bare 'except:' found at lines: {bare_excepts}. Use 'except Exception:' instead to avoid catching system exceptions like KeyboardInterrupt."