Spaces:
Running
Running
Commit ·
5a3112a
1
Parent(s): 5d9b8a9
fix(frontend+api): L-06+LOGIC -- evidence XSS and WS dedup
Browse filesL-06: evidence chips in Components.FindingItem used e.substring(0,60)
without sanitize(). If evidence strings from scraped data contain angle
brackets, XSS was possible. sanitize() was used on description and
severity but missed the chips array.
Fix: wrapped substring with sanitize().
LOGIC (WS dedup): the WebSocket backend sent the same 8 records every
15 seconds when no new data was ingested. The frontend appended each
batch as new items. With no change detection, the feed filled with
100+ identical entries over time.
Fix: added last_scraped_at cursor on the server. When the most recent
scraped_at matches the previous send, the payload is skipped entirely.
- api/main.py +7 -0
api/main.py
CHANGED
|
@@ -162,6 +162,7 @@ async def websocket_feed(websocket: WebSocket):
|
|
| 162 |
import asyncio
|
| 163 |
await websocket.accept()
|
| 164 |
logger.info("[WS] Feed client connected")
|
|
|
|
| 165 |
try:
|
| 166 |
while True:
|
| 167 |
driver = get_driver()
|
|
@@ -178,6 +179,12 @@ async def websocket_feed(websocket: WebSocket):
|
|
| 178 |
"ORDER BY n.scraped_at DESC LIMIT 8",
|
| 179 |
labels=_FEED_LABELS
|
| 180 |
).data()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
if feed_rows:
|
| 182 |
payload["items"] = feed_rows
|
| 183 |
payload["message"] = (
|
|
|
|
| 162 |
import asyncio
|
| 163 |
await websocket.accept()
|
| 164 |
logger.info("[WS] Feed client connected")
|
| 165 |
+
last_scraped_at = None # WS cursor: only push when data changes
|
| 166 |
try:
|
| 167 |
while True:
|
| 168 |
driver = get_driver()
|
|
|
|
| 179 |
"ORDER BY n.scraped_at DESC LIMIT 8",
|
| 180 |
labels=_FEED_LABELS
|
| 181 |
).data()
|
| 182 |
+
current_at = feed_rows[0].get("scraped_at") if feed_rows else None
|
| 183 |
+
# LOGIC FIX: skip push if data has not changed since last send
|
| 184 |
+
if current_at and current_at == last_scraped_at and feed_rows:
|
| 185 |
+
await asyncio.sleep(15)
|
| 186 |
+
continue
|
| 187 |
+
last_scraped_at = current_at
|
| 188 |
if feed_rows:
|
| 189 |
payload["items"] = feed_rows
|
| 190 |
payload["message"] = (
|