Back to skill

Security audit

React Best Practices 2 0.1.0

Security checks for vulnerabilities and agentic risk

Overview

This is mostly a React/Next.js guidance skill, but some recommended examples could lead agents to write unsafe code involving session cookies, inline scripts, and shared caches.

Review this skill before installing. It is documentation-only and not directly malicious, but agents following it may copy unsafe patterns into production code. Avoid logging raw cookies or tokens, do not use `dangerouslySetInnerHTML` with dynamic data, scope cross-request caches carefully, and use pinned/project-local tooling instead of floating `npx` commands.

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

T09 · Insecure Skill Coding Practices

Error
Location
rules/server-after-nonblocking.md:46
Finding
Raw Session Cookie Disclosed to an Unspecified Logging or Analytics Sink<![CDATA[ ## Vulnerability Details **File Location**: `rules/server-after-nonblocking.md:46-48` **Duplicate Location**: `AGENTS.md:1048-1050` **Vulnerability Type**: Sensitive authentication data exposure **Risk Level**: High ### Vulnerable Code ```tsx const sessionCookie = (await cookies()).get('session-id')?.value || 'anonymous' logUserAction({ sessionCookie, userAgent }) ``` ### Technical Analysis The Skill presents this code as a correct implementation and instructs agents to pass the raw value of the `session-id` cookie to `logUserAction`. Session cookies are authentication credentials and should not be included in analytics events, general application logs, or other sinks not specifically designed to store secrets. The implementation of `logUserAction` is not included, so direct network exfiltration cannot be confirmed. Nevertheless, the example creates a sensitive-data flow into an unspecified logging boundary. Logging systems commonly forward events to external monitoring providers, centralized collectors, backups, dashboards, and support tools. Passing the raw cookie therefore expands access to a reusable credential beyond the authentication subsystem. The session cookie is not necessary to demonstrate Next.js `after()` behavior. This data collection exceeds the minimum privileges and data access required for the Skill's declared performance-optimization functionality. ### Attack Path 1. An agent applies the Skill's recommended non-blocking logging pattern to a Next.js application. 2. The route handler reads the raw `session-id` cookie from an authenticated request. 3. The cookie value is passed to `logUserAction`. 4. The logging implementation forwards or persists the event in application logs, an analytics platform, or centralized monitoring infrastructure. 5. A compromised logging provider, unauthorized dashboard user, support operator, or attacker with log access obtains the session identifier. 6. If the session remains valid and lacks ...[truncated 677 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never pass raw cookies, session IDs, access tokens, authorization headers, or other reusable credentials to logging or analytics functions. - Replace the session cookie with a non-secret internal user identifier when user-level audit correlation is legitimately required. - For pseudonymous analytics, derive a non-reversible identifier using a server-side keyed HMAC and rotate the key under a documented policy. - Define a strict allowlist for fields accepted by `logUserAction`; reject sensitive field names such as `cookie`, `session`, `token`, and `authorization`. - Add centralized redaction before events leave the application process. - Apply restricted access, short retention periods, encryption, and audit controls to log storage. - Add automated tests that submit sentinel credentials and verify that they never appear in emitted events. - Replace the example with a safe pattern such as: ```tsx after(async () => { const userAgent = (await headers()).get('user-agent') || 'unknown' await logUserAction({ event: 'resource-updated', userAgent, }) }) ``` - Remove the vulnerable duplicate from both `rules/server-after-nonblocking.md` and the generated `AGENTS.md`. ]]>

T08 · Insecure Dependencies

Warning
Location
rules/rendering-svg-precision.md:27
Finding
Unpinned Third-Party Package Download and Execution Through npx<![CDATA[ ## Vulnerability Details **File Location**: `rules/rendering-svg-precision.md:27` **Duplicate Location**: `AGENTS.md:2078` **Vulnerability Type**: Unpinned dependency execution **Risk Level**: Medium ### Vulnerable Code ```bash npx svgo --precision=1 --multipass icon.svg ``` ### Technical Analysis The Skill recommends executing `svgo` through `npx` without specifying a version or requiring a lockfile-pinned local dependency. If the package is not already installed, `npx` may resolve and download executable code from the configured package registry at invocation time. This makes the executed implementation mutable after the Skill has been reviewed. A compromised registry account, malicious registry configuration, dependency compromise, or unexpected future package release could cause different code to execute under the same documented command. The identified package name is not shown to be malicious, and the repository does not automatically run this command. The risk arises when a user or agent follows the recommendation in an environment where `npx` retrieves an unreviewed package version. ### Attack Path 1. A user or coding agent follows the Skill's SVG optimization instructions. 2. The environment does not contain an approved local version of `svgo`. 3. `npx` resolves the package using the current package-manager configuration and registry state. 4. A compromised or otherwise unsafe package version is downloaded. 5. Package CLI code and any applicable installation behavior execute with the privileges of the invoking user. 6. Malicious code can read or modify files accessible to that user, inspect environment variables, alter the repository, or initiate network connections. ### Impact Assessment A compromised package executes as a local process with the invoking user's permissions. Potentially exposed resources include project source code, repository credentials, environment variables, package-manager tokens, SSH material readable by th ...[truncated 259 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Add a reviewed, exact version of `svgo` as a development dependency and commit the package lockfile. - Invoke the lockfile-resolved local binary rather than allowing on-demand package resolution: ```bash pnpm exec svgo --precision=1 --multipass icon.svg ``` - Install dependencies with immutable or frozen-lockfile enforcement in automated environments. - Use an approved registry and verify package integrity through lockfile hashes and dependency-review tooling. - Avoid commands such as `npx --yes` that suppress confirmation when downloading executable packages. - Run asset-processing tools in a restricted environment without production secrets, broad home-directory access, or unnecessary network access. - If a one-off command is unavoidable, specify an audited exact version rather than a floating package name, while recognizing that a pinned project dependency and lockfile provide stronger controls. - Update both `rules/rendering-svg-precision.md` and its generated duplicate in `AGENTS.md`. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Unvalidated Output Injection

High
Category
Output Handling
Content
{children}
      </div>
      <script
        dangerouslySetInnerHTML={{
          __html: `
            (function() {
              try {
Confidence
97% confidence
Finding
`dangerouslySetInnerHTML` is a direct code-injection sink. In a skill intended for AI agents, demonstrating this sink as a recommended pattern materially increases the chance that future generated code will route untrusted values into inline scripts, enabling DOM-based or reflected XSS with session theft, account compromise, or arbitrary script execution in the browser.

Unvalidated Output Injection

High
Category
Output Handling
Content
{children}
      </div>
      <script
        dangerouslySetInnerHTML={{
          __html: `
            (function() {
              try {
Confidence
92% confidence
Finding
The skill explicitly recommends using dangerouslySetInnerHTML to inject an inline script, normalizing a pattern that bypasses React's default escaping and weakens CSP posture. While the shown snippet is static and not directly user-controlled, this guidance can be copied into real applications and later extended with dynamic values, creating a credible XSS sink and increasing the chance of unsafe script injection.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The manifest says this skill is for React and Next.js performance optimization guidelines, but this section teaches authentication, authorization, input validation, and protection of Server Actions as public endpoints. Those are legitimate engineering topics, but they are not directly justified by the skill's stated purpose of performance-focused code writing/review/refactoring guidance.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
This guidance recommends raw inline script injection with `dangerouslySetInnerHTML`, which normalizes a high-risk capability outside the skill's stated performance-optimization scope. Even though the example uses static code, agents following this pattern may generalize it to dynamic values from cookies, query params, or user preferences, creating an XSS sink in React/Next.js applications.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The example shows `dangerouslySetInnerHTML` without any warning about the XSS risk or constraints on allowed data sources. In an agent-focused skill, omission of those guardrails is dangerous because automated refactoring or code generation may copy the pattern into contexts where the script body includes attacker-controlled input.

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.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The file states that developers should use `useTransition` instead of manual loading state for loading indicators, and the 'correct' example wraps an async fetch in `startTransition`. In React, transitions are intended for marking state updates as non-urgent; they do not make the network request itself a transition, so presenting this as a general replacement for loading state is an intent-level contradiction between the guidance and what the code actually demonstrates.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The example explicitly recommends logging a session cookie value together with user-agent data in a background task, but provides no warning about minimizing, redacting, or avoiding sensitive identifiers. Session identifiers are security-sensitive and can enable account correlation, tracking, or misuse if logs are exposed, and moving the logging to `after()` makes it easy for developers to adopt the pattern without considering privacy or retention controls.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The guidance recommends cross-request in-memory caching of user records keyed only by user ID, but it does not warn that shared process memory can retain user data across requests, serve stale authorization-sensitive data, or leak data when cached objects are reused in the wrong security context. In a React/Next.js best-practices skill, this is more dangerous because readers may copy the pattern directly into production server code and assume it is a generally safe optimization.

Missing User Warnings

Low
Confidence
87% confidence
Finding
This markdown skill describes a pattern that reads from localStorage and injects a synchronous inline script before hydration. While the behavior is central to the example, the document does not include any warning or disclosure about accessing client-side stored data or the implications of using inline script execution.

Static analysis

No suspicious patterns detected.