T08 · Insecure Dependencies
- Location
scripts/extract.py:27- Finding
Automatic Runtime Installation of an Unpinned Third-Party Dependency
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly a coherent resume parser, but it should be reviewed because it automatically installs an unpinned dependency and persists sensitive resume data to disk.
Review before installing or running. Use this only in a controlled virtual environment, preinstall a pinned and reviewed pdfmuse dependency instead of relying on automatic pip install, process only authorized resume folders, and store generated JSON/Markdown/CSV outputs in a restricted location. Be aware that outputs may contain contact details and other personal information, and same-named resumes from different folders can overwrite each other's extraction files.
scripts/extract.py:27Automatic Runtime Installation of an Unpinned Third-Party Dependency
scripts/extract.py:192Silent Output Overwrite Through Basename Collisions
The description overstates the skill’s core functionality. The code does handle PDF/DOCX resumes, supports batch/folder processing, and extracts contacts with some source-related metadata, which aligns partially with the declaration. However, the declared primary purpose is converting resumes into structured JSON Resume data including work history, education, skills, and projects. The code explicitly says it never infers semantic resume structure and only emits: clean Markdown, page/layout warnings, links, and mined contacts/profiles. There is no implementation of full JSON Resume mapping, no extraction of employment/education/project sections, and no structured candidate-profile assembly beyond limited sidecar metadata. Therefore this is a material description-behavior mismatch.
The declared purpose centers on document ingestion and extraction: parsing resumes from PDF/DOCX into structured JSON Resume output, including multilingual support and batch recruiting workflows. The actual code does none of that. It reads JSON files from disk, validates their schema-like structure, warns on unknown fields, and checks date formatting. This is materially different from resume parsing/extraction. While validation could be a supporting utility within a larger resume-processing system, this specific code chunk's primary purpose is validation of already-generated JSON, not conversion of resumes into JSON. Therefore the description does not accurately represent the behavior of this code chunk.
The README promotes parsing resumes into structured JSON without any warning that resumes contain highly sensitive personal data such as names, contact details, employment history, and education records. In a recruiting or ATS context, users may process third-party documents at scale, increasing the likelihood of unintended privacy exposure or noncompliant handling if they are not explicitly warned about data sensitivity and retention.
The README documents that the tool writes JSON, Markdown summaries, and batch CSV indexes to disk, but it does not warn that these artifacts persist source resume data and derived candidate information. This can lead to accidental long-term storage, broader internal exposure, or ingestion into less secure systems, especially when processing whole folders in batch for recruiting workflows.
The skill requests or implies shell, file read, and file write capabilities without declaring an explicit tool scope or permissions boundary. That makes it easier for an agent framework to invoke the skill with broader-than-necessary access, increasing the chance of unintended filesystem access, command execution, or data exposure when processing resumes.
The manifest description says to use the skill when the user wants to 'build a candidate table from resumes, or process a folder of resumes for recruiting/screening/ATS workflows.' This broadens activation beyond narrowly defined parsing requests and may overlap with common recruiting workflow requests where parsing is only one possible subtask, increasing the chance of unintended invocation.
The documentation says only python3 is needed, but the extraction flow performs runtime installation of an additional package. Runtime dependency installation can introduce supply-chain risk, unexpected network access, non-reproducible behavior, and execution of unreviewed code in environments that may process sensitive resume data.
The skill explicitly generates candidate summaries and batch roster files containing names, contact details, employment history, and other sensitive personal data, but provides no warning or handling guidance. In the context of resume parsing, that omission is more dangerous because the skill normalizes and aggregates PII into easily shareable outputs like Markdown summaries and CSV indexes, increasing privacy, retention, and unauthorized-sharing risk.
This markdown file describes transforming extracted resume content into resume.json and includes concrete examples containing personal data such as names, email addresses, phone numbers, birth date, gender, location, and employment history. The document does not warn that the skill processes and emits sensitive personal information, which is relevant for user privacy and data handling expectations.
The module docstring states that the script produces clean Markdown and a JSON sidecar of mined facts, and explicitly says semantic mapping to JSON Resume is done elsewhere by Claude. That behavior is narrower than the manifest's description of parsing resumes into structured JSON Resume data with work history, education, skills, and projects.
The script writes extracted contact information and source paths from resumes to disk by default, which creates persistent storage of sensitive personal data without any consent prompt, minimization, or retention controls. In a recruiting/ATS context this data is expected, but the default behavior still increases exposure risk if the output directory is shared, backed up, or processed by other tools.
Installing a package at runtime is not necessary for basic file parsing and materially expands the trust boundary beyond the local script. In this skill context, the behavior is more dangerous because resume parsing is expected to be a data-processing task, not one that mutates the environment or fetches executable code from a package index during execution.
The script executes a runtime pip install if pdfmuse is missing, which introduces an uncontrolled supply-chain and code-execution path during normal use. Even though subprocess.run is invoked with a fixed argument list rather than shell injection, it still causes the host to download and execute unpinned third-party package code, which is especially risky in an agent skill handling untrusted documents.
return pdfmuse
except ImportError:
print("pdfmuse not found -- installing (one-time)...", file=sys.stderr)
subprocess.run(
[sys.executable, "-m", "pip", "install", "-q", "pdfmuse"],
check=True,
)
The document instructs outputs to remain in the resume's own language and explicitly says not to translate names, companies, or schools. This is a natural-language locale policy constraint that does not present user opt-in or an alternative language choice.
The dependency is unpinned, so installations may resolve to different future versions of pdfmuse over time. That creates a supply-chain risk: a malicious or compromised upstream release, or a breaking/insecure update, could be pulled into this resume-processing skill without review. The batch parsing context increases exposure because this skill is likely used in automated recruiting workflows and may process untrusted files at scale.
pdfmuse
No suspicious patterns detected.