Back to skill

Security audit

ClawDirect Dev

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for building ATXP web apps, but it recommends an unsafe authentication-cookie flow that can expose reusable session credentials.

Review this carefully before installing or reusing it. The main issue is not that it uses ATXP, cookies, npm, or MCP, but that it teaches developers to put reusable authentication cookies in URLs and keep server-side sessions without clear expiry or revocation. Prefer a one-time, short-lived bootstrap token or direct cookie-setting support, add server-side session expiration and revocation, and pin dependency and CLI versions before using the template in production.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:313
Finding
Bearer Authentication Token Exposed Through URL Query Parameters<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:313-329` and `SKILL.md:385-393` **Vulnerability Type**: Authentication token exposure and session fixation **Risk Level**: High The documented authentication design instructs agents to transmit a reusable bearer credential in a URL query parameter: ```typescript // Cookie bootstrap middleware - handles ?myapp_cookie=XYZ for agent browsers // Agent browsers often can't set HTTP-only cookies directly, so they pass the cookie // value in the query string and the server sets it, then redirects to clean URL app.use((req, res, next) => { const cookieValue = req.query.myapp_cookie; if (typeof cookieValue === 'string' && cookieValue.length > 0) { res.cookie('myapp_cookie', cookieValue, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', path: '/', maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days }); const url = new URL(req.originalUrl, `http://${req.headers.host}`); url.searchParams.delete('myapp_cookie'); res.redirect(302, url.pathname + url.search || '/'); return; } next(); }); ``` The corresponding usage instructions are: ```bash npx atxp-call https://your-domain.com/mcp myapp_cookie '{}' ``` ```text https://your-domain.com?myapp_cookie=<cookie_value> ``` The server will set the HTTP-only cookie and redirect to clean the URL. ### Technical Analysis The cookie value is a bearer credential mapped directly to an ATXP account. Placing this credential in a query string can expose it through: - Browser history and synchronization services - Reverse-proxy, load-balancer, CDN, and web-server access logs - Application performance monitoring and analytics systems - Screenshots, copied URLs, support records, and browser automation traces - Referrer propagation under configurations that permit full or partial URL disclosure Redirecting to a clean URL only removes the credential from subsequent navigation. It does not rem ...[truncated 2474 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never place the actual session cookie or another long-lived bearer credential in a URL. - Return a short-lived, cryptographically random, single-use bootstrap code from the authenticated MCP tool. - Store only a hash of the bootstrap code and associate it with the authenticated account, creation time, expiration time, and intended purpose. - Exchange the bootstrap code through a dedicated HTTPS endpoint and consume it atomically before issuing a new session cookie. - Give bootstrap codes a very short lifetime, such as one to five minutes, and reject reused, expired, malformed, or unknown codes. - Consider using an auto-submitted HTTPS POST form or another mechanism that does not place the code in the URL. - Validate the bootstrap credential before setting any cookie to prevent arbitrary or invalid session installation. - Rotate the session identifier during bootstrap and after security-sensitive account changes. - Configure a restrictive `Referrer-Policy`, such as `no-referrer`, as defense in depth. - Scrub sensitive query parameters from application, proxy, CDN, monitoring, and analytics logs. - Require HTTPS in production and enable HSTS. Do not rely solely on `NODE_ENV` to prevent bearer cookies from being sent over plaintext transport. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:118
Finding
Authentication Sessions Lack Server-Side Expiration and Revocation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:118-142` and `SKILL.md:317-323` **Vulnerability Type**: Indefinitely replayable authentication sessions **Risk Level**: Medium The authentication table records a creation timestamp, but it has no expiration or revocation fields: ```typescript db.exec(` CREATE TABLE IF NOT EXISTS auth_cookies ( cookie_value TEXT PRIMARY KEY, atxp_account TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); ``` Cookie creation and validation do not enforce a lifetime: ```typescript export function createAuthCookie(atxpAccount: string): string { const cookieValue = crypto.randomBytes(32).toString('hex'); getDb().prepare(` INSERT INTO auth_cookies (cookie_value, atxp_account) VALUES (?, ?) `).run(cookieValue, atxpAccount); return cookieValue; } export function getAtxpAccountFromCookie(cookieValue: string): string | null { const result = getDb().prepare(` SELECT atxp_account FROM auth_cookies WHERE cookie_value = ? `).get(cookieValue) as { atxp_account: string } | undefined; return result?.atxp_account || null; } ``` The browser cookie is assigned a 30-day lifetime: ```typescript res.cookie('myapp_cookie', cookieValue, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', path: '/', maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days }); ``` ### Technical Analysis The 30-day `maxAge` controls only how long a conforming browser retains its local cookie. It does not invalidate the corresponding server-side record. The validation query accepts any token present in `auth_cookies`, regardless of its `created_at` value. No `expires_at` or `revoked_at` state is stored or checked, and the template provides no logout, account-wide revocation, token rotation, or expired-record cleanup procedure. Consequently, a token copied before the browser deletes it can be replayed manually after 30 days and will continue to authenticate. This subs ...[truncated 1327 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Add server-side session lifecycle fields, including `expires_at`, `revoked_at`, and optionally `last_used_at`. - Enforce expiration and revocation in every authentication lookup. For example, require `expires_at > CURRENT_TIMESTAMP` and `revoked_at IS NULL`. - Keep server-side expiration no longer than the browser cookie lifetime. - Implement explicit logout that revokes the current session and clears the browser cookie. - Provide account-wide session revocation for compromised credentials or security-sensitive account changes. - Rotate session tokens periodically and after authentication, privilege, or payment-related changes. - Periodically delete expired and revoked records. - Consider storing a cryptographic hash of each token rather than the raw bearer value, reducing direct token disclosure if the database is read. - Apply both an absolute lifetime and, where appropriate, an idle timeout. - Add automated tests confirming that expired, revoked, rotated, and logged-out sessions are rejected. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:78
Finding
Unpinned Third-Party Dependencies and Implicit npx Package Execution<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:78-79`, `SKILL.md:377-385`, and `SKILL.md:448-471` **Vulnerability Type**: Software supply-chain exposure **Risk Level**: Medium The setup instructions install dependencies without exact versions: ```bash mkdir my-agent-app && cd my-agent-app npm init -y npm install @longrun/turtle @atxp/server @atxp/express better-sqlite3 express cors dotenv zod npm install -D typescript @types/node @types/express @types/cors @types/better-sqlite3 tsx ``` The operational instructions also use `npx` without requiring a locally installed, version-pinned executable: ```markdown 1. Install ATXP: `npx skills add atxp-dev/cli --skill atxp` 2. Call MCP tools: `npx atxp-call https://your-domain.com/mcp <tool> [params]` ``` ```bash npx atxp-call https://your-domain.com/mcp myapp_cookie '{}' ``` Additional paid operations use the same execution pattern: ```bash npx atxp-call https://claw.direct/mcp clawdirect_add '{ "url": "https://your-site.com", "name": "Your Site Name", "description": "Brief description of what your site does for agent", "thumbnail": "<base64_encoded_image>", "thumbnailMime": "image/png" }' ``` ```bash npx atxp-call https://claw.direct/mcp clawdirect_edit '{ "url": "https://your-site.com", "description": "Updated description" }' ``` ### Technical Analysis The `npm install` commands resolve whatever package versions satisfy the registry's current defaults at installation time. The Skill provides neither exact versions nor a reviewed lockfile, so the effective code can change without any modification to `SKILL.md`. Package installation can execute lifecycle scripts with the user's operating-system permissions. Runtime packages also execute inside the server process and can access environment variables, authentication data, the SQLite database, and network resources available to that process. When the requested command is not already installed locally, `npx` may download a package a ...[truncated 2082 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin every direct dependency and development dependency to an exact, reviewed version. - Generate, review, and commit `package-lock.json`, then use `npm ci` in CI and deployment environments. - Install command-line tools as pinned local development dependencies and invoke them through package scripts. - Use `npx --no-install` so commands fail instead of implicitly downloading unreviewed packages. - If a one-time package execution is unavoidable, specify an exact version and verify its package identity, provenance, and integrity before execution. - Review transitive dependencies and installation lifecycle scripts. - Use dependency auditing, provenance verification, lockfile integrity checks, and automated update review. - Run builds and package installation in an isolated, least-privileged environment without production secrets. - Disable unnecessary lifecycle scripts where compatible with the dependency stack, while accounting for native modules that may legitimately require build steps. - Maintain an allowlist of approved package names, versions, registries, and expected maintainers to reduce dependency-confusion and package-substitution risk. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (7)

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill explicitly recommends transporting an authentication cookie in the URL query string, which can leak credentials through browser history, server logs, reverse proxies, analytics, referrer headers, screenshots, and shared links. This is especially dangerous because the cookie grants authenticated web access and the pattern is presented as recommended without a strong warning or compensating controls.

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.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The reusable SKILL.md template tells downstream developers and agents to authenticate by visiting a cookie-bearing URL, but omits any warning that doing so can disclose the credential to multiple logging and telemetry surfaces. Because this is a template, it amplifies the insecure pattern across other projects, increasing the likelihood of credential leakage and session hijacking at scale.

Static analysis

No suspicious patterns detected.