Back to skill

Security audit

xiaoqianran-duck

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real DuckDB/Hugging Face analytics skill, but its preview server and helper expose powerful SQL, local data, file, network, and token behavior without enough scoping or safety controls.

Install only if you are comfortable reviewing and controlling a prototype-grade local data tool. Do not expose the preview server to a network; prefer running it only on loopback, avoid sensitive databases, do not use the arbitrary SQL endpoint with untrusted input, keep HF tokens out of committed .env files, and regenerate lockfiles from a trusted registry before using the native dependencies in production.

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

T09 · Insecure Skill Coding Practices

Error
Location
examples/preview-server.js:43
Finding

Unauthenticated Network-Accessible Arbitrary SQL Execution

Content
View full analysis
Query Result
text
${JSON.stringify(rows, null, 2)}
Back`); } catch (e) { res.end(`

Error

text
${e.message}
Back`); } } else { res.statusCode = 404; res.end('Not found'); } server.listen(PORT, () => { console.log(`Preview server running at http://localhost:${PORT}`); ``` The query is passed to the following unrestricted execution method in `lib/duckdb-helper.js:158-163`: ```js async query(sql) { const conn = await this.connect(); const result = await conn.run(sql); const rows = await result.getRows(); return rows; } ``` ### Technical Analysis The `/query` endpoint takes the complete SQL statement from the `sql` URL parameter and sends it directly to DuckDB. There is no authentication, authorization, statement allowlist, read-only mode, multi-statement rejection, or filesystem/network restriction. Although the console message describes the service as being available at `localhost`, `server.listen(PORT)` does not explicitly bind to a loopback address. Depending on the platform, it normally listens on all available IPv4 or IPv6 interfaces. The service may consequently be reachable by other systems on the local network or through container, virtual-machine, or port-forwarding configurations. DuckDB SQL is not limited to ordinary `SELECT` queries. Subject to the process permissions and DuckDB configuration, it can modify or delete database objects, read supported local files, export data to files, load installed extensions, an ...[truncated 1815 chars]
Remediation
View remediation
{ console.log(`Preview server running at http://127.0.0.1:${PORT}`); }); ``` 2. Require strong authentication before permitting any database operation if non-loopback access is required. 3. Remove the arbitrary SQL endpoint from production builds. Replace it with narrowly scoped operations using validated table and column identifiers. 4. Open the database in read-only mode for preview use where possible. 5. If custom queries are required, parse and enforce a strict single-statement, read-only policy. Reject commands such as `COPY`, `ATTACH`, `INSTALL`, `LOAD`, `CREATE`, `DROP`, `DELETE`, `UPDATE`, and external file-reading functions. 6. Disable DuckDB external access and extension installation in the preview process unless explicitly required. 7. Use POST requests for stateful operations and implement CSRF tokens, strict Origin validation, and SameSite cookies. 8. Add request-size, query-time, memory, and concurrency limits to reduce denial-of-service risk. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
lib/duckdb-helper.js:89
Finding

SQL Injection Through Interpolated Identifiers and File Paths

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
examples/preview-server.js:21
Finding

Stored and Reflected HTML Injection in the Preview Interface

Content
View full analysis
xiaoqianran-duck Preview`; html += `

DB: ${helper.dbPath}

`; html += `

Tables

    `; for (const t of tables) { html += `
  • ${t}
  • `; } html += `
`; html += `

Run Query

`; html += `Run`; res.end(html); } else if (parsedUrl.pathname === '/table') { const name = parsedUrl.searchParams.get('name'); if (!name) { res.end('No table'); return; } const info = await helper.getTableInfo(name); const rows = await helper.query(`SELECT * FROM ${name} LIMIT 20`); let html = `

Table: ${name}

`; html += `
text
${JSON.stringify(info, null, 2)}
`; html += `

Sample rows (20)

text
${JSON.stringify(rows, null, 2)}
`; html += `Back`; res.end(html); } else if (parsedUrl.pathname === '/query') { const sql = parsedUrl.searchParams.get('sql') || 'SELECT 1'; try { const rows = await helper.query(sql); res.end(`

Query Result

text
${JSON.stringify(rows, null, 2)}
Back`); } catch (e) { res.end(`

Error

text
${e.message}
Back`); } ``` ### Technical Analysis The application generates HTML by concatenating untrusted values directly into markup. The affected values include: - Database table names. - The `name` URL parameter. - Database schema information. - Database row values. - Arbitrary query results. - DuckDB error messages. - The resolved database path. `JSON.stringify()` doe ...[truncated 1985 chars]
Remediation
View remediation
', '>') .replaceAll('"', '"') .replaceAll("'", '''); } ``` 2. URL-encode query parameters with `encodeURIComponent()` rather than inserting them directly into `href` attributes. 3. Prefer returning database results as `application/json` and rendering them with safe DOM APIs such as `textContent`. 4. Use a maintained templating engine with automatic escaping enabled. 5. Never assign untrusted values to `innerHTML` in any future client-side interface. 6. Add a restrictive Content Security Policy, for example one that disallows inline scripts and limits network destinations. 7. Add headers including `X-Content-Type-Options: nosniff`, an appropriate `Referrer-Policy`, and frame restrictions. 8. Add tests containing ``, quotes, angle brackets, event-handler attributes, and script elements in table names, values, and error-producing input. ]]>

T08 · Insecure Dependencies

Warning
Location
package-lock.json:14
Finding

Native Dependencies Retrieved from a Third-Party npm Mirror

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (42)

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

Suggesting that users store HF_TOKEN in a .env file next to the database encourages colocating credentials with project data in a way that is easy to leak through backups, source control, packaging, or accidental sharing. Because the token grants access to gated Hugging Face resources, exposure could allow unauthorized dataset access and account misuse.

Content

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

bash
export HF_TOKEN=hf_your_token
# or put in .env next to data.duckdb

In code:

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The code is explicitly designed to discover and consume credentials from ambient sources (.env and environment variables), which is a credential-access behavior. In an agent-integrated tool, this can expose private tokens to unintended operations and broadens the blast radius if the helper is invoked on attacker-influenced inputs.

Content

Scanner excerpt · lib/duckdb-helper.js (reported line 47)May include surrounding context.

js
}

  /**
   * Try to load HF token from environment or .env
   */
  async autoLoadHFToken() {
    let token = process.env.HF_TOKEN || process.env.HUGGINGFACE_TOKEN;

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Reading a local .env file to extract HF_TOKEN is credential harvesting from local developer secrets, even if intended for convenience. This is especially risky in reusable agent skills because the caller may not expect the library to inspect nearby secret files at all.

Content

Scanner excerpt · lib/duckdb-helper.js (reported line 52)May include surrounding context.

js
async autoLoadHFToken() {
    let token = process.env.HF_TOKEN || process.env.HUGGINGFACE_TOKEN;
    if (!token) {
      // Try .env file in project
      const envPath = path.join(path.dirname(this.dbPath), '.env');
      if (fs.existsSync(envPath)) {
        const envContent = fs.readFileSync(envPath, 'utf8');

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Constructing a path to a neighboring .env file and reading it for tokens demonstrates direct access to local secret material. In the context of an analytics helper, this capability is more dangerous because it is not necessary for basic local file import/query operations and could be abused indirectly through agent workflows.

Content

Scanner excerpt · lib/duckdb-helper.js (reported line 53)May include surrounding context.

js
let token = process.env.HF_TOKEN || process.env.HUGGINGFACE_TOKEN;
    if (!token) {
      // Try .env file in project
      const envPath = path.join(path.dirname(this.dbPath), '.env');
      if (fs.existsSync(envPath)) {
        const envContent = fs.readFileSync(envPath, 'utf8');
        const match = envContent.match(/HF_TOKEN=([^\s]+)/);

Credential Access

High
Category
Privilege Escalation
Confidence
72% confidence
Finding

The documentation suggests placing an HF access token in a .env file next to data.duckdb, but does not warn about file permissions, accidental commits, or leakage through packaged desktop apps and support bundles. Since the token may grant access to gated/private datasets, poor secret-handling guidance can lead to credential exposure.

Content

Scanner excerpt · skills/xiaoqianran-duck/SKILL.md (reported line 46)May include surrounding context.

bash
export HF_TOKEN=hf_your_token
# or put in .env next to data.duckdb

In code:

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 · examples/hf-import.js (reported line 12)May include surrounding context.

js
// Optional: set HF token for gated datasets
  // await helper.setHFTtoken('hf_your_token_here');
  // or put HF_TOKEN=... in .env next to data.duckdb

  const hfPath = 'hf://datasets/datasets-examples/doc-formats-parquet-1/data/train-00000-of-00001.parquet';

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 · skills/xiaoqianran-duck/examples/hf-import.js (reported line 12)May include surrounding context.

js
// Optional: set HF token for gated datasets
  // await helper.setHFTtoken('hf_your_token_here');
  // or put HF_TOKEN=... in .env next to data.duckdb

  const hfPath = 'hf://datasets/datasets-examples/doc-formats-parquet-1/data/train-00000-of-00001.parquet';

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

The code is explicitly designed to access credentials by reading Hugging Face tokens from environment variables and nearby configuration files. In an agent skill, automatic credential harvesting from the host environment is security-relevant because it can appropriate secrets without an explicit request from the user at the moment of use.

Content

Scanner excerpt · skills/xiaoqianran-duck/lib/duckdb-helper.js (reported line 47)May include surrounding context.

js
}

  /**
   * Try to load HF token from environment or .env
   */
  async autoLoadHFToken() {
    let token = process.env.HF_TOKEN || process.env.HUGGINGFACE_TOKEN;

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Reading a local .env file to extract HF_TOKEN broadens credential access beyond process-provided configuration and may pull secrets from the project directory unexpectedly. In a skill ecosystem, this increases the chance that unrelated developer secrets are used or exposed through authenticated remote operations.

Content

Scanner excerpt · skills/xiaoqianran-duck/lib/duckdb-helper.js (reported line 52)May include surrounding context.

js
async autoLoadHFToken() {
    let token = process.env.HF_TOKEN || process.env.HUGGINGFACE_TOKEN;
    if (!token) {
      // Try .env file in project
      const envPath = path.join(path.dirname(this.dbPath), '.env');
      if (fs.existsSync(envPath)) {
        const envContent = fs.readFileSync(envPath, 'utf8');

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The presence of hardcoded logic targeting '.env' files indicates intentional credential collection behavior from local filesystem context. While likely added for convenience, this is dangerous in agent-driven environments because it silently expands secret access and can cause authenticated actions under user credentials without transparent approval.

Content

Scanner excerpt · skills/xiaoqianran-duck/lib/duckdb-helper.js (reported line 53)May include surrounding context.

js
let token = process.env.HF_TOKEN || process.env.HUGGINGFACE_TOKEN;
    if (!token) {
      // Try .env file in project
      const envPath = path.join(path.dirname(this.dbPath), '.env');
      if (fs.existsSync(envPath)) {
        const envContent = fs.readFileSync(envPath, 'utf8');
        const match = envContent.match(/HF_TOKEN=([^\s]+)/);

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill documents environment-variable use for HF_TOKEN and operational capabilities, but it does not declare any tool scope or permissions boundary in the skill metadata. In an agent setting, this increases the chance that the skill can access sensitive environment data without explicit user awareness or least-privilege constraints.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

Using npx xiaoqianran-duck without pinning a specific version causes execution of whatever package version is current at install time. This creates a supply-chain risk where a compromised or malicious future release could be fetched and executed unexpectedly.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

Using npx xiaoqianran-duck without pinning a specific version causes execution of whatever package version is current at install time. This creates a supply-chain risk where a compromised or malicious future release could be fetched and executed unexpectedly.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

Using npx xiaoqianran-duck without pinning a specific version causes execution of whatever package version is current at install time. This creates a supply-chain risk where a compromised or malicious future release could be fetched and executed unexpectedly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill instructs users to place an HF access token in an environment variable or .env file but provides no warning about credential sensitivity, accidental commit risk, file permissions, or secret-handling hygiene. This is especially relevant because the tool accesses remote gated datasets and normalizes token use as part of routine workflow.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documented preview server exposes local table browsing and query execution over HTTP, but the skill does not warn users about binding scope, network exposure, or the risk of serving sensitive local data. In a desktop data tool, this can unintentionally leak imported files or query results to other local users or network peers.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The preview server accepts a user-supplied sql parameter and passes it directly to helper.query(sql) with no validation, authentication, or restriction to read-only statements. Even though this is described as a local preview tool, arbitrary SQL can expose sensitive local data, modify or delete database contents, and potentially access external resources depending on DuckDB features enabled in the environment.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The helper automatically reads Hugging Face credentials from process environment variables and a nearby .env file, which expands its access beyond explicit user-provided dataset paths. In a data-import utility, silently harvesting credentials increases the chance of unintended credential use and accidental access to private remote resources.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Automatic token loading from environment variables or .env files happens without any user-facing disclosure, so users may unknowingly authorize authenticated network access. This weakens transparency and can cause private credentials to be used in contexts the operator did not intend.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest emphasizes importing and querying analytical data, but this helper performs persistent mutations via CREATE OR REPLACE TABLE during imports and writes files during export. Those write-side behaviors are substantive operations, not merely read-only querying, and the description does not make that persistence/export behavior explicit.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Importing from hf:// triggers network access and may automatically use discovered Hugging Face credentials, but the helper provides no warning or consent boundary. In an agent setting, this can surprise users by contacting external services and accessing private datasets.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The helper can write query results to arbitrary filesystem paths without restriction or confirmation. If exposed through higher-level agent actions with untrusted input, this could overwrite files or facilitate unintended local data exfiltration to attacker-chosen locations.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The backend performs network access to Hugging Face and creates a local file as part of normal startup/example flow, even though the skill is described as a local analytics backend. This expands behavior beyond user-requested local analysis, can leak network metadata or trigger unapproved outbound connections, and may surprise applications embedding this backend such as Tauri/Electron apps.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Automatically installing and loading the httpfs extension on startup enables network-capable functionality without any user-driven need or consent. In an embedded desktop-app context, this increases attack surface, may trigger downloads or extension installation side effects, and makes a supposedly local tool perform remote-capable operations by default.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.