T01 · Skill Instruction Hijacking
- Location
scripts/draft_cover_letter.py:129- Finding
Untrusted job descriptions are inserted directly into an agent-executed prompt
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is aligned with automated job applying, but it needs review because it can submit applications and reuse or transmit sensitive personal data with incomplete consent and disclosure controls.
Review this skill carefully before installing. Use it only if you are comfortable giving it resume API access, letting it fill and submit job applications, and storing sensitive preferences locally. Confirm every application before submission, avoid saving sensitive or legal-consent answers for reuse, and restrict or delete the local preferences and resume files after use.
scripts/draft_cover_letter.py:129Untrusted job descriptions are inserted directly into an agent-executed prompt
references/screening_questions.md:30The Skill automatically grants consent to background checks and drug screening
scripts/manage_preferences.py:97Sensitive preferences and full resumes are written without restrictive file permissions
SKILL.md:85Privacy documentation incorrectly claims saved preferences are never transmitted
scripts/log_application.py:129Cover letters can be uploaded to ResumeX without being disclosed in the external-data policy
The declared description promises a broad, end-to-end job hunting and auto-application capability. In contrast, the actual code only loads a local resume JSON file, formats selected resume/job details, and outputs a prompt intended for an internal LLM to draft a cover letter. This is a materially different primary purpose. The code does not perform any of the core declared actions: no web search, no matching logic, no approval workflow, no browser control, no form filling, no submission, and no tracking/logging. While the code is tangentially related to job applications, it represents only a narrow support task (cover-letter drafting) rather than the declared automation skill.
This is a clear description-behavior mismatch. The declared purpose describes a comprehensive automated job search and application system. The code chunk is a CLI utility focused narrowly on retrieving resume data from resumex.dev and optionally extracting fields, saving JSON, or printing a textual summary. Accessing resumex.dev is consistent with part of the description, but the overwhelming majority of the declared functionality is absent. The primary purpose of the actual code is resume fetching/inspection, not finding or applying to jobs.
The description presents an end-to-end auto job application system. This code chunk is only a form-field mapping helper for job applications. It reads a resume file from disk, optionally reads preferences, resolves labels like 'First Name' or 'Email' to resume values, derives a few fields such as years of experience, and emits JSON summaries for mapping or coverage. Although the header comment mentions browser automation instructions and an environment variable for RESUMEX_API_KEY, the implemented commands all require --resume and never actually call resumex.dev, perform web search, drive a browser, submit forms, or log applications. Therefore the code's actual behavior is a narrow supporting component, not the broader declared skill behavior.
There is a clear description-behavior mismatch. The declared purpose describes a comprehensive automated job search and application system, but the code shown only constructs a payload and posts it to ResumeX job-tracker endpoints. Its primary purpose is logging an application entry, not searching for jobs or applying to them. Access to resumex.dev is consistent with one small declared subfeature (logging), but the main advertised capabilities are absent from this code chunk.
The declared description presents a full job-search and auto-application system integrated with resumex.dev, web search, and browser control. The supplied code chunk does none of those things. Instead, it manages persistent user preferences and screening answers through a command-line interface and stores them in a local JSON file. While preference storage could be a supporting component of a larger auto-applier skill, this chunk’s actual primary behavior is materially different from the declared end-user functionality and lacks the core declared capabilities entirely. Therefore this code chunk does not accurately represent the declared description.
The description presents an end-to-end automatic job hunting and application system. This code chunk is much narrower: it is a local CLI utility for constructing search queries and transforming/scoring job data. It does not contact resumex.dev, make network requests, control a browser, submit forms, or log anything externally. While the code is plausibly a supporting component of a larger auto-job-applier system, the declared description materially overstates what this supplied code chunk actually does.
The skill instructs the agent to always activate for very broad job-seeking phrases, even when the user has not mentioned resumex or consented to resume retrieval, web search, persistent storage, or browser automation. In a skill that can fetch sensitive resume data, save local preferences, and submit applications externally, broad triggers materially increase the risk of unintended activation and privacy-invasive actions.
Referenced artifact was not completely inspected
| `SKILL.md` | This file — main instructions for the agent |
The script builds and returns a raw LLM prompt that directly embeds untrusted resume fields and job description text without any delimiting, escaping, or instruction isolation. Because the surrounding skill uses browser automation and application submission, attacker-controlled content in a resume or job posting could inject instructions into the downstream model, causing manipulated cover letters, disclosure of embedded data, or undesired agent behavior if the consuming agent treats the prompt as authoritative.
Write the cover letter now:"""
return prompt
def main():
The README explicitly states that the skill activates automatically on very broad phrases like 'apply to jobs', 'job search', 'find jobs for me', and 'job hunting'. Because this skill can fetch resume data, search external sites, and automate applications, broad trigger language increases the chance of unintended invocation and privacy-impacting or action-taking behavior from casual user wording.
The skill requests and describes capabilities that include environment access, local file read/write, network access, and browser-driven automation, but it does not declare a constrained tool scope such as explicit permissions or allowed tools. In a skill that handles resumes, personal identifiers, and automated web actions, missing scope boundaries increases the chance of over-privileged execution and unintended data access or transmission.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
> when prompted during a form fill). This file is stored **locally only** and is **never sent
> to resumex.dev or any other server**. Review and restrict its filesystem permissions if needed:
> ```bash
> chmod 600 data/user_preferences.json
> ```
> To clear all saved preferences at any time:
> ```bash
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
> when prompted during a form fill). This file is stored **locally only** and is **never sent
> to resumex.dev or any other server**. Review and restrict its filesystem permissions if needed:
> ```bash
> chmod 600 data/user_preferences.json
> ```
> To clear all saved preferences at any time:
> ```bash
The file mandates 'Professional but human tone' for generated cover letters without offering user choice on language, locale, or style preferences. This imposes a fixed communication style rather than allowing the user to opt in or specify their preferred language/locale.
The skill explicitly transmits application metadata to an external service using an API key, including company, position, URL, status, and notes. Although this behavior is disclosed and related to the skill's purpose, it still constitutes external transmission of user activity data and becomes security-relevant because it involves persistent logging to a third-party service.
Or via curl:
curl -s -X POST "https://resumex.dev/api/v1/agent/jobs" \
-H "Authorization: Bearer $RESUMEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
The document instructs the agent to reuse answers from user_preferences.json, including highly sensitive employment, compensation, and demographic data, but does not clearly warn that these values are stored persistently and reused across future applications. In the context of an auto-job-apply skill that submits forms automatically, this can cause users to disclose sensitive information without informed consent and creates privacy risk if local preference data is retained or accessed later.
The instructions tell the agent to save user-provided answers directly to disk via manage_preferences.py set without requiring a warning, confirmation, or consent flow. Because this skill handles sensitive PII and protected-category application answers, silent persistence increases the chance of unintended retention, later misuse in other applications, or exposure from local file compromise.
The file provides operational guidance for automating job applications and form filling across third-party job boards and ATS platforms, but it does not require a clear user-facing warning that the agent will transmit highly sensitive personal data such as resume contents, contact details, employment history, and possibly cover letters to external sites. In this skill context, that omission is more dangerous because the broader skill is explicitly designed to fetch full resume data from resumex.dev and then submit applications automatically, increasing the risk of unintended disclosure or submission without informed user consent.
The apply-method heuristics label several destinations as 'auto-apply' and instruct the agent to fill and submit forms, but they do not impose a user confirmation requirement immediately before submission. In this skill, that is particularly risky because the agent is intended to act at scale across many job sites, so missing confirmations can lead to mass unintended submissions, privacy exposure, and reputational harm from applying to unsuitable roles or sharing stale/inaccurate resume data.
The file states that new screening answers are saved for future reuse, but it does not clearly disclose to the user that personal application responses will be persisted across sessions. Because screening answers can include sensitive employment and eligibility information, silent persistence increases privacy risk and can lead to reuse of stale or overly personal data without informed consent.
The workflow instructs the agent to save generated or user-provided answers broadly, while the reference includes highly sensitive data types such as salary expectations, date of birth, phone number, and work authorization. Persisting this information without strong minimization, sensitivity labeling, and consent controls creates meaningful privacy and compliance risk, especially since the skill automates repeated submissions to third-party job sites.
The guidance tells the agent to read JOB_TYPE from the environment to answer an application question, even though employment preference is user-specific profile data that should come from explicit user settings or prior consented preferences. Pulling it from environment state creates an unjustified side channel that can leak or misuse host/runtime configuration and may cause the agent to submit incorrect applications based on non-user data.
The script allows saving the user's full resume, including sensitive personal data, to any caller-supplied local path without restriction, minimization, or explicit consent guardrails. In the context of an auto-job-applier skill that already handles resume data and browser automation, this increases the risk of unnecessary local persistence, accidental exposure, or abuse by other components that can choose a path in sensitive or shared locations.
The code writes full resume contents to disk with no warning that the data contains highly sensitive PII such as contact details, employment history, and potentially other identifying information. This creates a privacy and security risk because users or downstream automation may store the file in insecure, shared, or monitored locations, making disclosure more likely.
The script prints resolved field values and coverage results directly to stdout, which can include sensitive resume and preference data such as email, phone number, location, salary expectations, work authorization, date of birth, and other personal details. In an agent/browser-automation skill context, stdout is often captured by logs, orchestration layers, or other tools, so this creates a real risk of unintended disclosure beyond the immediate caller.
No suspicious patterns detected.