Back to skill

Security audit

beijing-jifen-consult

Security checks for vulnerabilities and agentic risk

Overview

This skill is a local Beijing points-settlement calculator that clearly discloses its local browser saving behavior and shows no evidence of uploading data or unsafe execution.

Install/use it as a local calculator, but avoid entering sensitive personal details on a shared browser profile unless you are comfortable with them persisting locally; use the page's clear-record button or clear browser storage after use.

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

T09 · Insecure Skill Coding Practices

Warning
Location
assets/beijing-jifen-wizard.html:1518
Finding
Automatic Plaintext Persistence of Sensitive Personal Data in Browser Storage<![CDATA[ ## Vulnerability Details **File Location**: `assets/beijing-jifen-wizard.html`, lines 1518-1553 **Vulnerability Type**: Persistent plaintext storage of sensitive personal information **Risk Level**: Medium ### Vulnerable Code ```javascript function collectFormState(){ var data = { version: 4, form: {}, extras: {}, socialRows: [], resRows: [], birth: "", degreeDeduct: "" }; data.plan = JSON.parse(JSON.stringify(planState)); data.radios = collectRadioState(); try { var form = document.querySelector("#wizardForm"); new FormData(form).forEach(function(v, k){ data.form[k] = String(v); }); } catch (e) {} ["#areaStart1", "#areaStart2", "#taxStart1"].forEach(function(sel){ var el = $(sel); if (el) data.extras[sel] = ymValueFrom(el); }); ["#innovate1", "#innovate2", "#innovate3"].forEach(function(sel){ var el = $(sel); if (el) data.extras[sel] = el.value; }); $$("#socialSegs .seg-row").forEach(function(row){ var p = row.querySelectorAll(".ym-pair"); data.socialRows.push({ start: ymReadSafe(p[0]), end: ymReadSafe(p[1]) }); }); $$("#resSegs .seg-row").forEach(function(row){ var p = row.querySelectorAll(".ym-pair"); var t = row.querySelector(".seg-res-type"); data.resRows.push({ start: ymReadSafe(p[0]), end: ymReadSafe(p[1]), type: t ? t.value : "1" }); }); var birth = $("#birthYM .ym-pair"); data.birth = ymReadSafe(birth); var dd = $("#degreeDeductSeg"), dp = dd ? dd.querySelectorAll(".ym-pair") : []; if (dp.length >= 2) data.degreeDeduct = ymReadSafe(dp[0]) + "|" + ymReadSafe(dp[1]); return data; } function saveForm(){ if (restoringForm) return; try { localStorage.setItem(FORM_CACHE_KEY, JSON.stringify(collectFormState())); } catch (e) {} } ``` ### Technical Analysis The application automatically serializes nearly the entire calculator form and stores it as plaintext JSON in `localStorage`. The retained information can include birth month, employment and social-insurance periods, r ...[truncated 2395 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable persistent storage by default and require an explicit opt-in before saving form data. 2. Clearly identify every category of data that will be retained, the purpose of retention, and how long it will remain. 3. Minimize retained data. In particular, avoid persisting birth information, tax status, criminal-record eligibility, administrative penalties, and other sensitive fields unless strictly necessary. 4. Provide a session-only mode using in-memory state or `sessionStorage`, and make it the default. 5. Add an expiration timestamp and automatically delete stale records after a short, documented retention period. 6. Automatically clear sensitive state when the user completes the workflow, unless the user explicitly chooses to retain it. 7. Add a visible persistent-storage status indicator and an accessible control to disable future saving. 8. Consider field-level redaction or selective persistence so that only low-sensitivity UI preferences are retained. 9. Do not rely solely on client-side encryption when the encryption key is stored in the same browser context, as that does not protect against same-origin script access. 10. Retain the existing manual clearing function, but supplement it with automatic expiry and opt-in consent rather than treating manual deletion as the only lifecycle control. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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

Static analysis

No suspicious patterns detected.