MCP, MCP server
pdfmux
Self-healing PDF extraction that flags the pages it can't read instead of dropping them — and now certifies any extractor's output for silent drops. Open-source LlamaParse alternative for RAG pipelines, MCP server for Claude Desktop, LangChain + LlamaIndex loaders.
Compatibility: Not stated.
Grade B
Minor issues only, no Medium or High. Worth a quick look at the findings below before installing.
Not a guarantee. A hygiene check of the source at the commit shown, not a security audit.
Rescanned at commit 566be30cfae6, unchanged since the check below.
PERMISSION_DELETE_FILES NETWORK_NO_FIXED_HOST SECRETS_PATH_DOTENV SECRETS_ENV_READ
Why this grade
- PERMISSION_DELETE_FILES Low
Contains a call that can delete files.
eval/pdf-inspector-eval/runner.py, line 281
cpu=subprocess.run( - NETWORK_NO_FIXED_HOST Low
Makes a network call whose host is not written as a fixed address.
scripts/benchmark_gemma4.py, line 87
with urllib.request.urlopen(req, timeout=timeout) as resp: - SECRETS_PATH_DOTENV Low
Mentions a .env file.
.env.example, line 2
# Copy to .env.local and fill in values - SECRETS_ENV_READ Note
Reads an environment variable whose name contains KEY, SECRET, TOKEN, PASSWORD or CREDENTIAL.
scripts/verify-gemma4.py, line 87
if not (os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY")):
Any High, or two or more Medium findings, give D. One Medium gives C. Low findings or a security Note give B. Each code names a finding behind the letter.
Grades are a hygiene check of the source at the commit shown, on the date checked, not a security audit or a guarantee. The free directory grades are automated. Before release, a PlugVet engineer reviews every paid report and any grade we hold back, including all F grades, against the source code and the evidence we quote.
What was checked
Plain notes from the hygiene checks.
Permissions
Concern
can delete files.
PERMISSION_DELETE_FILES
eval/pdf-inspector-eval/runner.py, line 281
cpu=subprocess.run(
eval/pdf-inspector-eval/runner.py, line 285
nproc=subprocess.run(["nproc"], capture_output=True, text=True).stdout.strip(),
eval/pdf-inspector-eval/runner.py, line 286
mem=subprocess.run(
Show more
eval/pdf-inspector-eval/runner.py, line 291
pdfmux_git_sha=subprocess.run(
eval/pdf-inspector-eval/runner.py, line 294
pdfmux_version=subprocess.run(
src/pdfmux/remote/sandbox.py, line 84
proc = subprocess.run( # noqa: S603 - fixed argv, no shell
src/pdfmux/remote/sandbox.py, line 95
subprocess.run(["docker", "kill", ctx["container"]], capture_output=True, timeout=15) # noqa: S603,S607
src/pdfmux/remote/sandbox.py, line 136
proc = subprocess.run( # noqa: S603 - fixed argv, no shell
src/pdfmux/remote/server.py, line 357
shutil.rmtree(work, ignore_errors=True) # the uploaded PDF never outlives the call
src/pdfmux/remote/server.py, line 481
shutil.rmtree(d, ignore_errors=True)
Install and update
Pass
No install-time script found, and dependencies are pinned or absent.
Network
Concern
can reach a host that is not written as a fixed address.
NETWORK_NO_FIXED_HOST
scripts/benchmark_gemma4.py, line 87
with urllib.request.urlopen(req, timeout=timeout) as resp:
scripts/benchmark_gemma4.py, line 117
urllib.request.urlopen("http://localhost:11434/api/tags", timeout=5)
scripts/benchmark_gemma4.py, line 127
with urllib.request.urlopen("http://localhost:11434/api/tags", timeout=5) as resp:
Show more
src/pdfmux/cli.py, line 2515
curl .../v1/jobs/ID | pdfmux verify-manifest - --pubkey-url
src/pdfmux/manifest_verify.py, line 176
with urllib.request.urlopen(url, timeout=timeout) as resp: # noqa: S310 - https only, caller-chosen
Dockerfile, line 44
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/mcp')" || exit 1
Secrets
Concern
reads a credential or environment file.
SECRETS_ENV_READ SECRETS_PATH_DOTENV
scripts/verify-gemma4.py, line 87
if not (os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY")):
scripts/verify-gemma4.py, line 96
key = os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY", "")
.env.example, line 2
# Copy to .env.local and fill in values
Show more
src/pdfmux/extractors/mistral_ocr.py, line 43
return bool(os.environ.get("MISTRAL_API_KEY"))
src/pdfmux/extractors/mistral_ocr.py, line 70
api_key = os.environ.get("MISTRAL_API_KEY")
src/pdfmux/providers/claude.py, line 25
return bool(os.environ.get("ANTHROPIC_API_KEY"))
src/pdfmux/providers/gemini.py, line 25
return bool(os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY"))
src/pdfmux/providers/gemini.py, line 57
api_key = os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY")
src/pdfmux/providers/gemma.py, line 91
return bool(os.environ.get("GEMINI_API_KEY") or os.environ.get("GOOGLE_API_KEY"))
.gitignore, line 10
.env
.gitignore, line 11
.env.*
Agent instructions
Pass
No instruction to ignore earlier instructions or to hide a step.
Obfuscation
Pass
No encoded or minified payload found.
Licence
Pass
A licence file is present (LICENSE).
Maintainer activity
Pass
The latest commit is within the last 365 days.
Note
Hygiene check of commit 566be30cfae6. can delete files. can reach a host that is not written as a fixed address. reads a credential or environment file.
Date and source
Date checked:
github.com
Commit graded: 566be30cfae600f91b84618aef632f91c3f52e60
This link goes to the original host. PlugVet does not host or check what you download from there, and installing it is your own decision and risk.