Back to skill

Security audit

Phy Devto Post

Security checks for vulnerabilities and agentic risk

Overview

This skill is for publishing to DEV.to, but it can immediately post publicly from the user's logged-in Chrome session without a required review or confirmation step.

Review this skill carefully before installing. It is not evidence of malware, but it can publish live DEV.to posts through your logged-in Chrome account. Prefer using it only after adding a draft-first workflow, an explicit confirmation step showing the title/tags/account, and safer temporary-file handling for long articles.

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
SKILL.md:112
Finding
Predictable Shared Temporary Files Permit Draft Disclosure, File Clobbering, and Content Substitution## Vulnerability Details **File Location**: `SKILL.md`, lines 112-125 **Vulnerability Type**: Predictable and insecure temporary-file handling **Risk Level**: Medium ### Vulnerable Code ```bash # Write article content to temp JSON file python3 -c " import json with open('/tmp/devto_body.md') as f: body = f.read() with open('/tmp/devto_body.json', 'w') as f: json.dump(body, f) " # Use JXA to read the file and publish osascript -l JavaScript -e ' var chrome = Application("Google Chrome"); var tab = chrome.windows[0].activeTab; var body = JSON.parse($.NSString.alloc.initWithContentsOfFileEncodingError("/tmp/devto_body.json", $.NSUTF8StringEncoding, null).js); tab.execute({javascript: "(async()=>{try{var csrf=document.querySelector(\"meta[name=csrf-token]\").getAttribute(\"content\");var resp=await fetch(\"/articles\",{method:\"POST\",headers:{\"Content-Type\":\"application/json\",\"X-CSRF-Token\":csrf},credentials:\"include\",body:JSON.stringify({article:{title:\"YOUR TITLE\",body_markdown:" + JSON.stringify(body) + ",tags:[\"tag1\",\"tag2\"],published:true}})});var r=await resp.json();document.title=r.current_state_path?\"OK:\"+r.current_state_path:\"ERR:\"+JSON.stringify(r)}catch(e){document.title=\"ERR:\"+e.message}})()"}); ' ``` ### Technical Analysis The file-based publishing workflow uses fixed, globally predictable paths under the shared `/tmp` directory: - `/tmp/devto_body.md` - `/tmp/devto_body.json` The output file is opened with Python's ordinary write mode without secure exclusive creation, ownership validation, file-type validation, explicit restrictive permissions, or protection against symbolic links. The subsequent JXA process reopens the same predictable path without confirming that it still refers to the file created by the publishing workflow. This creates several local attack opportunities: 1. **Symbolic-link file clobbering:** A local process can pre-create `/tmp/devto_bod ...[truncated 3504 chars]
Remediation
## Remediation Suggestions 1. **Create an unpredictable private temporary directory.** Use Python's `tempfile.TemporaryDirectory()` or `tempfile.NamedTemporaryFile()` rather than fixed names under `/tmp`. 2. **Enforce restrictive permissions.** Create temporary files with mode `0600` and their containing directory with mode `0700`, independent of the user's `umask`. 3. **Prevent symbolic-link attacks.** Use atomic exclusive creation through `tempfile.mkstemp()` or flags equivalent to `O_CREAT | O_EXCL | O_NOFOLLOW`. Do not reopen a predictable pathname without validating it. 4. **Validate before reading.** If the file must be passed between Python and JXA, verify that it is a regular file, owned by the current user, not a symbolic link, and has restrictive permissions. Prefer retaining an open file descriptor where practical. 5. **Minimize the race window.** Generate the unpredictable path and immediately pass that exact path to JXA. Avoid separate commands that expose a stable pathname between writing and reading. 6. **Delete sensitive files reliably.** Remove temporary article files in a `finally` block or rely on a scoped temporary directory that is deleted after publication, including when publication fails. 7. **Avoid disk staging when possible.** Pass the article through standard input, a protected pipe, or another in-memory mechanism to prevent persistent plaintext drafts. A safer Python implementation should follow this pattern: ```python import json import os import tempfile source_path = "/path/to/user-selected/article.md" with open(source_path, "r", encoding="utf-8") as source: body = source.read() fd, temporary_path = tempfile.mkstemp( prefix="devto-", suffix=".json" ) try: os.fchmod(fd, 0o600) with os.fdopen(fd, "w", encoding="utf-8") as temporary_file: json.dump(body, temporary_file) # Pass temporary_path directly to the JXA process. # Validate ownership ...[truncated 286 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill description does not clearly warn that it will control the user's real Chrome session, use their authenticated DEV.to account, and potentially publish content publicly. In this context, omission of that warning undermines informed consent and makes accidental account actions more dangerous than a normal drafting-only skill.

Missing User Warnings

High
Confidence
99% confidence
Finding
The recommended workflow performs a direct authenticated POST to DEV.to with 'published: true', causing immediate live publication without any explicit review or confirmation checkpoint. Since it leverages the user's browser session and CSRF token, any mistaken invocation, prompt confusion, or manipulated content could result in unauthorized or unintended public posts from the user's account.

Missing User Warnings

High
Confidence
98% confidence
Finding
The fallback workflow programmatically clicks the Publish button with no mandatory confirmation or human review step. In a browser-automation skill operating on a real logged-in session, this creates a clear path to accidental or unauthorized publication of content under the user's identity.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger text includes a broad catch-all phrase covering essentially any DEV.to publishing request, which increases the chance the skill activates in situations the user did not specifically intend. Because this skill can drive a logged-in browser session and publish content live, overbroad activation materially raises the risk of unintended high-impact actions.

Static analysis

No suspicious patterns detected.