Back to skill

Security audit

PowPow Simple — Reisetagebuch auf der Karte verankern, chatfähige digitale Menschen erstellen

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly transparent about posting to PowPow, but it should be reviewed carefully because it handles passwords and stored login sessions and its scripts can publish, delete, or spend badges without code-enforced confirmation.

Install only if you are comfortable giving this skill access to your PowPow account session and letting it perform public actions on your behalf. Review the final preview yourself before any publish/create/delete command is run, avoid sharing a reusable password in ordinary chat where possible, and use a dedicated PowPow password or reset it afterward if concerned.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/publish.js:96
Finding

Public post publication is not protected by an executable confirmation gate

Content
View full analysis

Vulnerability Details

File Location: scripts/publish.js, lines 96–103 and 154–173
Vulnerability Type: Missing authorization confirmation for a public, identity-bearing action
Risk Level: High

Relevant code:

js
async function main() {
  const [, , htmlPath] = process.argv;
  if (!htmlPath) {
    console.error('Usage: node publish.js <html-file-path>');
    process.exit(1);
  }

  let content = fs.readFileSync(htmlPath, 'utf-8');
  console.log(`Content length: ${content.length} chars`);

  // ...

  const postData = {
    type: 'text',
    content,
    ...(locInfo
      ? {
          lng: locInfo.lng,
          lat: locInfo.lat,
          locationName: locInfo.name,
          isLocationExposed: true,
        }
      : { isLocationExposed: false }),
  };

  console.log('\nPublishing...');
  try {
    const post = await publishWithRetry(postData);

Technical Analysis

SKILL.md lines 301–318 require the agent to show the complete post, account, location, images, and preview and then wait for an explicit publish decision. However, this requirement is not enforced by publish.js.

The script accepts only a draft path, loads the authenticated session, uploads referenced local images, and submits the post. It does not require an approval token, a confirmation argument, an interactive prompt, or evidence that the user approved the final content. Consequently, direct invocation bypasses the workflow’s stated authorization boundary.

This is particularly significant because publication is externally visible, occurs under the authenticated user’s identity, and may expose a selected location on the public map.

Attack Path

  1. The user has a valid PowPow session stored in the configured state directory.
  2. An agent, automation component, or adversarially influenced caller selects or creates an HTML draft.
  3. The caller invokes:
    bash
    node scripts/publish.js <html-file-path>
    
  4. No user-approval artifact is required.
  5. Ref ...[truncated 573 chars]
Remediation
View remediation

Remediation Suggestions

Require a code-enforced approval artifact before uploading images or submitting the post:

  1. Generate a preview containing the final account, content, image manifest, and location.
  2. Compute a cryptographic digest over the final draft and manifest.
  3. After explicit user approval, issue a short-lived approval token bound to the digest, authenticated account, and intended operation.
  4. Make publish.js reject requests without a valid token or when the draft has changed after approval.
  5. For direct human CLI use, provide an interactive confirmation that displays the account and public-map consequences.
  6. Provide a non-mutating --dry-run mode and ensure image uploads do not occur during dry runs.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/create-digital-human.js:145
Finding

Badge-consuming digital-human creation lacks a code-enforced approval gate

Content
View full analysis

Vulnerability Details

File Location: scripts/create-digital-human.js, lines 145–190
Vulnerability Type: Missing authorization confirmation for irreversible resource consumption
Risk Level: Medium

Relevant code:

js
async function main() {
  const opts = parseArgs(process.argv.slice(2));

  let description = opts.desc;
  if (!description && opts.descFile) {
    if (!fs.existsSync(opts.descFile)) throw new Error(`--desc-file not found: ${opts.descFile}`);
    description = fs.readFileSync(opts.descFile, 'utf-8');
  }

  const { lng, lat } = validate(opts, description);
  const session = requireSession();

  // Badge pre-check: creating costs BADGES_REQUIRED badges and deletion does
  // NOT refund them - fail fast before uploading anything.
  if (session.userId) {
    const bal = await api('GET', `/api/badges/balance?userId=${session.userId}`);
    const current = bal.balance ? bal.balance.balance : 0;
    if (current < BADGES_REQUIRED) {
      throw new Error(`Badge balance too low: ${current} available, ${BADGES_REQUIRED} required. Earn badges on the platform first (see https://global.powpow.online).`);
    }
    console.log(`  💰 Badge balance: ${current} (creating a digital human consumes ${BADGES_REQUIRED})`);
  }

  const { avatarUrl, referenceImageUrl } = await resolveAvatar(opts, description);

  // ...

  const body = await api('POST', '/api/digital-humans', payload);

Technical Analysis

The script’s comment states that the agent must obtain confirmation before invocation, and SKILL.md lines 351–360 require explicit confirmation after disclosing the two-badge, non-refundable cost and 30-day expiry. The executable entry point does not enforce this requirement.

A balance check verifies only that sufficient badges exist; it does not establish user authorization. Once valid arguments and a session are available, the script may upload an avatar or reference image and immediately call the creation endpoint. No confirmation pa ...[truncated 921 chars]

Remediation
View remediation

Remediation Suggestions

  1. Add a mandatory approval token bound to the authenticated account and the exact name, persona, avatar reference, coordinates, cost, and expiry.
  2. Issue that token only after the user explicitly accepts the displayed two-badge, non-refundable charge.
  3. Validate the token immediately before any image upload or creation request.
  4. In interactive CLI use, display the final creation summary and require a positive confirmation.
  5. Add --dry-run or preview functionality that performs validation without uploading images or consuming badges.
  6. Invalidate approval if any material parameter changes.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/delete-post.js:9
Finding

Post deletion executes without mandatory confirmation

Content
View full analysis

Vulnerability Details

File Location: scripts/delete-post.js, lines 9–18
Vulnerability Type: Missing confirmation for a destructive operation
Risk Level: Medium

Relevant code:

js
async function main() {
  const [, , postId] = process.argv;
  if (!postId) {
    console.error('Usage: node delete-post.js <post-id>');
    process.exit(1);
  }

  try {
    const body = await api('DELETE', `/api/posts/${postId}`);
    console.log(`✅ Post deleted: ${postId}`);

Technical Analysis

The script performs an authenticated DELETE request as soon as it receives a post ID. It does not retrieve and display the target first, verify that it is a test post, require an interactive confirmation, or consume an approval token.

Server-side JWT scoping reportedly limits deletion to posts owned by the authenticated user. That ownership restriction prevents cross-account deletion but does not establish that the account owner authorized deletion of the particular post. Because deletion is destructive, relying solely on the caller to invoke the helper correctly leaves the operation vulnerable to mistaken or adversarial agent invocation.

Attack Path

  1. The user has a valid authenticated session.
  2. A caller obtains or selects the ID of a post owned by that user.
  3. The caller invokes:
    bash
    node scripts/delete-post.js <post-id>
    
  4. The script immediately sends the authenticated DELETE request.
  5. The owned post is removed without a code-enforced confirmation step.

Impact Assessment

An attacker-influenced agent or faulty automation can delete posts belonging to the currently authenticated user. Server-side authorization limits the scope to that user’s own posts, so this does not establish cross-account deletion or privilege escalation. The primary impact is unauthorized destructive modification of the user’s published content.

Remediation
View remediation

Remediation Suggestions

  1. Retrieve the target post and display its author, title or excerpt, publication time, and location before deletion.
  2. Require an explicit interactive confirmation or a short-lived approval token bound to the post ID and authenticated owner.
  3. Consider restricting this helper to posts explicitly marked as test content, consistent with its documented cleanup purpose.
  4. Add a preview or --dry-run mode.
  5. Log a non-sensitive deletion audit record containing the account ID, post ID, approval timestamp, and operation result.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (26)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
Geokodierung → Matching → Assemblierung → Veröffentlichung → Verifikation),
  kein unabhängiges verstecktes Werkzeug.
- `delete-post.js` löscht nur den eigenen Beitrag des angemeldeten Nutzers
  (`DELETE /api/posts/{id}`, JWT-beschränkt, serverseitig erzwungen) und ist in
  SKILL.md Schritt 8 zur Testbereinigung dokumentiert. Diese Fähigkeit ist auch
  in der Skill-Beschreibung deklariert.
- Keine Geheimnisse im Paket. `config.json` enthält nur Standardwerte. Das

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/match-digital-human.js "<thema>" --limit 3 --json # sortierte Vorschläge

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/match-digital-human.js "<thema>" --limit 3 --json # sortierte Vorschläge

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/list-digital-humans.js "<name>" --json # Suche nach Name

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/list-digital-humans.js "<name>" --json # Suche nach Name

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/geocode.js "地坛公园" --limit 5 # mit --city 北京 eingrenzen

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- **Automatische Bildsuche** (nur mit konfiguriertem Unsplash-Key): `--image search:<english keywords>` (oder `node scripts/search-image.js "<keywords>"`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
**Pflicht: Beitrags-HTML immer mit `scripts/compose.js` assemblieren. Niemals Komponenten-Spans von Hand schreiben, niemals Klebecode schreiben, um html-formatt

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
**Pflicht: Beitrags-HTML immer mit `scripts/compose.js` assemblieren. Niemals Komponenten-Spans von Hand schreiben, niemals Klebecode schreiben, um html-formatt

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/verify.js <post-id>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/delete-post.js <post-id>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/create-digital-human.js \

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/security.md (reported line 44)May include surrounding context.

md
- `POST /api/upload/post-image` — Upload lokaler Bilder (multipart `file`; Anmeldung erforderlich)
- `POST /api/posts` — Beitrag erstellen (Anmeldung erforderlich; Server erzwingt Limits & Moderation)
- `GET  /api/posts/{id}` — einen Beitrag verifizieren
- `DELETE /api/posts/{id}` — eigenen Beitrag löschen (Testbereinigung)
- `POST /api/digital-humans` — digitalen Menschen erstellen (Anmeldung erforderlich;
  verbraucht 2 Badges, läuft nach 30 Tagen ab)
- `POST /api/digital-humans/generate-avatar` — KI-Avatar aus der Persona

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/delete-post.js (reported line 2)May include surrounding context.

js
/**
 * Delete one of your own posts (DELETE /api/posts/[id], JWT-scoped).
 * Useful for cleaning up test posts. You can only delete your own posts.
 *
 * Usage: node delete-post.js <post-id>

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file describes a German-language skill, yet several example commands and the usage note indicate that core search and matching workflows are centered on Chinese terms. This can amount to a language/locale policy issue because the skill effectively steers users toward a specific language without clearly offering a choice or making the limitation an explicit opt-in.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill explicitly relies on environment access and outbound network calls, but it does not declare a restrictive tool scope such as allowed tools, domains, or permissions. That creates an over-privileged execution posture where the agent may use broader capabilities than users or the platform expect, increasing the blast radius if the skill is misused or prompt-injected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill encourages users to send photos, travel stories, location, and timing details for publication to a public map, but it does not present a clear upfront privacy warning about the sensitivity and public visibility of that personal material. This raises the risk of inadvertent oversharing of identifiable travel patterns, companions, and location history, especially because the workflow emphasizes ease of posting and map pinning.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill instructs the assistant to ask users for their PowPow username and password directly in chat and even discourages giving a meaningful safety warning because it might feel like phishing. Collecting credentials through the assistant channel is dangerous because the model, platform logs, transcripts, or downstream integrations may capture highly sensitive secrets, enabling account compromise if exposed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Lines L38-L40 explicitly say the endpoint path is internal and 'must not be named to the user,' and to instead use a neutral term in internal discussion. This is a natural-language instruction embedded in the file that directs the agent to conceal specific information from the user.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/geocode.js (reported line 81)May include surrounding context.

js
console.log('Present these to the user to pick. If none fit, in this order:');
    console.log('  1) retry with different wording or --city <城市>;');
    console.log('  2) widen --limit and help the user recognise one from its district/address;');
    console.log('  3) publish without a location. Never ask the user for coordinates.');
  } catch (err) {
    if (err instanceof SessionExpiredError) {
      console.error(`❌ ${err.message}`);

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file sets DEFAULT_ACCEPT_LANGUAGE to zh-CN and includes user-facing error strings in Chinese, indicating the skill is forcing a specific language/locale by default. The policy allows locale constraints only when users are given a choice or the restriction is clearly justified; neither is present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The sort tie-breaker uses localeCompare with a hard-coded 'zh' locale, which imposes a specific language/locale behavior on all users. The file contains no user choice, opt-in mechanism, or documented region-specific justification for this locale constraint.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/search-image.js (reported line 57)May include surrounding context.

js
}

async function searchUnsplashOnce(query, key) {
  const url = `https://api.unsplash.com/search/photos?query=${encodeURIComponent(query)}&per_page=10&orientation=landscape`;

  for (let attempt = 0; attempt < 2; attempt++) {
    try {

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/search-image.js (reported line 180)May include surrounding context.

js
}

async function searchUnsplashOnce(query, key) {
  const url = `https://api.unsplash.com/search/photos?query=${encodeURIComponent(query)}&per_page=10&orientation=landscape`;

  for (let attempt = 0; attempt < 2; attempt++) {
    try {

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The file instructs the agent to explain screenshots 'in the user's language' when sending to a non-Chinese user. This imposes a language behavior as a rule, but the document does not mention asking the user for a preferred language or offering an explicit choice, which can conflict with language/locale policy expectations.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.potential_exfiltration

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
scripts/lib/api-client.js:66