Back to skill

Security audit

code-review-fix

Security checks for vulnerabilities and agentic risk

Overview

This code-review skill is mostly transparent about charging for use, but it ships a live-looking billing API key and can trigger paid billing requests using a local OS-derived user identifier.

Review this carefully before installing. The skill may contact skillpay.me for balance, charging, and payment-link actions, and it includes a billing API key directly in the package. Set an explicit SKILLPAY_USER_ID if used, avoid running it on sensitive repositories without understanding billing behavior, and use --fix only when you are prepared for in-place file changes.

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

T09 · Insecure Skill Coding Practices

Error
Location
lib/billing.ts:6
Finding

Hardcoded SkillPay API Credential Exposed in Distributed Source Code

Content
View full analysis

Vulnerability Details

File Location: lib/billing.ts:6-8, with credential use at lib/billing.ts:11-15, lib/billing.ts:26-37, and lib/billing.ts:53-61
Vulnerability Type: Hardcoded secret and reusable API credential
Risk Level: High

Vulnerable Code

typescript
const BILLING_API_URL = 'https://skillpay.me';
const BILLING_API_KEY = 'sk_97337971993cff4076fb179c0e1f42d592a89406507c603db864d6784c849bd8';
export const SKILL_ID = '3da52f24-9e3d-43bd-931d-0925e237ed93';

The embedded credential is used in multiple network requests:

typescript
const resp = await fetch(
  `${BILLING_API_URL}/api/v1/billing/balance?user_id=${encodeURIComponent(userId)}`,
  { headers: { 'X-API-Key': BILLING_API_KEY } }
);
typescript
const resp = await fetch(`${BILLING_API_URL}/api/v1/billing/charge`, {
  method: 'POST',
  headers: {
    'X-API-Key': BILLING_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    user_id: userId,
    skill_id: SKILL_ID,
    amount: 0.001,
  }),
});
typescript
const resp = await fetch(`${BILLING_API_URL}/api/v1/billing/payment-link`, {
  method: 'POST',
  headers: {
    'X-API-Key': BILLING_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ user_id: userId, amount }),
});

Technical Analysis

The project distributes a live-looking SkillPay API key directly in its source code. Every user who downloads the Skill can retrieve the credential without needing to execute the application. The key is then transmitted as an X-API-Key header to balance, charging, and payment-link endpoints.

Client-distributed API credentials cannot be treated as confidential because package recipients control the execution environment and can inspect source code or outgoing requests. An attacker can extract the key and reproduce authenticated requests independently of the Skill. The ex ...[truncated 1572 chars]

Remediation
View remediation

Remediation Suggestions

  1. Immediately revoke and rotate the exposed API key because its confidentiality can no longer be assumed.
  2. Remove the credential from source code and repository history.
  3. Do not distribute a privileged billing key to clients, even through environment variables if end users control the runtime.
  4. Place privileged SkillPay communication behind a trusted backend. The client should authenticate as a specific user, while the backend stores the billing credential in a managed secret store.
  5. Scope replacement credentials to the minimum endpoints, skill, transaction amount, and environment required.
  6. Require server-side authorization for every user_id; never accept an arbitrary client-supplied identifier solely because the request has the shared API key.
  7. Add rate limits, replay protection, transaction identifiers, audit logs, and anomaly detection to charge operations.
  8. Fail closed on non-successful HTTP responses and validate response schemas before consuming fields such as balance or payment_url.
  9. Add automated secret scanning to source-control and release pipelines.

other

Warning
Location
scripts/main.ts:31
Finding

Local Operating-System Username Is Transmitted as an Undisclosed Billing Identifier

Content
View full analysis

Vulnerability Details

File Location: scripts/main.ts:31-33, transmission triggers at scripts/main.ts:101-103 and scripts/main.ts:156-166; network sinks at lib/billing.ts:11-15, lib/billing.ts:26-37, and lib/billing.ts:53-61
Vulnerability Type: Privacy data exposure through implicit device-derived identification
Risk Level: Medium

Vulnerable Code

typescript
function getUserId(): string {
  // Use an environment variable or machine identifier as the user ID
  return process.env.SKILLPAY_USER_ID || 'local-user-' + require('os').userInfo().username;
}

After the free-call allowance, the derived identifier is sent through the billing function:

typescript
const userId = getUserId();

if (!isFree) {
  console.log('⏳ Checking billing status...');
  const result = await chargeUser(userId);
  if (!result.ok) {
    return;
  }
}

It is transmitted to SkillPay in a charge request:

typescript
body: JSON.stringify({
  user_id: userId,
  skill_id: SKILL_ID,
  amount: 0.001,
}),

The same identifier is also transmitted by balance and payment-link operations:

typescript
`${BILLING_API_URL}/api/v1/billing/balance?user_id=${encodeURIComponent(userId)}`
typescript
body: JSON.stringify({ user_id: userId, amount }),

Technical Analysis

When SKILLPAY_USER_ID is not configured, the application reads the current operating-system account name and converts it into a persistent identifier prefixed with local-user-. That identifier is sent to https://skillpay.me after the free allowance is exhausted and when a user invokes the balance or payment-link commands.

An operating-system username may contain a real name, corporate account identifier, email-derived handle, or another stable value. Sending it to an external billing provider permits correlation of activity with a local account or individual.

Billing integration is cons ...[truncated 1837 chars]

Remediation
View remediation

Remediation Suggestions

  1. Stop using os.userInfo().username as an automatic fallback identity.
  2. Require the user to explicitly configure a billing account identifier before any network billing operation.
  3. Alternatively, generate a cryptographically random pseudonymous identifier and store it locally with restrictive file permissions.
  4. Present a clear consent notice before the first network request, identifying the destination, transmitted fields, purpose, retention expectations, and available offline behavior.
  5. Provide an offline mode that performs local analysis without billing-network access.
  6. Keep billing identifiers separate from source paths, filenames, code contents, usernames, hostnames, and other device attributes.
  7. Minimize server-side retention and prevent use of the identifier for unrelated tracking.
  8. Validate and constrain explicitly supplied identifiers before placing them in URLs or request bodies.
  9. Document that balance, charge, and payment-link commands contact SkillPay and describe the exact information transmitted.
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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (23)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · .gitignore (reported line 5)May include surrounding context.

text
dist/
build/
*.log
.env
.DS_Store
.code-review-fix-state.json

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

A privileged billing API key is hardcoded directly in source code, which exposes a sensitive credential to anyone with access to the repository, build artifacts, logs, or distributed skill package. If leaked, an attacker could query balances, generate payment links, or initiate billing actions against the external billing service using the skill's authority.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code uses a hardcoded billing credential to make authenticated requests to an external payment service without any visible disclosure, consent flow, or trust boundary documentation. This creates both a secret exposure issue and an opaque privileged integration that could bill users or expose account data without their informed awareness.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The chargeUser function performs a live charge attempt against an external billing API as soon as it is called, with no built-in confirmation, approval gate, or proof of user authorization in this code path. In a skill context, this is especially dangerous because invocation of normal application logic could directly trigger monetary charges or abuse if called unexpectedly or by a compromised component.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README advertises automatic code fixing but does not clearly warn users that source files may be modified in place. In a code-review skill, this can lead to unintended changes, loss of work, or users running destructive actions without informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The --fix example shows a command that will alter the specified file but provides no warning in the immediate context. Users may copy-paste the command assuming it is a read-only review operation, causing accidental file modification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The example integration sends code content to an external LLM service without any privacy, confidentiality, or data-transfer warning. In a code-review tool, the uploaded code may contain proprietary logic, secrets, or regulated data, so omission of this warning can mislead users into unsafe disclosure.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The README explicitly references a third-party API endpoint for LLM analysis, which implies code may leave the local environment. Even though this is presented as an example, the skill context makes it sensitive because reviewed code often contains confidential business logic or credentials.

Content

Scanner excerpt · README.md (reported line 86)May include surrounding context.

可以在 analyzeCode 函数中接入 Claude API 或其他 LLM:

typescript
const response = await fetch('https://api.anthropic.com/v1/messages', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.ANTHROPIC_API_KEY,

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The README explicitly references a third-party API endpoint for LLM analysis, which implies code may leave the local environment. Even though this is presented as an example, the skill context makes it sensitive because reviewed code often contains confidential business logic or credentials.

Content

Scanner excerpt · README.md (reported line 86)May include surrounding context.

可以在 analyzeCode 函数中接入 Claude API 或其他 LLM:

typescript
const response = await fetch('https://api.anthropic.com/v1/messages', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.ANTHROPIC_API_KEY,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill explicitly advertises that it can 'directly fix code' and includes a '--fix' mode, but the documentation does not warn users that files may be modified, how changes are applied, or whether confirmation/backup mechanisms exist. This creates a real safety risk because users may invoke the skill expecting analysis only and unintentionally allow destructive or incorrect edits to source files.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This TypeScript file contains user-facing report strings and instructional text entirely in Chinese, such as the success message, issue summaries, and auto-fix command guidance. Because the file provides no opt-in, language selection, or justification for a Chinese-only locale, it violates the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The code documentation at L174-L182 presents the fixer as an automatic repair mechanism, and the report generator at L164-L169 tells users that any issue with a fix suggestion is auto-fixable. In reality, fixCode only applies one specific style rewrite and does not implement fixes for the security and performance findings that also carry fixSuggestion text, creating a meaningful intent/behavior mismatch in the inline documentation and user-facing guidance.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The payment-link function sends user identifiers and requested payment amounts to a third-party billing service without any visible user notice, minimization, or privacy controls. While less severe than direct charging, it still shares potentially sensitive user/account data externally and could be abused for tracking, phishing-style payment flows, or unauthorized payment requests.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script derives a persistent identifier from an environment variable or the local OS username and uses it for tracking and billing. This is dangerous because it ties usage and payment state to host identity without clear necessity for code review, creating privacy risk and potential cross-context user tracking on shared systems.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script reads environment or OS-derived identity data and sends it into billing-related functions without clear disclosure at the point of collection. This is risky because users may not realize host identity is being used for remote financial/account operations, which can violate privacy expectations and enable hidden attribution.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill performs billing, charging, and payment handling inside a code review tool, which is outside the minimally expected functionality for analyzing or fixing code. In an agent skill context, this increases risk because users may invoke the tool expecting local analysis while it triggers financial workflows and stores usage state, creating opportunity for unwanted charges or deceptive monetization.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

When --fix is used, the tool overwrites the target file immediately with no confirmation, backup, or dry-run preview. This can cause accidental loss of source code, unsafe modifications, or corruption of sensitive files if the analyzer output is wrong or manipulated.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The presence of payment-link and balance subcommands extends the skill beyond code review into financial account operations. In this context, unrelated monetization features make the skill more dangerous because they normalize payment interactions in a tool users may trust for purely local development assistance.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The skill documentation uses Chinese throughout for its descriptive and instructional text, which may impose a language requirement on users without opt-in. The policy specifically calls out forced language or locale constraints as a natural-language policy concern unless the choice is optional or clearly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The file contains natural-language comments entirely in Chinese, which reflects a fixed language choice in the skill's human-readable content. Under the policy rule, language constraints should be optional or clearly justified; this file provides no indication of user choice or a documented reason for the locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The natural-language description forces a bilingual presentation in a specific language combination, but the file does not state that language selection is user-configurable or limited to a justified regional context. Under the policy, locale or language constraints should be opt-in or explicitly documented.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 15)May include surrounding context.

json
"license": "MIT",
  "dependencies": {},
  "devDependencies": {
    "@types/bun": "^1.0.0"
  }
}

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The help text and multiple runtime messages are presented only in Chinese, which imposes a specific language on all users. The file does not provide a language selection mechanism or indicate that the skill is intentionally limited to a Chinese-speaking audience.

Content

No source excerpt is available for this finding.