Back to skill

Security audit

Neckr0ik Freelance Automator

Security checks for vulnerabilities and agentic risk

Overview

This skill is presented as real freelance-platform automation, but the inspected code mostly creates local synthetic job records and drafts, which could mislead users running a freelance business.

Review this carefully before installing. Treat its job results as generated examples unless the publisher adds real platform integrations and clear labeling. Do not rely on it to send client messages, invoices, proposals, or platform actions without manual review. Avoid using sensitive client data with proposal generation unless you are comfortable sending it to a local Ollama model, and be aware it stores business records under ~/.freelance-automator.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/freelance.py:238
Finding
Path Traversal in Job File Lookup<![CDATA[ ## Vulnerability Details **File Location**: `scripts/freelance.py`, lines 238-246 **Vulnerability Type**: Path traversal / arbitrary JSON file read **Risk Level**: Medium ### Vulnerable Code ```python # Load job job_file = self.jobs_dir / f"{job_id}.json" if not job_file.exists(): print(f"✗ Job not found: {job_id}") return None job_data = json.loads(job_file.read_text()) job = Job(**job_data) ``` The affected `job_id` value originates from the command-line interface: ```python prop_parser.add_argument('--job-id', required=True) ``` ### Technical Analysis The application constructs a file path by directly interpolating the user-controlled `job_id` into a filename. It does not reject absolute paths, path separators, or `..` traversal components. It also does not resolve the resulting path and verify that it remains within `self.jobs_dir`. Consequently, a value such as `../../external-job` can resolve to `../../external-job.json` outside the intended `~/.freelance-automator/jobs` directory. An absolute path can similarly override the base directory under `pathlib` path-joining semantics. The selected file must contain valid JSON whose keys are compatible with the `Job` dataclass. This requirement limits generic arbitrary-file disclosure, but an attacker can still read a compatible file outside the jobs directory. Values loaded from that file are subsequently inserted into the Ollama proposal prompt. If Ollama is unavailable, portions of the job data may also be reflected in the fallback proposal and displayed or stored. Because external job fields are treated as LLM prompt content without trust boundaries, a malicious compatible JSON document can additionally contain prompt-injection instructions that influence the generated proposal. This is a secondary consequence of the path traversal rather than a separate confirmed Agent instruction-hijacking issue. ### Attack Path 1. The attacker creates or identifies a readable JSON file outsi ...[truncated 1672 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict job identifiers to the exact generated identifier format: ```python import re if not re.fullmatch(r"job-[0-9]+-[a-f0-9]{8}", job_id): raise ValueError("Invalid job ID") ``` 2. Resolve both paths and enforce containment within the jobs directory: ```python jobs_root = self.jobs_dir.resolve() job_file = (jobs_root / f"{job_id}.json").resolve() if not job_file.is_relative_to(jobs_root): raise ValueError("Job path escapes the jobs directory") ``` 3. Explicitly reject path separators, absolute paths, `.` components, and `..` components before accessing the filesystem. 4. Open files defensively and handle parsing and schema failures without exposing sensitive path or content information: ```python try: job_data = json.loads(job_file.read_text(encoding="utf-8")) job = Job(**job_data) except (OSError, json.JSONDecodeError, TypeError) as exc: raise ValueError("Invalid job record") from exc ``` 5. Validate loaded fields by type, length, and allowed character set before incorporating them into an LLM prompt. 6. Clearly delimit untrusted job data in the prompt and instruct the model to treat it only as data, not as instructions. Where proposal integrity is important, add output validation before printing or persisting generated content. 7. Add regression tests covering absolute paths, nested traversal sequences, encoded or mixed separators, nonexistent files, malformed JSON, and symbolic-link containment. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documentation claims real automation across Upwork, Fiverr, Freelancer, and PeoplePerHour, including job finding, proposal handling, and delivery, but the implementation reportedly only fabricates example jobs and performs local generation/storage. This mismatch is dangerous because users may rely on false assumptions about external actions, leading to business decisions, accidental disclosure of data, or trust in outputs that were never validated against real platforms.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill advertises operational CLI behaviors and references an implementation script with file and shell capabilities, but it does not declare any explicit tool scope or permission boundaries. In an agent ecosystem, missing scope declarations can cause over-broad access assumptions and make it easier for the skill to read, write, or invoke commands beyond what a user expects.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
Promoting automated client responses and follow-up messaging without warning about review requirements or unintended outbound communication can cause the system to send inaccurate, inappropriate, or sensitive messages automatically. In a freelance-business context, that can damage client relationships, leak project details, or violate platform communication policies.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill explicitly describes sending invoices directly to client email without mentioning confirmation, recipient verification, or safeguards around external transmission. That creates a risk of accidental outbound delivery to the wrong party, unauthorized disclosure of billing information, or spam-like behavior initiated without adequate user review.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The tool claims to find freelance jobs but actually fabricates realistic-looking listings and persists them as if they were genuine search results. In an automation skill for running a freelance business, this is dangerous because it can mislead users into acting on false opportunities, producing fraudulent proposals, wasted effort, and potentially reputational or financial harm.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
Proposal generation sends job and client-related content to an ollama subprocess without explicit user consent or a clear disclosure at the point of use. In this skill context, users may include client names, project details, budgets, or sensitive work descriptions, so silent transmission to another processing component creates a data-handling and confidentiality risk.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
Keep it under 300 words."""

        try:
            result = subprocess.run(
                ["ollama", "run", "llama3.2:latest", prompt],
                capture_output=True,
                text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Low
Confidence
76% confidence
Finding
The generated invoice text always includes `Crypto (USDC/USDT)` alongside other payment methods. This imposes a specific payment/locale/business-policy choice in natural-language output rather than offering the user a choice or making it configurable.

Static analysis

No suspicious patterns detected.