Back to skill

Security audit

Mog Rating Preview

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent, but it can upload a sensitive face photo to a configurable website instead of only the official MogScore site.

Review before installing. Only run this with photos you are authorized to submit, assume the photo leaves your machine for processing, keep MOGSCORE_BASE_URL unset or restricted to the official HTTPS MogScore origin, and avoid passing arbitrary local file paths.

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
scripts/run-mog-rating-preview.mjs:26
Finding

Unrestricted Base URL Allows Sensitive Image Uploads to Attacker-Controlled Origins

Content
View full analysis

Vulnerability Details

File Location: scripts/run-mog-rating-preview.mjs:26-43, 67-71, 191-227; SKILL.md:13-15
Vulnerability Type: Unvalidated destination URL for sensitive file uploads
Risk Level: High

Vulnerable Code

js
export function parseArgs(argv = process.argv.slice(2), env = process.env) {
  const options = {
    baseUrl: env.MOGSCORE_BASE_URL?.trim() || DEFAULT_BASE_URL,
    browserExecutable: env.MOGSCORE_BROWSER_EXECUTABLE?.trim() || "",
    headed: true,
    image: "",
    timeoutMs: DEFAULT_TIMEOUT_MS
  };

  for (let index = 0; index < argv.length; index += 1) {
    const arg = argv[index];

    if (arg === "--headed") {
      options.headed = true;
      continue;
    }

    if (arg === "--image" || arg === "--base-url" || arg === "--browser-executable" || arg === "--timeout-ms") {
      const value = argv[index + 1];
      if (!value || value.startsWith("--")) {
        throw new UsageError(`${arg} requires a value.`);
      }

      index += 1;

      if (arg === "--image") {
        options.image = value;
      } else if (arg === "--base-url") {
        options.baseUrl = value;
      }
js
export function buildTargetUrl(baseUrl) {
  const origin = new URL(baseUrl).origin;
  const target = new URL("/mog-rating", origin);
  target.searchParams.set("mode", "upload");
  return target.toString();
}
js
export async function runMogRatingPreview(options) {
  const imagePath = path.resolve(options.image);
  const targetUrl = buildTargetUrl(options.baseUrl);

  try {
    await fs.access(imagePath);
  } catch {
    return buildErrorPayload("upload_failed", `Image file is not readable: ${imagePath}`, false);
  }

  let browser;
  try {
    const executablePath = await resolveBrowserExecutable(options);
    const { chromium } = await import("playwright-core");
    browser = await chromium.launch(buildBrowserL
...[truncated 4057 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove MOGSCORE_BASE_URL and --base-url if alternate service origins are not essential.
  2. Otherwise, validate the URL against an explicit allowlist before launching the browser:
    • Require the https: scheme.
    • Require the exact hostname mogscore.ai, or a narrowly defined list of approved subdomains.
    • Reject embedded usernames and passwords.
    • Reject unexpected ports.
    • Normalize the hostname before comparison.
  3. After page.goto(), inspect page.url() and abort unless the final origin remains on the approved allowlist. Apply the same check after any later navigation.
  4. Update isReportsResponse() to verify the response origin in addition to the HTTP method and pathname.
  5. Validate that --image points to a regular file with an approved image extension and detected MIME type before attaching it.
  6. Display or log the validated upload origin before transferring the image so that the destination is auditable.
  7. Add tests covering HTTP URLs, deceptive hostnames, embedded credentials, nonstandard ports, cross-origin redirects, and report responses from unrelated origins.

T08 · Insecure Dependencies

Note
Location
SKILL.md:10
Finding

Unpinned Dependency in Skill Installation Metadata

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:10-12
Vulnerability Type: Unpinned third-party dependency
Risk Level: Low

Vulnerable Code

yaml
install:
  - kind: node
    package: playwright-core

The project manifest separately specifies a fixed version:

json
"dependencies": {
  "playwright-core": "1.51.1"
}

Technical Analysis

The skill installation metadata identifies playwright-core without a version constraint. An installer that follows SKILL.md rather than package.json may resolve whichever package version is current at installation time.

This creates inconsistent dependency resolution: direct package installation uses version 1.51.1, while metadata-driven installation may retrieve a later and unreviewed version. The effective code executed by the skill can therefore change without a corresponding change to the audited project.

No evidence indicates that playwright-core is currently malicious or that dependency confusion is actively occurring. The issue is a supply-chain hardening and reproducibility weakness.

Attack Path

  1. A host installs skill requirements using the install entry in SKILL.md.

  2. Because no version is specified, the package registry resolves a newer release available at installation time.

  3. If that release is compromised, malicious, or contains a security regression, its code is installed into the skill environment.

  4. The dependency is imported when the workflow executes:

    js
    const { chromium } = await import("playwright-core");
    
  5. The changed dependency then executes with the privileges of the user running the skill.

Impact Assessment

The affected dependency runs inside the Node.js process and participates in launching and controlling a local browser. A compromised package could potentially access files readable by the process, inspect environment variables, initiate network connections, alt ...[truncated 316 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin the metadata dependency to the same audited version used by the project manifest:

    yaml
    install:
      - kind: node
        package: playwright-core@1.51.1
    
  2. Add and commit a package lockfile containing registry URLs and integrity hashes.

  3. Ensure every installation path honors the lockfile or an equivalently immutable dependency specification.

  4. Keep the version in SKILL.md, package.json, and the lockfile synchronized through automated checks.

  5. Use automated dependency scanning and review security advisories before upgrading.

  6. Configure package installation to use the expected trusted registry and disable unnecessary lifecycle scripts where operationally possible.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 50)May include surrounding context.

md
node scripts/run-mog-rating-preview.mjs \

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares environment-variable capabilities but does not define any explicit tool scope or permission boundary. That makes its runtime expectations less transparent and can enable broader-than-necessary access patterns, especially in agent systems where undeclared capabilities weaken policy enforcement and review.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This skill instructs the agent to upload a user's face photo to an external website but does not clearly warn the user in the skill description or invocation contract that biometric-sensitive data will leave the local environment. Face images are highly sensitive personal data, so omission of a prominent disclosure undermines informed consent and increases privacy, compliance, and trust risks.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The base URL is taken from an environment variable or CLI argument and later used to build the navigation target, allowing the browser to visit any origin rather than being pinned to mogscore.ai. In this skill, that is especially dangerous because the script then uploads a local file to the visited page and waits for a matching API call, enabling exfiltration of user images or other local files to an attacker-controlled site.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script accepts an arbitrary local path via --image, resolves it, verifies readability, and then uploads that file through the browser flow. Although the skill description implies only an authorized selfie should be used, the code does not enforce file type, content, or provenance, so a caller can cause unintended local file disclosure to the remote site.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The automation uploads a face image and submits it to a remote service without any built-in disclosure, confirmation, or consent checkpoint in the script itself. Because the data is a sensitive biometric-adjacent photo and the skill is designed to send it off-device, lack of explicit notice and confirmation increases privacy risk and the chance of unauthorized transmission.

Content

No source excerpt is available for this finding.