Overview
CVE-2026-41457 describes an injection flaw in OwnTone Server versions 28.4 through 29.0 where the DAAP query and filter handling failed to sanitize user-supplied values for integer-mapped DAAP fields. This allowed attackers to inject arbitrary SQL expressions by supplying malicious values through the query= and filter= parameters, bypassing filters and gaining unauthorized access to media library data. The vulnerability aligns with CWE-89 (SQL Injection) and emphasizes how dynamic SQL construction without proper validation can expose sensitive data in media libraries. In the Node.js (Express) ecosystem, similar patterns can occur when request parameters are directly interpolated into SQL strings, especially when fields referenced by the user determine which column is filtered or selected. The risk is elevated if numeric fields are treated as integers without validation, enabling crafted payloads to alter logic or retrieve unintended rows. The CVE highlights the importance of strict input handling, proper query parameterization, and careful construction of SQL against user input in web services built with Node.js and Express. Operators should upgrade affected systems and refactor code to avoid string concatenation for SQL with user-controlled values.
Affected Versions
28.4 through 29.0
Code Fix Example
Node.js (Express) API Security Remediation
VULNERABLE:
const express = require('express');
const app = express();
const pool = require('./db'); // mysql2/promise pool
app.get('/search', async (req, res) => {
const { field, value } = req.query; // user-controlled input
// Vulnerable: directly interpolating input into SQL
const sql = `SELECT * FROM media WHERE ${field} = '${value}'`;
try {
const [rows] = await pool.query(sql);
res.json(rows);
} catch (e) {
res.status(500).send('Error');
}
});
FIX:
app.get('/search', async (req, res) => {
const { field, value } = req.query;
// Whitelist allowed fields to prevent arbitrary SQL injection via column names
const allowedFields = ['id','title','artist','album','genre'];
const safeField = allowedFields.includes(field) ? field : 'id';
// Use parameterized queries for values and safe placeholders for identifiers
const sql = 'SELECT * FROM media WHERE ?? = ?';
try {
const [rows] = await pool.query(sql, [safeField, value]);
res.json(rows);
} catch (e) {
res.status(500).send('Error');
}
});