fix(lyrics): avoid shell injection in NetEase requests
This commit is contained in:
+5
-5
@@ -12,7 +12,7 @@ highlighting, animated line changes, and configurable online or local sources.
|
||||
|
||||
## Requirements
|
||||
|
||||
Install `playerctl`, `python3`, `curl`, and `cp` on `PATH`. The active media
|
||||
Install `playerctl`, `python3`, and `cp` on `PATH`. The active media
|
||||
player must expose MPRIS metadata for automatic track and playback detection.
|
||||
|
||||
Noctalia installs the plugin files; it does not install system packages for you.
|
||||
@@ -103,7 +103,7 @@ HTTP mode contacts only the configured endpoint. The plugin never reads browser
|
||||
cookies or player credentials.
|
||||
|
||||
The service runs `playerctl` to read and control MPRIS playback, `python3` for the
|
||||
LRCLIB helper and dynamic-lyric parser, `curl` for the public NetEase API, and
|
||||
`cp` to preserve temporary local cover files. Query scratch files and downloaded
|
||||
cover images are written inside the plugin runtime directory. Remote code is
|
||||
never downloaded or executed.
|
||||
LRCLIB helper and dynamic-lyric parser, and `cp` to preserve temporary local cover
|
||||
files. Public NetEase requests use Noctalia's HTTP API. Query scratch files and
|
||||
downloaded cover images are written inside the plugin runtime directory. Remote
|
||||
code is never downloaded or executed.
|
||||
|
||||
+13
-10
@@ -82,19 +82,18 @@ local function fetchLyricsNetEase(track, embeddedLyrics)
|
||||
|
||||
local function tryFetch(query, fallback)
|
||||
local searchUrl = "https://music.163.com/api/search/get?type=1&s=" .. noctalia.string.urlEncode(query) .. "&limit=5"
|
||||
local cmd = 'curl -s --max-time 10 --connect-timeout 5 "' .. searchUrl .. '" -H "Referer: https://music.163.com"'
|
||||
|
||||
noctalia.runAsync(cmd, function(r1)
|
||||
noctalia.http({ url = searchUrl, headers = { "Referer: https://music.163.com" } }, function(r1)
|
||||
if not inFlight then return end
|
||||
if tk ~= lastTrackKey then inFlight = nil; return end
|
||||
|
||||
if r1.exitCode ~= 0 or not r1.stdout or #r1.stdout == 0 then
|
||||
if not r1.ok or r1.status < 200 or r1.status >= 300 or not r1.body or #r1.body == 0 then
|
||||
if fallback then fallback()
|
||||
else inFlight = nil; noctalia.state.set("lyrics", nil) end
|
||||
return
|
||||
end
|
||||
|
||||
local data = noctalia.json.decode(r1.stdout)
|
||||
local data = noctalia.json.decode(r1.body)
|
||||
if not data or not data.result or not data.result.songs or #data.result.songs == 0 then
|
||||
if fallback then fallback()
|
||||
else inFlight = nil; noctalia.state.set("lyrics", nil) end
|
||||
@@ -120,17 +119,21 @@ local function fetchLyricsNetEase(track, embeddedLyrics)
|
||||
bestMatch = data.result.songs[1]
|
||||
end
|
||||
|
||||
local songId = bestMatch.id
|
||||
local lyricUrl = "https://music.163.com/api/song/lyric?id=" .. songId .. "&lv=1&kv=1&tv=-1"
|
||||
local lCmd = 'curl -s --max-time 10 --connect-timeout 5 "' .. lyricUrl .. '" -H "Referer: https://music.163.com"'
|
||||
local songId = tostring(bestMatch.id or "")
|
||||
if not songId:match("^%d+$") then
|
||||
if fallback then fallback()
|
||||
else inFlight = nil; noctalia.state.set("lyrics", nil) end
|
||||
return
|
||||
end
|
||||
local lyricUrl = "https://music.163.com/api/song/lyric?id=" .. noctalia.string.urlEncode(songId) .. "&lv=1&kv=1&tv=-1"
|
||||
|
||||
noctalia.runAsync(lCmd, function(r2)
|
||||
noctalia.http({ url = lyricUrl, headers = { "Referer: https://music.163.com" } }, function(r2)
|
||||
if not inFlight then return end
|
||||
if tk ~= lastTrackKey then inFlight = nil; return end
|
||||
|
||||
local lyrics = nil
|
||||
if r2.exitCode == 0 and r2.stdout and #r2.stdout > 0 then
|
||||
local ldata = noctalia.json.decode(r2.stdout)
|
||||
if r2.ok and r2.status >= 200 and r2.status < 300 and r2.body and #r2.body > 0 then
|
||||
local ldata = noctalia.json.decode(r2.body)
|
||||
local klyricStr = ""
|
||||
if ldata and ldata.klyric then
|
||||
local k = ldata.klyric
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ version = "1.1.0"
|
||||
plugin_api = 3
|
||||
author = "h465855hgg"
|
||||
license = "MIT"
|
||||
dependencies = ["playerctl", "python3", "curl", "cp"]
|
||||
dependencies = ["playerctl", "python3", "cp"]
|
||||
tags = ["bar", "service", "music", "media", "animation"]
|
||||
icon = "music"
|
||||
description = "Synchronized lyrics with karaoke highlighting, animated transitions, and flexible lyric sources."
|
||||
|
||||
@@ -45,11 +45,10 @@ need_command() {
|
||||
MISSING_COMMANDS=""
|
||||
need_command playerctl
|
||||
need_command python3
|
||||
need_command curl
|
||||
need_command cp
|
||||
|
||||
if [ -z "$MISSING_COMMANDS" ]; then
|
||||
echo "All runtime commands are installed: playerctl python3 curl cp"
|
||||
echo "All runtime commands are installed: playerctl python3 cp"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -90,28 +89,28 @@ PM="$(detect_pm)"
|
||||
|
||||
case "$PM" in
|
||||
apt)
|
||||
INSTALL_CMD="$SUDO apt-get update && $SUDO apt-get install -y playerctl python3 curl coreutils"
|
||||
INSTALL_CMD="$SUDO apt-get update && $SUDO apt-get install -y playerctl python3 coreutils"
|
||||
;;
|
||||
dnf)
|
||||
INSTALL_CMD="$SUDO dnf install -y playerctl python3 curl coreutils"
|
||||
INSTALL_CMD="$SUDO dnf install -y playerctl python3 coreutils"
|
||||
;;
|
||||
pacman)
|
||||
INSTALL_CMD="$SUDO pacman -S --needed playerctl python curl coreutils"
|
||||
INSTALL_CMD="$SUDO pacman -S --needed playerctl python coreutils"
|
||||
;;
|
||||
zypper)
|
||||
INSTALL_CMD="$SUDO zypper install -y playerctl python3 curl coreutils"
|
||||
INSTALL_CMD="$SUDO zypper install -y playerctl python3 coreutils"
|
||||
;;
|
||||
apk)
|
||||
INSTALL_CMD="$SUDO apk add playerctl python3 curl coreutils"
|
||||
INSTALL_CMD="$SUDO apk add playerctl python3 coreutils"
|
||||
;;
|
||||
xbps)
|
||||
INSTALL_CMD="$SUDO xbps-install -Sy playerctl python3 curl coreutils"
|
||||
INSTALL_CMD="$SUDO xbps-install -Sy playerctl python3 coreutils"
|
||||
;;
|
||||
*)
|
||||
cat >&2 <<'EOF'
|
||||
Could not detect a supported package manager.
|
||||
Install these packages manually with your distribution package manager:
|
||||
playerctl python3 curl coreutils
|
||||
playerctl python3 coreutils
|
||||
EOF
|
||||
exit 1
|
||||
;;
|
||||
@@ -138,7 +137,6 @@ sh -c "$INSTALL_CMD"
|
||||
MISSING_COMMANDS=""
|
||||
need_command playerctl
|
||||
need_command python3
|
||||
need_command curl
|
||||
need_command cp
|
||||
|
||||
if [ -n "$MISSING_COMMANDS" ]; then
|
||||
|
||||
Reference in New Issue
Block a user