{"id":4718,"name":"sing","author":"MJ Hamim","framework":"goat","overall":65,"grade":"C","level":"risky","verdict":"Risky — serious capabilities found, review before installing","scores":{"security":57,"privacy":93,"quality":100,"maintenance":90,"community":16},"counts":{"critical":0,"high":1,"medium":1,"low":2},"alerts":[{"id":"shell","severity":"high","category":"security","title":"Shell access","description":"Spawns operating-system processes through child_process. A command running shell code can read or change anything the bot's account can.","count":2,"locations":[{"line":5,"snippet":"const { spawn, spawnSync } = require(\"child_process\");"},{"line":24,"snippet":"const has = (cmd, flag = \"--version\") => { try { return spawnSync(cmd, [flag], { stdio: \"ignore\", timeout: 8000 }).status === 0; } catch (e) { return false; …"}]},{"id":"fs-destructive","severity":"medium","category":"security","title":"Deletes files","description":"Calls fs.rm / unlink / rmdir. Check what path it deletes and whether a user can influence it.","count":1,"locations":[{"line":25,"snippet":"const safeUnlink = (f) => { try { if (f && fs.existsSync(f)) fs.unlinkSync(f); } catch (e) {} };"}]},{"id":"env","severity":"low","category":"privacy","title":"Environment variable access","description":"Reads process.env. Fine on its own; worth a look if the values are sent anywhere.","count":9,"locations":[{"line":12,"snippet":"const YTDLP = process.env.YTDLP_PATH || \"yt-dlp\";"},{"line":13,"snippet":"const MAX_MIN = Number(process.env.SING_MAX_MIN || 10);"},{"line":14,"snippet":"const MAX_MB = Number(process.env.SING_MAX_MB || 24);"},{"line":15,"snippet":"const QUEUE_MAX = Number(process.env.SING_QUEUE_MAX || 5);"},{"line":16,"snippet":"const FORMAT = String(process.env.SING_FORMAT || \"m4a\").toLowerCase() === \"mp3\" ? \"mp3\" : \"m4a\";"}]},{"id":"fs-access","severity":"low","category":"security","title":"Filesystem access","description":"Reads or writes files on the machine running the bot.","count":1,"locations":[{"line":3,"snippet":"const fs = require(\"fs-extra\");"}]}],"capabilities":[{"id":"network","label":"Network","active":false},{"id":"filesystem","label":"Filesystem","active":true},{"id":"shell","label":"Shell","active":true},{"id":"env","label":"Env vars","active":true},{"id":"eval","label":"Dynamic code","active":false},{"id":"credentials","label":"Session data","active":false},{"id":"install","label":"Installs packages","active":false},{"id":"process","label":"Process control","active":false}],"checks":[{"label":"Exports a command/module","ok":true},{"label":"Handles errors (try/catch or .catch)","ok":true},{"label":"Readable, not minified","ok":true},{"label":"Has explanatory comments","ok":true},{"label":"No deprecated dependencies","ok":true},{"label":"Reasonable size (< 200 KB)","ok":true}],"dependencies":{"builtin":["child_process","path","stream","stream/promises"],"external":["@distube/ytdl-core","fs-extra","youtubei.js","yt-search"],"local":[]},"domains":[],"scannedAt":"2026-11-05T13:07:41.393Z"}