Back to skill

Security audit

AI Job Hunter Pro

Security checks for vulnerabilities and agentic risk

Overview

This job-search skill is purpose-related but needs Review because it stores sensitive resume data and can produce or record job-application materials with weak controls and hardcoded personal claims.

Review carefully before installing. Use only dry-run mode, inspect every generated cover letter for false claims, avoid relying on the tracker as proof of real submissions, and treat the local profile, resume database, feedback, and application history as sensitive files. Prefer a locked dependency environment and avoid opening the dashboard with untrusted job JSON until the URL handling and third-party script loading are fixed.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
dashboard.html:327
Finding

DOM-Based Code Injection Through Untrusted Job URLs

Content
View full analysis
${i+1}
${escHtml(job.title)}
${escHtml(job.company)} · ${escHtml(job.location || '')}
${tagsHtml}
${job.match_score.toFixed(3)}
`; ``` ### Technical Analysis The dashboard accepts an arbitrary user-selected JSON file and assigns its parsed contents to `jobsData`. While job titles, companies, and locations are processed through `escHtml()`, the `job.url` value is inserted directly into an HTML string containing an inline JavaScript event handler. A single quote in the URL terminates the JavaScript string passed to `window.open()`. The remainder of the value can then inject JavaScript into the `onclick` handler. Because the constructed markup is assigned through `innerHTML`, the browser parses the injected handler as executable code. For example, this URL value ...[truncated 1670 chars]
Remediation
View remediation
{ window.open(safeUrl, '_blank', 'noopener,noreferrer'); }); } ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/rag_engine.py:109
Finding

Plaintext Persistence of Resume and Profile Data Without Explicit Access Controls

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:1
Finding

Unpinned Executable Dependencies and Unverified Remote Browser Assets

Content
View full analysis
=0.4.0 sentence-transformers>=2.2.0 pdfplumber>=0.10.0 python-docx>=0.8.11 ``` ```python def install_dependencies(): req_file = os.path.join(os.path.dirname(__file__), "requirements.txt") if os.path.exists(req_file): print("[SETUP] Installing dependencies...") subprocess.run([sys.executable, "-m", "pip", "install", "-r", req_file, "-q"], check=True) print("[OK] Dependencies installed") else: print("[WARN] requirements.txt not found, installing core packages...") packages = ["chromadb", "sentence-transformers"] subprocess.run([sys.executable, "-m", "pip", "install"] + packages + ["-q"], check=True) ``` ```html ``` The scraper also recommends an additional undeclared installation: ```python try: from playwright.sync_api import sync_playwright except ImportError: print("[ERROR] playwright not installed. Run: pip install playwright && playwright install chromium") sys.exit(1) ``` ### Technical Analysis Every Python dependency is specified using a minimum version without an upper bound, exact version, or artifact hash. Running the setup script immediately executes `pip install`, allowing future package and transitive-dependency releases to execute with the user's privileges. Playwright is required by the scraper implementations but is absent from `requirements.txt`. Users are instead instructed to perform another unpinned installation and download a Chromium binary. The dashboard loads executable JavaScr ...[truncated 1684 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/apply_pipeline.py:284
Finding

Configured Application Confirmation Controls Are Not Enforced

Content
View full analysis
dict: """ Process a single job through the pipeline. Modes: dry-run: Generate materials, show preview, don't submit submit: Actually submit the application """ job_id = job.get("id", "unknown") result = { "job_id": job_id, "job_title": job.get("title"), "company": job.get("company"), "mode": mode, "timestamp": datetime.now().isoformat() } # Step 1: Generate cover letter if generate_cover_letter: cover_letter = self.cover_gen.generate( job, match_reasons=job.get("match_reasons", []) ) result["cover_letter"] = cover_letter # Step 2: ATS optimization if optimize_ats: ats_result = self.ats_opt.optimize( json.dumps(self.profile), job.get("description", "") ) result["ats_analysis"] = ats_result # Step 3: Record in database self._record_application(job, result, mode) if mode == "dry-run": result["action"] = "PREVIEW ONLY — not submitted. Run with --mode submit to apply." else: result["action"] = "Application submitted (simulated)." self._update_status(job_id, "discovered", "applied") ``` ```python parser.add_argument("--mode", choices=["dry-run", "submit"], default="dry-run") ``` The supplied profile exposes controls that are never enforced by the pipeline: ```json "preferences": { "max_daily_applications": 20, "min_match_score": 0.75, "require_confirmation": true, "dry_run": true, "auto_cover_letter": true, "ats_opti ...[truncated 2147 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/apply_pipeline.py:55
Finding

Generated Cover Letters Include Unverified Candidate-Specific Claims

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (34)

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The declared description presents a broad end-to-end job search assistant with job discovery, resume-JD matching via RAG, automated application, tracking, cover-letter generation, and reporting. The supplied code only covers a narrower downstream pipeline: cover-letter generation, ATS optimization, and local application/status tracking. It does not perform job search, retrieval, semantic matching, or real external submission; instead, submission is explicitly simulated. While parts of the description are represented (cover letters and status tracking), the code materially underdelivers on the core declared capabilities and also uses local file/database storage despite no declared permissions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code chunk primarily implements browser automation for scraping job postings from specific company career sites and storing the results locally. It also supports optional merging with another scraped dataset and optional resume-to-job matching through a separate RAG engine. This only partially overlaps with the declared description. The declared description promises a broader assistant with automated application pipeline, status tracking, cover letter generation, and funnel analysis, none of which are present in this code. While job search and resume-JD matching are somewhat represented, the actual code’s main behavior is a company-career-page scraper, making the description materially broader and not accurately representative of this supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code chunk's main purpose is scraping job listings from specific company career websites using Playwright, then saving and optionally merging those listings. It also optionally invokes a RAG engine to match jobs against a resume collection, which partially aligns with the declared resume-JD matching claim. However, most of the declared product scope is absent from this code: there is no auto-application flow, no submission of applications, no status tracking, no cover-letter generation, and no reporting/analytics. Additionally, the concrete implemented capability of browser-based scraping from company sites is a primary behavior not reflected in the description. Therefore the description materially overstates and misrepresents what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description presents a broad end-to-end job search assistant with resume-job matching, automated applications, status tracking, cover-letter generation, and reporting. The supplied code chunk, however, is narrowly focused on scraping public job listings from LinkedIn and Indeed and saving them, with only an optional call to an external RAG engine for matching. Its primary implemented behavior is job scraping, not the full automated application/tracking/reporting workflow described. This is a material description-behavior mismatch because several major user-facing capabilities are declared but absent from the code shown, while the implemented scraping behavior is more specific than the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code is clearly related to the declared domain of job search and does accurately support one major advertised feature: RAG-based resume-JD matching. It parses resumes, chunks and embeds them, stores vectors in ChromaDB, matches job descriptions semantically, and adjusts scores using user feedback. However, the declared description presents a substantially broader assistant that can auto-apply to jobs, track applications/status, generate cover letters, and analyze the user's job-search funnel. None of those capabilities appear in this code chunk. There is also no real job-platform search integration here—only matching against provided job JSON or demo jobs. Because the declared purpose materially overstates the implemented capabilities in this supplied chunk, this should be flagged as a description/behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a broad AI job-search assistant with discovery, matching, auto-apply, cover-letter generation, and tracking. The supplied code chunk only covers the tracking/analytics portion: reading and updating application records in a local SQLite database, generating reports, and listing applications. While status tracking and funnel analysis are consistent with part of the description, the main declared capabilities such as AI matching, job search, and auto-apply are not implemented in this chunk. Because the code’s actual behavior is materially narrower than the declared purpose and lacks several central advertised capabilities, this is a description/behavior mismatch.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
86% confidence
Finding

The README instructs users to run npx playbooks add skill ai-job-hunter-pro without pinning a specific package version, which can cause execution of whatever package version is current at install time. In a skill distribution context, this increases supply-chain risk because users may execute updated or compromised code unexpectedly during setup.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README promotes automated job application behavior, including 'auto-apply' workflows, but does not prominently warn that actions may submit real applications, modify third-party accounts, or violate platform terms. In this skill's context, the absence of explicit safeguards is more dangerous because it targets multiple real job platforms and handles high-impact user actions that can damage reputation, spam employers, or trigger account restrictions.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill instructs execution of Python scripts that read local files, write local state, invoke shell commands, and likely perform network access, but it declares no explicit tool scope or permissions. This creates an authorization gap where a host system or reviewer cannot reliably constrain or understand the skill's effective capabilities, increasing the risk of overbroad file and network access when handling sensitive resume and profile data.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger phrases are very broad and map to common job-seeking language, which can cause the skill to activate in contexts the user did not intend. Because the skill handles sensitive resume/profile data and may progress toward application submission workflows, ambiguous invocation increases the chance of unintended data processing or action-taking.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document declares lang="zh-CN", which sets the interface language/locale to Simplified Chinese. Under the stated policy, forcing a specific language without user opt-in or a documented region-specific justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The dashboard imports executable JavaScript from a third-party CDN and pulls fonts from Google, which creates unnecessary outbound network dependencies for a file presented as a local dashboard for viewing job-matching data. If the CDN response is tampered with, blocked, or replaced, the page could execute attacker-controlled code in the browser or leak usage metadata despite handling potentially sensitive job-search data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The generator automatically chooses Chinese or English output solely from the detected language of the job description. This imposes a language/locale decision on the user without offering a choice or documenting consent, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The pipeline automatically loads a user profile from disk, then uses that profile to generate cover letters and ATS analysis, and persists derived personal data into a local SQLite database without any explicit consent, minimization, or retention controls. In a job-application skill, this materially increases privacy risk because resumes and profiles commonly contain sensitive personal and employment information that may be stored longer than the user expects.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The scraper hard-codes locale="zh-CN" for every browser session, which imposes a specific language/locale choice regardless of user preference. This is a natural-language policy issue because the file does not offer any user opt-in, override, or justification for restricting locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code hard-codes locale="en-US" when creating the browser context, which imposes a specific locale on all scraping sessions. This is a natural-language policy concern because the skill does not offer the user any locale choice or explain why English/US localization is required.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The scraper hard-codes locale="en-US" when creating the browser context, which imposes a specific locale on all users regardless of their preferences or region. The file does not offer an opt-in/override or explain why an English-US locale is required for correct operation.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/rag_engine.py (reported line 29)May include surrounding context.

python
missing = []
    for pkg in REQUIRED_PACKAGES:
        try:
            __import__(pkg)
        except ImportError:
            missing.append(pkg)
    if missing:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Resume import stores extracted resume text embeddings and chunk documents in a persistent local ChromaDB under the user's home directory without an explicit consent, retention notice, or deletion workflow. Because resumes commonly contain sensitive personal data, silent persistence can expose PII to other local users, backups, or later compromise of the host.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a job-search assistant focused on resume-JD matching, application automation, and tracking, but this file implements parsing by spawning local executables like pdftotext and pandoc. Using subprocess-based execution is a materially broader capability than ordinary semantic matching logic and is not justified by the manifest text for this skill.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/rag_engine.py (reported line 133)May include surrounding context.

python
"""Extract text from PDF using available tools."""
        try:
            import subprocess
            result = subprocess.run(
                ["pdftotext", "-layout", path, "-"],
                capture_output=True, text=True, timeout=30
            )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/rag_engine.py (reported line 169)May include surrounding context.

python
# Fallback: use pandoc if available
            try:
                import subprocess
                result = subprocess.run(
                    ["pandoc", path, "-t", "plain"],
                    capture_output=True, text=True, timeout=30
                )

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The feedback feature persists job-description text plus preference history and timestamps to local storage without warning the user that behavioral preference data is being retained. Over time this creates a profile of the user's interests and job-search behavior, which is privacy-sensitive and unnecessary to store silently.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/setup_rag.py (reported line 26)May include surrounding context.

python
req_file = os.path.join(os.path.dirname(__file__), "requirements.txt")
    if os.path.exists(req_file):
        print("[SETUP] Installing dependencies...")
        subprocess.run([sys.executable, "-m", "pip", "install", "-r", req_file, "-q"], check=True)
        print("[OK] Dependencies installed")
    else:
        print("[WARN] requirements.txt not found, installing core packages...")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/setup_rag.py (reported line 31)May include surrounding context.

python
else:
        print("[WARN] requirements.txt not found, installing core packages...")
        packages = ["chromadb", "sentence-transformers"]
        subprocess.run([sys.executable, "-m", "pip", "install"] + packages + ["-q"], check=True)

def init_directories():
    os.makedirs(DATA_DIR, exist_ok=True)

Static analysis

No suspicious patterns detected.