I do have a working system for this, but I do not believe it is as secure as Roblox’s secret system.
I am using Google’s AI API in my Roblox game, and it requires me to put the API key inside the URL. If I use the API key as plaintext in the URL, it works. However, if I use Roblox’s secret API to retrieve the key and append it to the URL using secret:AddPrefix(URL), I get a 400 Bad Request error. I believe this is because it is interpreting the API key as something like Secret(Key) instead of the actual key.
The workaround I do is to store the secret in a TextLabel inside ServerStorage. On startup, my script fetches the secret in the TextLabel. After that, it immediately deletes the TextLabel.
The reason I am especially worried is that the AI generates arbitrary code and it is run server-side.
If your script that sends the request is in ServerScriptService then clients can’t see it, so malicious players can’t see your token even if it is in the script.
They send a prompt to the AI, and the AI makes code. The code is run server-side. Someone could try something like “get the value of a variable named “key” from this script and display it on a part.”
If the client somehow has access to ServerScriptService there isn’t really anything you can do against them because they probably control the entire server and can get the key from memory.
The player does kind of have access to ServerScriptService, they give a prompt to an AI, and the AI generates code that is run on the server. The code is wrapped in a coroutine.wrap function however.
function module.AI(api_key, prompt)
local url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-exp-1206:generateContent?key=" .. api_key
local t = {} -- I ommited the table contents for brevity
local json = HttpService:JSONEncode(t)
local status, err = pcall(function()
local response = HttpService:PostAsync(url, json)
local code = tostring([[ This part just gets the code from the response ]])
return string.sub(code, 7, -5)
end)
return status, err
end
And this is the ServerScript that actually executes the code:
local AI = require(game.ReplicatedStorage.AI).AI
local HttpService = game.HttpService
local Key = game.ServerStorage.AiApiKey.Text
game.ServerStorage.AiApiKey.Text = ""
game.ServerStorage.AiApiKey:Destroy()
function Callback(player, prompt)
local status, err = AI(Key, prompt)
local code = err
if status then
local func = loadstring(code)
local status, err = pcall(coroutine.wrap, func)
if not status then
warn("Coroutine wrap failed:", err)
return status, err
end
status, err = pcall(err)
if not status then
warn("AI Generated code errored:", err)
return status, err
end
end
return status, code
end
game.ReplicatedStorage.AITrigger.OnServerInvoke = Callback
Edit: @efsane14010 Sorry I replied to the wrong person