CVE-2022-36231
Description
pdf_info 0.5.3 and earlier is vulnerable to OS command injection via unsanitized user input used in backtick shell execution.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
pdf_info 0.5.3 and earlier is vulnerable to OS command injection via unsanitized user input used in backtick shell execution.
## Vulnerability pdf_info <= 0.5.3 is vulnerable to OS command injection because the command method uses backticks to execute the pdfinfo binary, passing the user-controlled @pdf_path directly without sanitization [3]. The official description notes the Ruby code uses backticks instead of Open3 [1].
Exploitation
An attacker can exploit this by providing a crafted pdf_path string that includes command chaining characters (e.g., ;). For example, creating a PDF::Info object with a path like 'pdf/sample1.pdf; $(malicious command)' will execute arbitrary OS commands when metadata is called [3]. No authentication is required if the application accepts user-supplied PDF paths.
Impact
Successful exploitation allows an attacker to execute arbitrary OS commands in the context of the Ruby process. This could lead to data exfiltration, lateral movement, or full system compromise, depending on the privileges of the application [3].
Mitigation
The vulnerability has been fixed in a pull request that replaces backticks with Open3.capture3 to prevent command injection [4]. Users should upgrade to pdf_info version 0.5.4 or later. The gem's repository was transferred to new maintainers to facilitate the fix [4].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
pdf_infoRubyGems | <= 0.5.3 | — |
Affected products
2- pdf_info/pdf_infodescription
Patches
154d4e01da111Merge pull request #15 from tomtaylor/fix-cve-command-injection
3 files changed · +17 −28
lib/pdf/info.rb+14 −10 modified@@ -1,5 +1,6 @@ require 'date' unless defined? DateTime require 'pdf/info/exceptions' +require 'open3' module PDF class Info @@ -18,20 +19,19 @@ def initialize(pdf_path) end def command - output = `#{self.class.command_path} -enc UTF-8 -f 1 -l -1 "#{@pdf_path}" 2> /dev/null` - exit_code = $? - case exit_code - when 0 || nil - if !output.valid_encoding? + stdout, stderr, status = Open3.capture3(self.class.command_path, "-enc", "UTF-8", "-f", "1", "-l", "-1", @pdf_path) + + if status.success? + if !stdout.valid_encoding? # It's already UTF-8, so we need to convert to UTF-16 and back to # force the bad characters to be replaced. - output.encode!('UTF-16', :undef => :replace, :invalid => :replace, :replace => "") - output.encode!('UTF-8') + stdout.encode!('UTF-16', :undef => :replace, :invalid => :replace, :replace => "") + stdout.encode!('UTF-8') end - return output + return stdout else exit_error = PDF::Info::UnexpectedExitError.new - exit_error.exit_code = exit_code + exit_error.exit_code = status.exitstatus raise exit_error end end @@ -82,7 +82,11 @@ def process_output(output) metadata[:pages] << pair.last.scan(/[\d.]+/).map(&:to_f) metadata[:format] = pair.last.scan(/.*\(\w+\)$/).to_s when String - metadata[pair.first.downcase.tr(" ", "_").to_sym] = pair.last.to_s.strip + # For a specific key, take the first value, and don't allow later keys to overwrite it + # This prevents later declarations of 'Title' from overwriting the title of the document. + key = pair.first.downcase.tr(" ", "_").to_sym + value = pair.last.to_s.strip + metadata[key] = value unless metadata[key] end end
pdf_info.gemspec+1 −1 modified@@ -20,5 +20,5 @@ Gem::Specification.new do |s| s.require_paths = ["lib"] s.add_development_dependency "rake" - s.add_development_dependency "rspec"#, '~> 2.12.0' + s.add_development_dependency "rspec", '~> 2.12' end
spec/pdf_info_spec.rb+2 −17 modified@@ -155,24 +155,9 @@ its([:producer]) { should == "GPL Ghostscript 8.15" } its([:subject]) { should be_nil } its([:author]) { should eq "carlos"} - its([:creation_date]) { should eq DateTime.parse("2010-10-09T10:29:55+00:00")} - its([:modification_date]) { should eq DateTime.parse("2010-10-09T10:29:55+00:00")} + its([:creation_date]) { should eq DateTime.parse("2010-10-09T12:29:55+01:00").new_offset(0) } + its([:modification_date]) { should eq DateTime.parse("2010-10-09T12:29:55+01:00").new_offset(0) } its([:tagged]) { should be_false } its([:file_size]) { should eq "218882 bytes" } end - - describe "running on a file with invalid utf-8 metadata" do - subject do - PDF::Info.command_path = "pdfinfo" - PDF::Info.new(File.join(File.dirname(__FILE__), 'assets', 'invalid-utf8.pdf')).metadata - end - - its([:page_count]) { should == 12 } - its([:title]) { should eq "图形1.CDR" } - # the two date fields are badly encoded in this file, so the DateTime parse - # will fail, and we'll have a nil in these fields - its([:creation_date]) { should be_nil } - its([:modification_date]) { should be_nil } - end - end
Vulnerability mechanics
Root cause
"The Ruby code uses shell backticks to execute an external command with an unsanitized file path, allowing command injection."
Attack vector
An attacker can supply a crafted PDF file path containing shell metacharacters (e.g., backticks, semicolons, or pipes) to the `PDF::Info.new` constructor. When the `command` method is called, the unsanitized `@pdf_path` is interpolated into a backtick-delimited shell command, causing the injected commands to be executed. No authentication or special privileges are required; the attacker only needs to control the file path argument passed to the library.
Affected code
The vulnerable code is in `lib/pdf/info.rb` within the `command` method. The original implementation used Ruby backticks to execute `pdfinfo` with the user-supplied `@pdf_path` interpolated directly into the shell command string [patch_id=1641402].
What the fix does
The patch replaces the shell backtick invocation (`\`...\``) with `Open3.capture3`, which passes each argument as a separate array element to the underlying process, preventing shell interpretation of special characters. The file path `@pdf_path` is now passed as a literal argument rather than being interpolated into a shell command string. Additionally, the patch adds `require 'open3'` to load the necessary library [patch_id=1641402].
Preconditions
- inputAttacker must control the pdf_path argument passed to PDF::Info.new.
Generated on May 23, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-9fh3-j99m-f4v7ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-36231ghsaADVISORY
- github.com/newspaperclub/pdf_info/issues/16ghsaWEB
- github.com/newspaperclub/pdf_info/pull/15ghsaWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/pdf_info/CVE-2022-36231.ymlghsaWEB
- rubygems.org/gems/pdf_infoghsaWEB
News mentions
0No linked articles in our index yet.