Skip to content

πŸ›‘οΈ Sentinel: [CRITICAL] Fix RCE in PDF compilation#345

Open
anchapin wants to merge 2 commits into
mainfrom
sentinel-subprocess-security-1025421589653301781
Open

πŸ›‘οΈ Sentinel: [CRITICAL] Fix RCE in PDF compilation#345
anchapin wants to merge 2 commits into
mainfrom
sentinel-subprocess-security-1025421589653301781

Conversation

@anchapin

@anchapin anchapin commented Jun 7, 2026

Copy link
Copy Markdown
Owner

🚨 Severity: CRITICAL
πŸ’‘ Vulnerability: PDF compilation via pdflatex and pandoc can execute arbitrary commands if -no-shell-escape is not specified, leading to potential Remote Code Execution (RCE) from untrusted input. Additionally, lack of subprocess timeouts could lead to DoS from hanging compilations.
🎯 Impact: An attacker could potentially gain unauthorized code execution privileges on the server or cause a Denial of Service by supplying malformed LaTeX input.
πŸ”§ Fix: Added -no-shell-escape flag (for pdflatex) and --pdf-engine-opt=-no-shell-escape (for pandoc) to subprocess calls in cli/generators/cover_letter_generator.py and cli/pdf/converter.py. Added a 30-second timeout to .communicate() calls with proper process cleanup (catching TimeoutExpired, killing the process, and flushing pipes) to mitigate DoS risks.
βœ… Verification: Ran pytest tests/test_cover_letter_generator.py tests/test_cover_letter_security.py tests/test_pdf_security.py and full python -m pytest test suite successfully. Evaluated and approved by code review.


PR created automatically by Jules for task 1025421589653301781 started by @anchapin

Summary by Sourcery

Mitigate security risks in LaTeX-based PDF generation by hardening external compilation subprocesses and documenting the RCE class of issues.

Bug Fixes:

  • Prevent potential remote code execution in pdflatex and pandoc-based PDF compilation by disabling shell escape when compiling untrusted LaTeX content.
  • Reduce denial-of-service risk from hanging PDF compilation by enforcing timeouts and terminating stalled subprocesses.

Enhancements:

  • Improve robustness of PDF generation utilities by adding explicit timeout handling and cleanup around external compiler invocations.

Documentation:

  • Extend Sentinel security notes with guidance on enforcing no-shell-escape for all LaTeX/PDF compilation subprocesses to prevent RCE.

Co-authored-by: anchapin <6326294+anchapin@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

πŸ‘‹ 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 @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@sourcery-ai

sourcery-ai Bot commented Jun 7, 2026

Copy link
Copy Markdown

Reviewer's Guide

Hardened PDF compilation against RCE and DoS by enforcing LaTeX shell-escape restrictions for both pdflatex and pandoc, and by adding timeouts with safe teardown for all long-running compilation subprocesses, plus documenting the new Sentinel security requirement.

Sequence diagram for secured pdflatex PDF compilation with timeout

sequenceDiagram
    participant Converter as PdfConverter
    participant Subprocess as subprocess
    participant Pdflatex as pdflatex_process

    Converter->>Subprocess: Popen(["pdflatex", "-interaction=nonstopmode", "-no-shell-escape", tex_path.name])
    Subprocess-->>Converter: Pdflatex (process)

    Converter->>Pdflatex: communicate(timeout=30)
    alt [process finishes before timeout]
        Pdflatex-->>Converter: stdout, stderr
        alt [process.returncode == 0 or output_path.exists()]
            Converter-->>Converter: return True
        else [compile failed]
            Converter-->>Converter: return False
        end
    else [subprocess.TimeoutExpired]
        Converter->>Pdflatex: kill()
        Converter->>Pdflatex: communicate()
        Pdflatex-->>Converter: stdout, stderr
        Converter-->>Converter: return False
    end
Loading

File-Level Changes

Change Details Files
Hardened cover letter PDF compilation by disabling LaTeX shell escape and adding subprocess timeouts with cleanup.
  • Updated pdflatex invocation to include -no-shell-escape while preserving nonstop interaction mode and working directory handling.
  • Updated pandoc fallback invocation to use --pdf-engine-opt=-no-shell-escape in addition to the existing xelatex engine configuration.
  • Wrapped communicate() calls with a 30-second timeout, killing the process and draining pipes on TimeoutExpired before returning failure.
  • Maintained existing success criteria based on return code or existence of the expected PDF output file.
cli/generators/cover_letter_generator.py
Applied the same LaTeX hardening and timeout logic to the shared PDF converter utilities.
  • Added -no-shell-escape to pdflatex calls in the generic PDF converter while keeping interaction and working directory semantics unchanged.
  • Extended pandoc-based compilation to pass --pdf-engine-opt=-no-shell-escape alongside the xelatex engine selection.
  • Guarded all compilation communicate() calls with a 30-second timeout and explicit kill plus cleanup on timeout, returning False when exceeded.
  • Preserved existing True/False return semantics based on process success or presence of the compiled PDF file.
cli/pdf/converter.py
Documented the new Sentinel security requirement around disabling LaTeX shell escape during PDF compilation.
  • Recorded the RCE vulnerability, key learning, and prevention guidelines in the Sentinel security playbook for future reference and consistency across the codebase.
.jules/sentinel.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • The new subprocess timeout and kill/cleanup logic is duplicated in multiple places; consider extracting a small helper (e.g., run_with_timeout(cmd, cwd=None, timeout=30) -> (returncode, stdout, stderr)) to centralize behavior and make future changes less error-prone.
  • The 30-second timeout is currently hard-coded in several calls; it may be useful to make this configurable (via a constant or parameter) so different environments or workloads can tune the compilation time limit without code changes.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new subprocess timeout and kill/cleanup logic is duplicated in multiple places; consider extracting a small helper (e.g., `run_with_timeout(cmd, cwd=None, timeout=30) -> (returncode, stdout, stderr)`) to centralize behavior and make future changes less error-prone.
- The 30-second timeout is currently hard-coded in several calls; it may be useful to make this configurable (via a constant or parameter) so different environments or workloads can tune the compilation time limit without code changes.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click πŸ‘ or πŸ‘Ž on each comment and I'll use the feedback to improve your reviews.

Co-authored-by: anchapin <6326294+anchapin@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant