Back to skill

Security audit

NextJS Frontend Development + Integration

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real UI-development skill, but it includes overbroad host, browser, dependency, and process-management instructions that users should review before installing.

Use this only in a disposable or well-isolated workspace. Decline nginx/sudo setup unless you intentionally want external preview exposure, review every npm/npx command, validate project names before shell use, avoid screenshots of private/authenticated pages, and do not run broad PM2 or kill commands on a shared host.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/screenshot.sh:5
Finding
Unrestricted Screenshot Target and Output Path with Chromium Sandbox Disabled<![CDATA[ ## Vulnerability Details **File Location**: `scripts/screenshot.sh:5-16` **Vulnerability Type**: Server-side request forgery-like internal resource access, arbitrary file output, and unsafe browser execution **Risk Level**: High ### Vulnerable Code ```bash URL="${1:?Usage: screenshot.sh <url> <output_path> [width] [height]}" OUTPUT="${2:?Output path required}" WIDTH="${3:-1400}" HEIGHT="${4:-900}" # Use a temp HTML that loads the target in an iframe after delay, # or use virtual-time-budget to let JS execute chromium --headless --disable-gpu --no-sandbox --disable-dev-shm-usage \ --window-size="${WIDTH},${HEIGHT}" \ --screenshot="$OUTPUT" \ --hide-scrollbars \ --virtual-time-budget=5000 \ "$URL" 2>/dev/null ``` ### Technical Analysis The script accepts an arbitrary URL and output path without validating either value. Chromium can consequently be directed to network locations beyond the intended local preview server, including loopback services, private-network applications, and potentially cloud instance metadata endpoints. The unrestricted output argument also allows the caller to select any path writable by the current operating-system user. Existing files at those paths may be replaced by screenshot data. Symbolic links and sensitive application paths are not rejected. Chromium is launched with `--no-sandbox`. This removes an important containment boundary and increases the impact of a browser vulnerability or malicious page loaded by the script. Although sandbox disabling is sometimes used in restricted containers, the script does not detect such an environment or limit this behavior to cases where it is necessary. The intended visual-review functionality only requires access to the generated application on a known loopback port and output into a controlled temporary directory. Arbitrary network access, arbitrary output paths, and disabling the browser sandbox exceed those minimum requirements. ### Attack Path 1. An attacker per ...[truncated 1457 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict screenshot targets to the intended development service: - Allow only `http://localhost:3002` and explicitly approved routes by default. - Parse URLs with a robust URL parser rather than string-prefix checks. - Reject embedded credentials, redirects to unapproved hosts, non-HTTP schemes, and alternate IP representations. - Resolve hostnames and block loopback, link-local, private, multicast, and metadata ranges unless individually required and approved. 2. Constrain output files: - Create a dedicated directory with restrictive permissions using `mktemp -d`. - Generate output filenames internally instead of accepting arbitrary paths. - If caller-selected names are necessary, accept only basenames and reject traversal components and symbolic links. - Avoid overwriting existing files and verify the destination with safe, race-resistant file operations. 3. Remove `--no-sandbox`. If a documented container environment truly requires it, fail closed by default and require an explicit, informed opt-in. 4. Validate width and height as bounded positive integers to prevent malformed arguments and excessive resource consumption. 5. Do not automatically share screenshots of non-public or authenticated pages. Require confirmation describing the screenshot target and recipient before transmission. ]]>

T08 · Insecure Dependencies

Error
Location
SKILL.md:251
Finding
Mutable and Unpinned Third-Party Package Execution<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:251-364` **Vulnerability Type**: Third-party software supply-chain exposure **Risk Level**: High ### Vulnerable Code ```bash npx create-next-app@latest <project-name> \ --typescript \ --tailwind \ --app \ --no-src-dir \ --import-alias "@/*" ``` ```bash npm install axios @tanstack/react-query npm install -D @types/node ``` ```bash npx shadcn-ui@latest init ``` ```bash npx shadcn-ui@latest add button card input label select textarea npx shadcn-ui@latest add dropdown-menu dialog sheet tabs npx shadcn-ui@latest add table form avatar badge separator toast ``` ```bash npm install react-hook-form @hookform/resolvers zod ``` ### Technical Analysis The workflow uses `npx ...@latest`, which retrieves and executes whatever release is associated with the mutable `latest` tag at invocation time. The audited Skill therefore does not fully define the code that will execute. Other packages are installed without exact versions in the command examples. No reviewed lockfile or integrity-verification procedure is supplied. Installation can execute package lifecycle scripts with the privileges of the Agent or user running npm. This does not establish that any named package is malicious. The vulnerability is that a future compromised release, package-maintainer account, registry response, or transitive dependency can change the effective executable payload after the Skill has been reviewed. ### Attack Path 1. A package maintainer account, package release, registry, or transitive dependency is compromised. 2. The mutable `latest` tag or an unconstrained dependency resolves to the compromised version. 3. The Skill executes `npx` or `npm install` during project generation. 4. The downloaded CLI code or an installation lifecycle script runs locally. 5. Malicious code inherits the filesystem, network, environment-variable, and process privileges of the invoking account. 6. The payload can modify the gene ...[truncated 867 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace mutable tags with reviewed, exact versions, for example `package-name@x.y.z`. 2. Commit a lockfile and use `npm ci` for reproducible installation. 3. Review and update pinned versions through a controlled dependency-update process. 4. Verify registry identity and package integrity before execution. 5. Avoid automatic `npx` execution where possible: - Install an approved CLI version as a locked development dependency. - Invoke the locked local binary. 6. Require explicit user approval before downloading or executing a previously unavailable CLI. 7. Consider disabling lifecycle scripts during initial installation with `--ignore-scripts`, then explicitly permit only reviewed scripts where functionality requires them. 8. Run package installation in an isolated, unprivileged environment with minimal filesystem access, network access, and environment variables. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:563
Finding
Command Injection Through Unvalidated Project Name Substitution<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:563-569` **Vulnerability Type**: Shell command injection **Risk Level**: Critical ### Vulnerable Code ```bash # Stop any existing instance of this project pm2 delete <project-name> 2>/dev/null || true # Start with PM2 (port 3002 for nginx proxy) PORT=3002 pm2 start npm --name "<project-name>" --cwd "$(pwd)" -- run dev ``` The same user-derived placeholder is also placed into project-creation commands: ```bash npx create-next-app@latest <project-name> \ --typescript \ --tailwind \ --app \ --no-src-dir \ --import-alias "@/*" ``` ### Technical Analysis The workflow asks the user for a project name and later interpolates that value into shell commands. In particular, `pm2 delete <project-name>` and the project-creation command place the value in an unquoted shell position. If an Agent replaces the placeholder literally with attacker-controlled text, shell metacharacters such as semicolons, command substitutions, redirection operators, or logical operators can alter the command structure. Quoting the value in the `--name` argument alone does not address the other unquoted occurrences. Even quoted shell interpolation requires care because generated command text can be mishandled by the Agent before execution. A strict project-name allowlist and argument-oriented process invocation are therefore necessary. ### Attack Path 1. The Skill asks the requester to provide a project name. 2. An attacker provides a crafted value containing shell syntax, such as a semicolon followed by another command. 3. The Agent substitutes that value into `pm2 delete <project-name>` or `npx create-next-app@latest <project-name>`. 4. The resulting command is passed to a shell. 5. The shell interprets the injected syntax as additional commands. 6. The injected command executes with all privileges and environmental access held by the Agent's operating-system account. ### Impact Assessment Successful exploitati ...[truncated 651 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate the project name before using it. A suitable conservative rule is: ```text ^[a-z0-9][a-z0-9_-]{0,63}$ ``` 2. Reject names containing whitespace, path separators, dots used for traversal, shell metacharacters, command substitutions, or leading hyphens. 3. Quote every shell expansion consistently. Do not leave the project name unquoted in `pm2 delete` or project-creation commands. 4. Prefer APIs or subprocess argument arrays that bypass shell parsing. 5. Insert `--` before positional values where the called command supports end-of-options markers. 6. Generate a separate internal PM2 identifier rather than directly reusing arbitrary display names. 7. Display the validated project name and final operation to the user before execution. 8. Add security tests covering semicolons, backticks, `$()`, redirections, newlines, leading dashes, spaces, and traversal strings. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:1048
Finding
Troubleshooting Commands Can Terminate Unrelated Processes<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:1048-1071` **Vulnerability Type**: Overbroad process control and violation of least privilege **Risk Level**: High ### Vulnerable Code ```bash # Restart dev server: `pkill -f "next dev" && npm run dev` ``` ```bash # Check what's running pm2 list # Stop the conflicting process pm2 delete <project-name> # Or check port directly lsof -ti:3002 # Kill process on port (if not PM2-managed) kill -9 $(lsof -ti:3002) # Restart with PM2 PORT=3002 pm2 start npm --name "<project-name>" --cwd "$(pwd)" -- run dev ``` The document also recommends the following broad PM2 operation at `SKILL.md:1112`: ```bash pm2 delete all && pm2 list ``` ### Technical Analysis The troubleshooting workflow identifies processes through a broad command-line pattern, a shared TCP port, or the entire PM2 process registry. It does not verify that the selected process belongs to the generated project, was started by this Skill, or is safe to terminate. `pkill -f "next dev"` can match every Next.js development server owned by the executing user. `kill -9 $(lsof -ti:3002)` forcefully terminates any process bound to port 3002, even if it belongs to a different project. `pm2 delete all` removes every PM2-managed process for the current PM2 account. Using `SIGKILL` also prevents graceful cleanup and can cause data loss or corrupted temporary state. Managing one generated preview server only requires control over the exact process created for that project; global process matching exceeds that requirement. ### Attack Path 1. Another application or user project is running a Next.js process, is registered with the same PM2 account, or legitimately occupies port 3002. 2. The generated project encounters a module error or port conflict. 3. The Agent follows the documented troubleshooting instructions. 4. `pkill`, `kill -9`, or `pm2 delete all` selects processes without verifying ownership by the current project. 5. Unrelated services ...[truncated 1016 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Record the exact PID, PM2 identifier, working directory, and start time when launching the generated project. 2. Before termination, verify that: - The process is owned by the invoking account. - Its working directory matches the generated project. - Its executable and arguments match the expected development server. - Its PID is the one previously recorded by this Skill. 3. Remove `pkill -f "next dev"` and `pm2 delete all` from the workflow. 4. Do not terminate arbitrary port owners automatically. Report the conflict and request explicit user confirmation. 5. Use graceful shutdown signals such as `SIGTERM` first, wait for an appropriate timeout, and use `SIGKILL` only after confirmation and ownership validation. 6. Allocate an available unprivileged port dynamically instead of assuming port 3002 must be reclaimed. 7. Use a unique, validated PM2 process name and act only on that exact process. 8. Clearly distinguish processes created by the Skill from pre-existing system or user processes in all troubleshooting guidance. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (28)

Credential Access

High
Category
Privilege Escalation
Content
5. **Generate Features** - Build pages and components
6. **Build UI** - Use shadcn/ui components
7. **Visual Review** - Screenshot analysis (optional)
8. **Environment Setup** - .env configuration
9. **Scripts & Documentation** - README and package.json
10. **Export & Deploy** - Zip project and deployment guidance
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill is presented as UI scaffolding, but it also instructs browser-driven screenshot capture, local URL rendering, PM2 process management, and nginx-based publishing. This capability expansion matters because users or orchestrators may invoke the skill expecting harmless file generation, while it actually performs host and network operations that broaden attack surface and can expose locally running applications or sensitive content.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The skill recommends `sudo apt-get install chromium-browser` and `sudo apt-get install nginx`, granting or encouraging privileged package installation unrelated to core code scaffolding. This is dangerous because it normalizes elevation and system modification within a development skill, making accidental or coerced host compromise easier if the instructions are followed in sensitive environments.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The nginx setup instructs writing under `/etc/nginx` and reloading the system web server with `sudo`, which is infrastructure administration outside the stated scope of frontend scaffolding. Misuse can expose a development server externally, interfere with existing web services, or create an unintended ingress path to local content.

Chaining Abuse

High
Category
Tool Misuse
Content
}
  }
  ```
- **Enable**: `sudo ln -s /etc/nginx/sites-available/<project-name> /etc/nginx/sites-enabled/ && sudo systemctl reload nginx`
- **If declined**: Access directly via `http://localhost:3002` (PM2 port)

**Before starting, ask user if they want to enable optional features.**
Confidence
94% confidence
Finding
The chained `sudo ln -s ... && sudo systemctl reload nginx` combines multiple privileged operations in one step, reducing opportunities for review and making accidental misuse more likely. In this skill, chaining amplifies the risk of unintended infrastructure changes and external service exposure.

Credential Access

High
Category
Privilege Escalation
Content
├── styles/                             # Global styles
│   └── globals.css                     # Tailwind imports + custom styles
│
├── .env.local                          # Environment variables (gitignored)
├── .env.example                        # Environment variables template
├── .eslintrc.json                      # ESLint config
├── .prettierrc                         # Prettier config
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The README states the skill triggers on very generic requests like 'build', 'create', 'develop', and 'add features', which can cause the skill to activate outside a narrowly intended UI-development context. In an agent setting, overly broad activation increases the chance of unexpected code generation, project scaffolding, or modification of an existing repository when the user did not clearly request those actions.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The documented workflow includes project setup, dependency installation, environment setup, and export/deploy steps, but it does not warn users about filesystem changes, generated artifacts, or packaging outputs. In an automated agent context, this can lead to silent creation or modification of directories, config files, archives, and deployment-related assets, which is risky even if not overtly malicious.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The manifest says to use the skill when the user asks to "build, create, develop, or scaffold" a wide range of apps, and also when they ask to "add features" or "extend existing Next.js projects." These activation conditions are expansive and ambiguous enough to match many ordinary frontend or full-stack requests without clearly defining when this skill should or should not activate.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
Embedding PM2-based service management in a UI scaffolding skill introduces host-level process control beyond simple project generation. This increases risk because the skill can start, stop, persist, and manage processes on the host, which is unnecessary for many build-only tasks and can affect other workloads if misapplied.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
#### 1. Auto-Revision with Visual Review (requires Chromium)
- **What it does**: Takes screenshots during development to visually review designs and auto-fix issues
- **Installation**: `sudo apt-get install chromium-browser` (Debian/Ubuntu)
- **Privileges**: Read/write access to project files, execute chromium in headless mode
- **If declined**: Manual review only (you describe, user verifies)
Confidence
96% confidence
Finding
This line explicitly directs use of `sudo` to install Chromium. Encouraging root execution inside a broadly triggered development skill increases the chance of privilege misuse and broadens the blast radius of any mistaken or maliciously influenced action.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The live preview guidance exposes the app through nginx on an external port without a prominent warning about network exposure, authentication, or firewall implications. This can unintentionally publish in-progress applications, local APIs, or sensitive test data to other network users.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
#### 2. Live Preview Server (requires Nginx)
- **What it does**: Serves project on external port for live preview during development (useful for mobile testing or remote access)
- **Installation**: `sudo apt-get install nginx`
- **How it works**: PM2 runs dev server on port 3002, nginx proxies it to chosen external port
- **Nginx config template**:
  ```nginx
Confidence
96% confidence
Finding
This line instructs `sudo apt-get install nginx`, which introduces privileged package management not required for routine UI generation. Installing and enabling a system web server changes host exposure and increases attack surface.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
}
  }
  ```
- **Enable**: `sudo ln -s /etc/nginx/sites-available/<project-name> /etc/nginx/sites-enabled/ && sudo systemctl reload nginx`
- **If declined**: Access directly via `http://localhost:3002` (PM2 port)

**Before starting, ask user if they want to enable optional features.**
Confidence
98% confidence
Finding
This line chains privileged filesystem modification and service reload commands under `/etc/nginx`, directly exercising root-level system administration. Such instructions can alter production web-server behavior, expose local services, or disrupt existing configurations if executed blindly.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Static analysis

No suspicious patterns detected.