Back to skill

Security audit

ChatGPT Web Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to do what it claims, but it needs Review because it handles persistent ChatGPT login state and browser automation with several under-scoped local security risks.

Install only if you are comfortable letting this skill reuse a logged-in ChatGPT web session and store browser/session artifacts locally. Use a dedicated low-privilege account or isolated environment, avoid sensitive prompts, review and clear data/ and any chatgpt-profile-* temporary directories, and be aware that first-run setup downloads dependencies and a browser.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/browser_utils.py:172
Finding

Authenticated Browser Profile Persists in an Unmanaged Temporary Directory

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/config.py:158
Finding

Chromium Sandbox Is Disabled for Remote Web Content

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/setup_environment.py:42
Finding

Automatic Dependency and Browser Installation Lacks Integrity Verification

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run.py:31
Finding

Script Runner Permits Path Traversal and Execution Outside the Approved Scripts Directory

Content
View full analysis
[args...]") print(" or: ./scripts/run.py [args...]") print("Available scripts: auth_manager.py, ask_chatgpt.py, chat_manager.py, session_manager.py, cleanup_manager.py") return 1 script_name = sys.argv[1] script_args = sys.argv[2:] if script_name.startswith("scripts/"): script_name = script_name[8:] if not script_name.endswith(".py"): script_name += ".py" skill_dir = Path(__file__).parent.parent script_path = skill_dir / "scripts" / script_name if not script_path.exists(): print(f"❌ Script not found: {script_name}") print(f" Looked for: {script_path}") return 1 venv_python = ensure_venv() cmd = [str(venv_python), str(script_path)] + script_args try: result = subprocess.run(cmd) return result.returncode ``` ### Technical Analysis The runner displays an approved list of scripts but does not enforce it. User-controlled `script_name` is joined to the `scripts` directory without rejecting path separators or verifying that the resolved path remains beneath that directory. A value such as `../untrusted.py` resolves outside `scripts/`. In addition, `pathlib` discards the preceding path when joining an absolute path, allowing an existing absolute `.py` path to be selected. The existence check confirms only that the target exists, not that it is an approved Skill script. This flaw requires an attacker to influence the runner's first argument and identify or place an accessible Python file. It does not independently create arbitrary source code. ### Attack Path 1. An attacker places a malicious Python file in a location writable by the attacker, or identifies an existing Python file with useful execution behav ...[truncated 925 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises substantial functionality related to controlling ChatGPT through a browser and managing conversations and session state. The supplied code chunk does not implement any of these behaviors; it is only an empty package initializer with a docstring. This is a material mismatch between the described purpose and the actual provided code.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/browser_utils.py (reported line 93)May include surrounding context.

python
display = BrowserFactory._discover_display()
        if not display:
            return None
        launch_env = os.environ.copy()
        launch_env["DISPLAY"] = display
        return launch_env

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README explicitly advertises local persistence of conversation/session metadata and optional proof screenshots, but it does not clearly warn users that these artifacts may contain sensitive prompt contents, account-linked data, or screenshots of private conversations. In a browser-automation skill that reuses a logged-in ChatGPT session, this omission increases the risk of unintentional retention and disclosure of sensitive data on disk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill explicitly instructs use of local shell execution, browser automation, persistent filesystem storage, and networked interaction, but it declares no tool scope or permission boundaries. That makes the skill over-privileged by default and increases the chance that an agent or user invokes powerful capabilities without clear consent or isolation, especially around login state and local data access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill advertises persistent browser login state, cookies, storage state, and conversation metadata stored locally, but it does not present a prominent privacy warning or retention notice. This is dangerous because sensitive authentication material and chat history may remain on disk and be exposed to other local processes, backups, or later users of the same environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill supports proof and debug screenshots and stores them on disk, but it does not clearly warn that screenshots may capture full conversation contents, account details, or other sensitive page data. In this context, screenshots are especially risky because they can preserve secrets outside the normal conversation store and may be shared or retained unintentionally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file documents potentially destructive operations such as reset, close, gc, and delete but provides no warning about possible loss of session or conversation state. For markdown files, missing disclosures about behaviors that could affect user data or system integrity should be flagged when the description omits cautionary guidance.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: python-dotenv==1.0.0 — 2 advisory(ies): CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via ); CVE-2026-28684 (python-dotenv reads key-value pairs from a .env file and can set them as environ)

Medium
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is pinned to python-dotenv==1.0.0, and the provided advisory indicates a symlink-following issue in set_key that can lead to arbitrary file overwrite when modifying .env files. In a browser-automation skill with persistent local state and login context, unsafe dotenv file handling is more concerning because local credential or configuration files may exist alongside the skill and could be overwritten if vulnerable code paths are used.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code automates a browser session to submit arbitrary user-provided prompts to the ChatGPT web UI, but the file contains no user-consent, disclosure, or policy guardrails before transmitting that content to a third-party service. In a skill designed for persistent logged-in browser automation and reusable sessions, this creates a real privacy and data-handling risk because sensitive prompts may be sent externally without explicit acknowledgement or scoping controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code reads proxy-related environment variables, including URLs that may embed usernames and passwords, and passes those credentials into browser launch settings. The file contains no confirmation prompt, logging, or explanatory comment/docstring warning the user that environment-sourced network credentials may be consumed and used for outbound traffic.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The function loads cookies from a persistent state file on disk and injects them directly into a browser context, which can silently reuse an authenticated session. In an agent skill that automates ChatGPT web access with persistent login state, this increases the chance of unintended account access, session confusion, or use of stale/borrowed credentials if the state file is shared, replaced, or insufficiently protected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code deletes entire runtime and screenshot directories via shutil.rmtree, which is a destructive operation affecting user or system data. Although the script prints a result after completion, there is no confirmation prompt, pre-action warning, or explanatory comment/docstring disclosing that these targets will be fully removed and recreated.

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/run.py (reported line 25)May include surrounding context.

python
if not venv_dir.exists():
        print("🔧 First-time setup: creating virtual environment...")
        result = subprocess.run([sys.executable, str(setup_script)])
        if result.returncode != 0:
            print("❌ Failed to set up environment")
            sys.exit(1)

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/run.py (reported line 59)May include surrounding context.

python
cmd = [str(venv_python), str(script_path)] + script_args

    try:
        result = subprocess.run(cmd)
        return result.returncode
    except KeyboardInterrupt:
        print("\n⚠️ Interrupted by user")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The code launches a background daemon using subprocess.Popen with stdio redirected to DEVNULL, which hides the action from the user. In this file there is no confirmation prompt, print/log message, or explanatory comment/docstring near the operation disclosing that a persistent background process will be started.

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/session_manager.py (reported line 214)May include surrounding context.

python
return
        self._cleanup_stale_runtime_files()
        cmd = [sys.executable, str(Path(__file__).resolve()), "_serve"]
        subprocess.Popen(
            cmd,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,

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_environment.py (reported line 45)May include surrounding context.

python
if self.requirements_file.exists():
            print("📦 Installing dependencies...")
            try:
                subprocess.run([str(self.venv_pip), "install", "--upgrade", "pip"], check=True)
                subprocess.run([str(self.venv_pip), "install", "-r", str(self.requirements_file)], check=True)
                print("🌐 Installing Google Chrome for Patchright...")
                try:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
81% confidence
Finding

Installing dependencies from requirements.txt causes arbitrary package installation and execution of package build/install hooks from a file local to the skill. In the context of an agent skill, this is more sensitive because a tampered or unreviewed dependency list can execute attacker-controlled code during environment setup and compromise the host running the skill.

Content

Scanner excerpt · scripts/setup_environment.py (reported line 46)May include surrounding context.

python
print("📦 Installing dependencies...")
            try:
                subprocess.run([str(self.venv_pip), "install", "--upgrade", "pip"], check=True)
                subprocess.run([str(self.venv_pip), "install", "-r", str(self.requirements_file)], check=True)
                print("🌐 Installing Google Chrome for Patchright...")
                try:
                    subprocess.run([str(self.venv_python), "-m", "patchright", "install", "chrome"], check=True)

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_environment.py (reported line 49)May include surrounding context.

python
subprocess.run([str(self.venv_pip), "install", "-r", str(self.requirements_file)], check=True)
                print("🌐 Installing Google Chrome for Patchright...")
                try:
                    subprocess.run([str(self.venv_python), "-m", "patchright", "install", "chrome"], check=True)
                except subprocess.CalledProcessError as error:
                    print(f"⚠️ Warning: failed to install Chrome automatically: {error}")
                    print("   Run manually if needed: python -m patchright install chrome")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code persists authentication-related information to disk via AuthInfoStore.save() without any visible protection, warning, or minimization in this file. In the context of a browser-automation skill with persistent login state, storing auth data unencrypted in local JSON can expose session material or tokens to other local users, malware, backups, or accidental disclosure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The example on this line uses a Chinese-language question as the only concrete prompt example, which can imply a fixed language expectation in the skill reference. Under the policy, language or locale constraints should either be optional, user-selected, or clearly documented as intentionally region-specific.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/cleanup_manager.py (reported line 48)May include surrounding context.

python
manager = CleanupManager()
    try:
        payload = getattr(manager, args.target)()
    except Exception as error:
        payload = result_from_exception(error)

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The file persists session and daemon metadata to storage via save_json_file, which is a file-write operation affecting local user data. This file does not provide a user-facing notice, confirmation, or explanatory comment/docstring that session details will be stored on disk.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.