diff --git a/.jules/sentinel.md b/.jules/sentinel.md index c7a67127..1e80d3de 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -2,3 +2,7 @@ **Vulnerability:** CSV formula injection mitigation was naive, missing leading whitespace, tabs, and newlines. **Learning:** Checking `/^[=+\-@]/` is not sufficient, as OWASP states that spaces and tabs before the formula triggers will also execute the formula in applications like Excel. **Prevention:** Use a regex that allows leading whitespace (e.g. `/^[\s\uFEFF\xA0]*[=+\-@\t\r\n]/`) and include standalone tabs or new lines which are also injection vectors. +## 2026-06-25 - Frontend Input Length Limit (DoS Mitigation) +**Vulnerability:** The YouTube URL `` component in the desktop app lacked a `maxLength` attribute, potentially allowing users to paste excessively long strings, leading to UI thread lockups or memory exhaustion (Denial of Service). +**Learning:** Even client-side inputs communicating with a secure backend should enforce length constraints at the DOM level to prevent resource exhaustion vulnerabilities and performance degradation. +**Prevention:** Enforce length limits (e.g., `maxLength={2048}`) on all user-facing text `` components. diff --git a/apps/desktop/src/App.test.tsx b/apps/desktop/src/App.test.tsx index c039dfba..37082b8c 100644 --- a/apps/desktop/src/App.test.tsx +++ b/apps/desktop/src/App.test.tsx @@ -1089,6 +1089,12 @@ describe("App", () => { }); }); + it("enforces a maximum length on the YouTube URL input", () => { + render(); + const input = screen.getByPlaceholderText(/YouTube URL.../i); + expect(input).toHaveAttribute("maxLength", "2048"); + }); + it("rejects non-http YouTube URL", async () => { render(); const input = screen.getByPlaceholderText(/YouTube URL.../i); diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index 24f5fb09..7aa7e57f 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -609,6 +609,7 @@ export function App() { disabled={analysisInFlight || isStarting || isImporting} className="h-10 flex-1 border-0 bg-transparent text-slate-100 placeholder:text-slate-500 focus-visible:ring-cyan-300" aria-label="YouTube URL" + maxLength={2048} />