🛡️ Sentinel: [CRITICAL] Fix missing -no-shell-escape in PDF generation#321
🛡️ Sentinel: [CRITICAL] Fix missing -no-shell-escape in PDF generation#321anchapin wants to merge 1 commit into
Conversation
Added `-no-shell-escape` flags and timeouts to `pdflatex` and `pandoc` subprocess calls in `cli/pdf/converter.py` and `cli/generators/cover_letter_generator.py` to prevent Remote Code Execution (RCE) via `\write18` and mitigate Denial of Service (DoS) risks from infinite compilation loops. Co-authored-by: anchapin <6326294+anchapin@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
Reviewer's GuideTightens PDF generation security by adding -no-shell-escape flags and enforcing 30s timeouts (with cleanup and failure signaling) on all pdflatex/pandoc subprocesses used by the cover letter generator and generic PDF converter. Sequence diagram for secured pdflatex PDF compilation with timeoutsequenceDiagram
participant Caller
participant Converter as converter._compile_pdflatex
participant Subprocess as subprocess.Popen
Caller->>Converter: _compile_pdflatex(tex_path, output_path, working_dir)
Converter->>Subprocess: Popen(["pdflatex", "-interaction=nonstopmode", "-no-shell-escape", tex_path.name])
activate Subprocess
alt within 30s
Converter->>Subprocess: process.communicate(timeout=30)
Subprocess-->>Converter: stdout, stderr
alt process.returncode == 0 or output_path.exists()
Converter-->>Caller: return True
else
Converter-->>Caller: return False
end
else subprocess.TimeoutExpired
Converter->>Subprocess: process.kill()
Subprocess-->>Converter: process.communicate()
Converter-->>Caller: return False
end
deactivate Subprocess
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The timeout handling and process cleanup logic is duplicated across all four subprocess calls; consider extracting a small helper (e.g.,
run_with_timeout(args, cwd)returning success/False) to centralize this behavior and reduce future drift. - These code paths use
subprocess.Popen(...).communicate()immediately and never callcheck=True, so catchingsubprocess.CalledProcessErroris ineffective; you can either switch tosubprocess.run(..., check=True, timeout=30)or adjust the exception handling to match the current usage. - Since a timeout is now treated as a hard failure (
return False), it may be useful to at least log or propagate that a timeout occurred (using the capturedstdout/stderr), so callers or operators can distinguish timeouts from normal compilation failures.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The timeout handling and process cleanup logic is duplicated across all four subprocess calls; consider extracting a small helper (e.g., `run_with_timeout(args, cwd)` returning success/False) to centralize this behavior and reduce future drift.
- These code paths use `subprocess.Popen(...).communicate()` immediately and never call `check=True`, so catching `subprocess.CalledProcessError` is ineffective; you can either switch to `subprocess.run(..., check=True, timeout=30)` or adjust the exception handling to match the current usage.
- Since a timeout is now treated as a hard failure (`return False`), it may be useful to at least log or propagate that a timeout occurred (using the captured `stdout`/`stderr`), so callers or operators can distinguish timeouts from normal compilation failures.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
🚨 Severity: CRITICAL
💡 Vulnerability: Missing
-no-shell-escapeflags inpdflatexandpandoccalls allowed Remote Code Execution (RCE) via\write18if malicious LaTeX was processed. Missing timeouts allowed Denial of Service (DoS) via infinite compilation loops.🎯 Impact: An attacker could execute arbitrary commands on the system or exhaust server resources.
🔧 Fix: Added
-no-shell-escape/--pdf-engine-opt=-no-shell-escapeflags and 30-second timeouts with proper cleanup to all PDF compilation subprocess calls incli/pdf/converter.pyandcli/generators/cover_letter_generator.py.✅ Verification: Ran
python -m pytest tests/test_pdf_security.pyand full test suite to ensure tests pass and subprocess timeouts/flags are correctly handled.PR created automatically by Jules for task 7938752640156516623 started by @anchapin
Summary by Sourcery
Harden PDF generation by enforcing safe LaTeX engine options and adding execution time limits to compilation subprocesses.
Enhancements: