diff --git a/aperisolve/analyzers/jpseek.py b/aperisolve/analyzers/jpseek.py index b5f30d3..27d01b4 100644 --- a/aperisolve/analyzers/jpseek.py +++ b/aperisolve/analyzers/jpseek.py @@ -16,16 +16,18 @@ class JpseekAnalyzer(SubprocessAnalyzer): """Build the jpseek command wrapped with expect for password support.""" extracted_dir = self.get_extracted_dir() out = str(extracted_dir / "jpseek.out") - jpseek_cmd = f"jpseek {self.img} {out}" if password is None: password = "" - expect_cmd = ( - f"expect -c 'spawn {jpseek_cmd}; " - f'expect "Passphrase:"; ' - f'send "{password}\\r"; ' - f"expect eof'" + # File paths are quoted with Tcl braces to prevent interpretation of + # special characters. The password is passed via an environment variable + # (JPSEEK_PASS) to avoid any command injection through string interpolation. + expect_script = ( + f"spawn jpseek {{{self.img}}} {{{out}}}; " + 'expect "Passphrase:"; ' + 'send "$env(JPSEEK_PASS)\\r"; ' + "expect eof" ) - return ["bash", "-c", expect_cmd] + return ["env", f"JPSEEK_PASS={password}", "expect", "-c", expect_script] def _remove_output_artifacts(self, output: str) -> str: extracted_dir = self.get_extracted_dir() diff --git a/pyproject.toml b/pyproject.toml index 88baeff..ab6571c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "aperisolve" -version = "3.2.0" +version = "3.2.1" description = "Open-source steganalysis web platform for automated image analysis and steganography detection" readme = "README.md" requires-python = ">=3.12"