reject brackets in export filtergraph validation instead of stripping link labels

This commit is contained in:
Josh Hawkins 2026-06-13 17:11:49 -05:00
parent 23d4facfb3
commit 2b488dba71
2 changed files with 9 additions and 5 deletions

View File

@ -124,8 +124,8 @@ def _base_flag(token: str) -> str:
def _validate_filtergraph(value: str) -> tuple[bool, str]:
"""Validate a filtergraph value, allowing only filters in _SAFE_FILTERS."""
# No safe filter needs these; they only show up in read/exfil payloads.
if "://" in value or ".." in value:
# None of the safe filters need any of these
if any(token in value for token in ("://", "..", "[", "]")):
return False, "Invalid filter graph in custom ffmpeg arguments"
lowered = value.lower()
@ -136,9 +136,7 @@ def _validate_filtergraph(value: str) -> tuple[bool, str]:
# filters never use unescaped "," or ";" in their arguments, so splitting on
# them to recover filter names cannot hide a disallowed filter.
for spec in re.split(r"[;,]", value):
# Strip leading/trailing [link] labels (e.g. "[in]scale=...[out]").
spec = re.sub(r"^(\[[^\]]*\])+", "", spec.strip())
spec = re.sub(r"(\[[^\]]*\])+$", "", spec).strip()
spec = spec.strip()
if not spec:
continue

View File

@ -64,6 +64,12 @@ class TestValidateFfmpegArgs(unittest.TestCase):
# marker embedded as an option of an otherwise-allowed filter name
self.assertRejected("-vf scale=movie=/etc/passwd")
def test_filtergraph_brackets_rejected(self):
# link labels aren't needed for safe filters; rejecting "[" / "]" keeps
# filtergraph validation linear (no ReDoS on attacker input)
self.assertRejected("-vf [in]scale=640:480[out]")
self.assertRejected("-vf " + "[" * 5000)
def test_preset_file_read_rejected(self):
# cwd-anchored traversal slipped past the old startswith() path check
self.assertRejected("-fpre frigate/../../../etc/passwd")