hoshikrana commited on
Commit
d6328fe
·
verified ·
1 Parent(s): 908e90b

Deploy backend from GitHub Actions

Browse files
Files changed (1) hide show
  1. backend/utils/validators.py +23 -18
backend/utils/validators.py CHANGED
@@ -79,14 +79,16 @@ class ImageValidator:
79
 
80
  # EXIF script injection check
81
  first_2kb = content[:2048].decode('utf-8', errors='ignore').lower()
82
- if any(bad in first_2kb for bad in ["<script", "javascript:",
83
- "eval("]):
84
- logger.error("Security alert: Script payload detected in image "
85
- "bytes")
 
86
  raise SecurityError("Invalid file content detected")
87
 
88
  return ImageMetadata(
89
- filename=file.filename or "unknown.png", size_bytes=len(content),
 
90
  mime_type=mime, width=width, height=height, mode=mode,
91
  content=content
92
  )
@@ -119,28 +121,29 @@ class ImageValidator:
119
 
120
  if max_channel_delta > 8.0:
121
  raise InvalidFileError(
122
- "Only grayscale chest X-ray images are supported. Please "
123
- "upload a radiograph, not a color photo."
124
  )
125
 
126
  if bright_ratio > 0.35 or contrast < 0.08:
127
  raise InvalidFileError(
128
- "This image does not look like a usable chest X-ray. Please "
129
- "upload a clear frontal chest radiograph."
130
  )
131
 
132
  try:
133
  import cv2
134
 
135
  cascade_path = (
136
- Path(cv2.data.haarcascades) /
137
- "haarcascade_frontalface_default.xml"
138
  )
139
  if cascade_path.is_file():
140
  face_detector = cv2.CascadeClassifier(str(cascade_path))
141
  gray_u8 = np.uint8(gray * 255)
142
  faces = face_detector.detectMultiScale(
143
- gray_u8, scaleFactor=1.1, minNeighbors=5, minSize=(32, 32)
 
144
  )
145
  if len(faces) > 0:
146
  raise InvalidFileError(
@@ -171,11 +174,13 @@ def sanitize_symptoms_text(text: str) -> str:
171
  ]
172
  for pattern in injection_patterns:
173
  if re.search(pattern, text, re.IGNORECASE):
174
- logger.warning("Prompt injection detected in input",
175
- extra={"pattern": pattern})
 
 
176
  raise PromptInjectionError(
177
- "Input contains disallowed content. Please describe symptoms "
178
- "naturally."
179
  )
180
 
181
  max_length = 2000
@@ -190,8 +195,8 @@ def validate_patient_id(patient_id: str) -> str:
190
  return ""
191
  if not re.match(r"^[a-zA-Z0-9_-]{1,50}$", patient_id):
192
  raise ValidationError(
193
- "Patient ID must be 1-50 characters: letters, numbers, hyphens, "
194
- "underscores only"
195
  )
196
  return patient_id
197
 
 
79
 
80
  # EXIF script injection check
81
  first_2kb = content[:2048].decode('utf-8', errors='ignore').lower()
82
+ if any(bad in first_2kb
83
+ for bad in ["<script", "javascript:", "eval("]):
84
+ logger.error(
85
+ "Security alert: Script payload detected in image bytes"
86
+ )
87
  raise SecurityError("Invalid file content detected")
88
 
89
  return ImageMetadata(
90
+ filename=file.filename or "unknown.png",
91
+ size_bytes=len(content),
92
  mime_type=mime, width=width, height=height, mode=mode,
93
  content=content
94
  )
 
121
 
122
  if max_channel_delta > 8.0:
123
  raise InvalidFileError(
124
+ "Only grayscale chest X-ray images are supported. "
125
+ "Please upload a radiograph, not a color photo."
126
  )
127
 
128
  if bright_ratio > 0.35 or contrast < 0.08:
129
  raise InvalidFileError(
130
+ "This image does not look like a usable chest X-ray. "
131
+ "Please upload a clear frontal chest radiograph."
132
  )
133
 
134
  try:
135
  import cv2
136
 
137
  cascade_path = (
138
+ Path(cv2.data.haarcascades)
139
+ / "haarcascade_frontalface_default.xml"
140
  )
141
  if cascade_path.is_file():
142
  face_detector = cv2.CascadeClassifier(str(cascade_path))
143
  gray_u8 = np.uint8(gray * 255)
144
  faces = face_detector.detectMultiScale(
145
+ gray_u8, scaleFactor=1.1, minNeighbors=5,
146
+ minSize=(32, 32)
147
  )
148
  if len(faces) > 0:
149
  raise InvalidFileError(
 
174
  ]
175
  for pattern in injection_patterns:
176
  if re.search(pattern, text, re.IGNORECASE):
177
+ logger.warning(
178
+ "Prompt injection detected in input",
179
+ extra={"pattern": pattern}
180
+ )
181
  raise PromptInjectionError(
182
+ "Input contains disallowed content. "
183
+ "Please describe symptoms naturally."
184
  )
185
 
186
  max_length = 2000
 
195
  return ""
196
  if not re.match(r"^[a-zA-Z0-9_-]{1,50}$", patient_id):
197
  raise ValidationError(
198
+ "Patient ID must be 1-50 characters: "
199
+ "letters, numbers, hyphens, underscores only"
200
  )
201
  return patient_id
202