Security report (responsible disclosure - no public exploit details)
Affected commit: 1b003ec
All issues below are remotely triggerable by any connected player (client-triggered server events/callbacks with no server-side authorization).
1. IDOR: illenium-appearance:server:updateOutfit (server/server.lua:220)
Database.PlayerOutfits.Update (server/database/playeroutfits.lua:25) runs UPDATE player_outfits SET model = ?, components = ?, props = ? WHERE id = ? with no citizenid filter. Outfit IDs are auto-increment and enumerable, so any player can overwrite any other player's saved outfits (appearance data tampering).
2. IDOR: illenium-appearance:server:deleteOutfit (server/server.lua:272)
Database.PlayerOutfits.DeleteByID (playeroutfits.lua:34) runs DELETE FROM player_outfits WHERE id = ? with no ownership check. Any player can delete any other player's outfits.
3. Missing authorization: illenium-appearance:server:saveManagementOutfit (server/server.lua:248)
Direct INSERT INTO management_outfits with no job/grade check (compare getManagementOutfits at server.lua:136, which validates job + grade). Any player can inject management uniforms for any job/gang (e.g. police, MinRank=0), forcing arbitrary models on all job members.
4. Missing authorization: illenium-appearance:server:deleteManagementOutfit (server/server.lua:263)
DELETE FROM management_outfits WHERE id = ? with no auth. Enumerating IDs removes all job uniforms (persistent DoS).
5. Money duplication: illenium-appearance:server:payForTattoo (server/server.lua:105)
local cost = tattoo.cost or Config.TattooCost takes the cost from the client-supplied payload (sent from NUI, game/nui.lua:84). A negative value passed to Framework.RemoveMoney(src, 'cash', cost) results in a credit instead of a debit on both supported frameworks (ESX RemoveAccountMoney and QBCore PlayerData.money.cash - amount both add money for negative amounts; the ESX balance check at server/framework/esx/main.lua:25 also passes).
Impact
- Tampering/destruction of any player's saved outfits.
- Corruption/deletion of job & gang management uniforms server-wide.
- Unlimited in-game money duplication (ESX + QBCore).
Suggested fix
updateOutfit/deleteOutfit: verify ownership (e.g. local o = Database.PlayerOutfits.GetByID(id); if o and o.citizenid == citizenID then ...).
saveManagementOutfit/deleteManagementOutfit: validate job + grade server-side like getManagementOutfits does.
payForTattoo: never trust the client cost — clamp to Config.TattooCost or ignore tattoo.cost entirely.
I can provide full PoC payloads privately. There is no SECURITY.md / private vulnerability reporting enabled on this repo — happy to switch to a private channel if preferred.
Security report (responsible disclosure - no public exploit details)
Affected commit:
1b003ecAll issues below are remotely triggerable by any connected player (client-triggered server events/callbacks with no server-side authorization).
1. IDOR:
illenium-appearance:server:updateOutfit(server/server.lua:220)Database.PlayerOutfits.Update(server/database/playeroutfits.lua:25) runsUPDATE player_outfits SET model = ?, components = ?, props = ? WHERE id = ?with nocitizenidfilter. Outfit IDs are auto-increment and enumerable, so any player can overwrite any other player's saved outfits (appearance data tampering).2. IDOR:
illenium-appearance:server:deleteOutfit(server/server.lua:272)Database.PlayerOutfits.DeleteByID(playeroutfits.lua:34) runsDELETE FROM player_outfits WHERE id = ?with no ownership check. Any player can delete any other player's outfits.3. Missing authorization:
illenium-appearance:server:saveManagementOutfit(server/server.lua:248)Direct
INSERT INTO management_outfitswith no job/grade check (comparegetManagementOutfitsat server.lua:136, which validates job + grade). Any player can inject management uniforms for any job/gang (e.g. police, MinRank=0), forcing arbitrary models on all job members.4. Missing authorization:
illenium-appearance:server:deleteManagementOutfit(server/server.lua:263)DELETE FROM management_outfits WHERE id = ?with no auth. Enumerating IDs removes all job uniforms (persistent DoS).5. Money duplication:
illenium-appearance:server:payForTattoo(server/server.lua:105)local cost = tattoo.cost or Config.TattooCosttakes the cost from the client-supplied payload (sent from NUI, game/nui.lua:84). A negative value passed toFramework.RemoveMoney(src, 'cash', cost)results in a credit instead of a debit on both supported frameworks (ESXRemoveAccountMoneyand QBCorePlayerData.money.cash - amountboth add money for negative amounts; the ESX balance check at server/framework/esx/main.lua:25 also passes).Impact
Suggested fix
updateOutfit/deleteOutfit: verify ownership (e.g.local o = Database.PlayerOutfits.GetByID(id); if o and o.citizenid == citizenID then ...).saveManagementOutfit/deleteManagementOutfit: validate job + grade server-side likegetManagementOutfitsdoes.payForTattoo: never trust the client cost — clamp toConfig.TattooCostor ignoretattoo.costentirely.I can provide full PoC payloads privately. There is no SECURITY.md / private vulnerability reporting enabled on this repo — happy to switch to a private channel if preferred.