Back to skill

Security audit

Interactive Widget

Security checks for vulnerabilities and agentic risk

Overview

The skill appears purpose-built for widgets, but it publishes potentially sensitive content to a persistent remote service with insufficient guardrails.

Install only if you are comfortable with widget content and form submissions going to the configured widget service and becoming durable/shareable. Do not use it for secrets, credentials, regulated personal data, or confidential business records unless access controls and retention are separately verified. Prefer pinning the CLI version, reviewing the package source, escaping all untrusted text before inserting it into HTML, and avoiding mutable third-party CDN scripts for sensitive pages.

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)

T08 · Insecure Dependencies

Error
Location
SKILL.md:20
Finding
Unpinned Global npm Package Installation Creates a Supply-Chain Execution Risk<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, line 20 **Vulnerability Type**: Unpinned third-party package installed globally **Risk Level**: High ### Vulnerable Code ```bash npm install -g @openduo/duoduo-widgets # if not installed ``` ### Technical Analysis The setup instructions install `@openduo/duoduo-widgets` without specifying an exact version or verifying package integrity. Consequently, the package resolved by npm at installation time may differ from the version originally reviewed. npm packages can run lifecycle scripts, such as `preinstall`, `install`, and `postinstall`, during installation. These scripts execute with the privileges of the user running npm. The `-g` option also installs the CLI into the global npm prefix, increasing its system-wide reach relative to a project-local dependency. The package is central to the Skill's operation: all subsequent `duoduo-widget` commands trust the installed executable. Compromise of the npm package, its publisher account, or the package resolution path could therefore turn normal Skill usage into arbitrary local code execution. ### Attack Path 1. An attacker compromises the upstream npm package, its maintainer account, or a newly published version. 2. The user or agent follows the documented setup command. 3. npm resolves and downloads the compromised latest package because no exact version is pinned. 4. Malicious lifecycle scripts execute during installation, or malicious code executes when a later `duoduo-widget` command is invoked. 5. The payload operates with the installing user's permissions and can access data available to that account. ### Impact Assessment A compromised package could execute arbitrary commands with the privileges of the npm user. Depending on the execution environment, this could expose local files, environment variables, widget content, authentication material, and other user-accessible resources. The use of a global installation may also alter a comm ...[truncated 195 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the CLI to a reviewed exact version: ```bash npm install --global @openduo/duoduo-widgets@X.Y.Z ``` 2. Record and verify package integrity using a trusted lockfile, package digest, or controlled artifact repository. 3. Prefer a project-local installation over `-g` and invoke it through a controlled path. 4. Disable npm lifecycle scripts during installation when the package does not require them: ```bash npm install --ignore-scripts --save-exact @openduo/duoduo-widgets@X.Y.Z ``` 5. Review the package contents and lifecycle scripts before approving an updated version. 6. Use a trusted npm registry and protect against dependency substitution through registry allowlisting. 7. Run the CLI in a sandbox with only the filesystem and network access required to create the requested widget. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:33
Finding
Potentially Sensitive Widget Content Is Uploaded to an External Persistent Service Without a Mandatory Consent Gate<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 33–40 **Related Locations**: `SKILL.md`, lines 74–79, 134–147, and 162–167 **Vulnerability Type**: Uncontrolled external transmission and persistent hosting of user-provided data **Risk Level**: High ### Vulnerable Code ```bash cat > /tmp/w-{wid}.html << 'SKELETON' <div style="background:#1a1a1a;color:#e0e0e0;padding:20px;font-family:system-ui;min-height:100vh;"> <h1 style="color:#fff;font-size:28px;font-weight:500;margin:0 0 4px;">Title</h1> <p style="color:#999;font-size:14px;margin:0 0 20px;">Subtitle</p> <!-- NEXT --> </div> SKELETON cat /tmp/w-{wid}.html | duoduo-widget update --wid "wid_..." ``` The external destination and persistence behavior are documented later: ```markdown Finalized artifacts are permanent. Fork: `open --fork <widget_id>`. ## Environment `WIDGET_SERVICE_URL` env var (default: `https://aidgets.dev`). ``` Interactive form values may also be submitted through the hosted widget: ```html <button onclick="window.duoduo.submit('action', {key:'val'})">Label</button> ``` ### Technical Analysis The Skill pipes generated HTML into `duoduo-widget update`, whose default service endpoint is `https://aidgets.dev`. The generated page may contain dashboard records, operational data, form fields, confirmation values, or other information originating from the conversation. Remote hosting is directly related to the declared purpose of creating durable, shareable pages, so the network operation is not inherently covert or unrelated. However, the instructions do not impose a mandatory sensitivity review or explicit informed-consent step before upload. They also do not require redaction, audience restrictions, deletion controls, or a warning that final artifacts are permanent. The Skill can additionally create interactive forms and wait for submitted values. Those values cross a remote service boundary, but the documentation does not establish which information must ne ...[truncated 1651 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit informed consent immediately before the first external upload. The prompt should identify: - The destination service. - The categories of data being uploaded. - Who may receive the resulting link. - The permanence and retention implications. 2. Perform a sensitivity check and prohibit credentials, authentication tokens, private keys, regulated personal data, and confidential records by default. 3. Redact or aggregate sensitive values before generating the widget. 4. Prefer a local-only HTML artifact when remote sharing is not necessary. 5. Require authenticated or access-controlled links for non-public content; do not rely solely on URL secrecy. 6. Provide expiration and deletion controls instead of treating finalized artifacts as unconditionally permanent. 7. Clearly document how form submissions are transported, stored, accessed, and deleted. 8. Minimize submitted form data and avoid free-text collection where constrained fields are sufficient. 9. Keep the existing prohibition on sharing `control_url` and `control_token`, and extend it with automated secret scanning before every update or finalization. 10. Allowlist the service endpoint rather than trusting an arbitrary inherited `WIDGET_SERVICE_URL` without user confirmation. ]]>

T08 · Insecure Dependencies

Warning
Location
references/html_patterns.md:116
Finding
Remotely Executed Chart.js Dependency Is Not Pinned to an Immutable Version or Protected by Integrity Verification<![CDATA[ ## Vulnerability Details **File Location**: `references/html_patterns.md`, line 116 **Related Location**: `SKILL.md`, lines 128–130 **Vulnerability Type**: Mutable third-party browser dependency without Subresource Integrity **Risk Level**: Medium ### Vulnerable Code ```html <script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script> ``` The Skill also broadly permits scripts from several external CDN providers: ```markdown - Inline styles only. CDN: `cdnjs.cloudflare.com`, `esm.sh`, `cdn.jsdelivr.net`, `unpkg.com` - Forbidden: `fetch()`, `XMLHttpRequest`, `WebSocket`, `eval()`, `new Function()` ``` ### Technical Analysis The Chart.js URL specifies only the major version, `@4`, rather than an immutable release. A compatible package release can therefore change the JavaScript executed by previously generated or newly opened widgets without any corresponding change to the reviewed Skill files. The script element does not use Subresource Integrity (`integrity`) or `crossorigin`. Browser viewers consequently trust whatever JavaScript the CDN serves for that mutable URL. The restrictions against `fetch`, `XMLHttpRequest`, and similar constructs apply to authored templates, but they do not technically prevent a compromised external script from performing network operations or reading page content. Loading a chart library is necessary for the supplied chart template, but allowing mutable executable code from multiple CDNs is broader than the minimum privilege needed. ### Attack Path 1. An attacker compromises the CDN, upstream package publication account, or a release selected by the major-version URL. 2. The mutable `@4` path begins serving modified JavaScript. 3. A user opens a generated widget containing the chart template. 4. The browser downloads and executes the modified script in the page context. 5. The script can inspect rendered widget data and interact with browser-accessible APIs available to that origin. 6. D ...[truncated 600 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin an exact, reviewed Chart.js release instead of a major-version range: ```html <script src="https://cdn.jsdelivr.net/npm/chart.js@4.x.y/dist/chart.umd.min.js" integrity="sha384-REVIEWED_DIGEST" crossorigin="anonymous" ></script> ``` 2. Prefer self-hosting a reviewed copy on the trusted widget service. 3. Add Subresource Integrity and ensure the digest is updated only through a controlled dependency-review process. 4. Restrict allowed script sources with a Content Security Policy. 5. Reduce the CDN allowlist to the smallest necessary set instead of permitting four interchangeable external sources. 6. Isolate widgets from privileged service interfaces using a sandboxed iframe and a separate origin. 7. Keep sensitive data outside pages that execute third-party JavaScript whenever possible. 8. Re-review the exact dependency version before upgrading it. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Hidden Instructions

High
Category
Prompt Injection
Content
<div style="background:#1a1a1a;color:#e0e0e0;padding:20px;font-family:system-ui;min-height:100vh;">
  <h1 style="color:#fff;font-size:28px;font-weight:500;margin:0 0 4px;">Title</h1>
  <p style="color:#999;font-size:14px;margin:0 0 20px;">Subtitle</p>
<!-- NEXT -->
</div>
SKELETON
cat /tmp/w-{wid}.html | duoduo-widget update --wid "wid_..."
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<p style="margin:0;color:#999;font-size:14px;">Content — $100 safe, no escaping needed</p>
</div>
<!-- NEXT -->"""
html = html.replace('<!-- NEXT -->', section)
open(f, 'w').write(html)
PYEOF
cat /tmp/w-{wid}.html | duoduo-widget update --wid "wid_..."
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The description emphasizes permanent browser URLs but does not prominently warn that finalized artifacts are durable and shareable, which can cause accidental publication of sensitive or regulated information. In an agent setting, this omission materially affects user consent and safe tool selection.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger phrases are broad enough to match many ordinary requests, increasing the chance this skill is invoked when a plain-text response would suffice. Because the skill produces durable, browser-accessible artifacts, over-triggering expands exposure of sensitive content and increases the odds of unsafe HTML generation in contexts that did not require it.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The skill explicitly states that raw HTML is safe and needs no escaping in a system that creates permanent, shareable web pages. That guidance can lead an agent to interpolate untrusted user or data content directly into HTML or patch payloads, enabling stored XSS, UI redressing, or malicious script/event injection in artifacts opened by other users.

Static analysis

No suspicious patterns detected.