We are observing an unpredictable picking of "current_user" when the workflow is triggered by a Scheduled Trigger.
In the documentation its stated that "current_user" will be only present when workflow is triggered manually via editor or via the app, which makes perfect sense as at this moment there is a concept of active session, hence current_user ... We were expecting to see a "null" current user when the Workflow is triggered via Scheduler or Webhook, but its not the case -> instead some random admin user is picked (not related to given workflow, that has neither defined the workflow nor the trigger).
In cases where "current_user" is used for any kind of authorization this raises a security threat
On attached screenshot is a log of scheduled run of a dummy workflow - issue is reproducible.
Your screenshot confirms that current_user.id is unexpectedly populated (showing 3) during a scheduled workflow run, which contradicts Retool's documentation stating that current_user should be null for non-manual triggers. @Darren@Tess ?
In the meantime you could simply modify your workflow to explicitly check if current_user is assigned during a scheduled run and log an error if needed.
const user = current_user || null;
const metadata = startTrigger.metadata || {};
const headers = startTrigger.headers || {};
const urlParams = startTrigger.urlParams || {};
const data = startTrigger.data || {}; // Captures data passed in App/Webhook
// Detect trigger type
let triggerType = "manual"; // Default assumption
// Check if `user_id` and `app_name` were explicitly passed (for App triggers)
const appUserId = data.user_id || null;
const appName = data.app_name || null;
if (Object.keys(metadata).length === 0) {
if (Object.keys(headers).length > 0) {
triggerType = "webhook"; // Webhook requests always contain headers
} else if (appUserId) {
triggerType = "app"; // If user_id is explicitly passed, it's an App trigger
} else {
triggerType = "schedule"; // If metadata & headers are empty, assume scheduled
}
} else {
if (metadata.webhookPayload || Object.keys(headers).length > 0) {
triggerType = "webhook";
} else if (metadata.scheduledTime) {
triggerType = "schedule";
} else if (appUserId) {
triggerType = "app";
}
}
// Logging instead of throwing errors
let warningMessage = "";
if (triggerType === "schedule" && user) {
warningMessage = `⚠️ Warning: Unexpected current_user (${user.id}) in scheduled trigger.`;
} else if (triggerType === "webhook" && user) {
warningMessage = `⚠️ Warning: Unexpected current_user (${user.id}) in webhook trigger.`;
}
// Log the warning if any
if (warningMessage) {
console.log(warningMessage);
}
return {
user_id: user ? user.id : appUserId,
triggerType,
appName,
warningMessage,
urlParams
};
For my test I added the parameters user_id and app_name when triggering form the app.
Suggested solution with changing workflow scripts does not work for scenario that we have where Workflow Manager role is less privileged then Admin. So from security perspective we can not rely on every Workflow Manager adding a validation check in every workflow to protect from unauthorized execution of subsequent logic because if they forget to do it when creating new workflow we still have the issue.
Another way could be to create a specific workflow detectAppUser with the above script or similar and requiring each new workflow to in its first block the workflow block detectAppUser.
That is very odd that the current_user is not null, my first guess is that in might be due to some type of caching either in the app or the browser, let me reproduce this and see what our workflows team thinks
@Max_DA I can confirm that the current_user.id was being console logged when there was no user viewing the app. Waiting to hear back from our engineers on if there is a way to clear the cache or if I should file a bug report.
In my testing, the logs always showed the same user ID and it was for myself, in your situation is it randomly changing the user ID every single time it runs and console logs?
Could you give me more details on the use cases where you are using current_user as a logic check for security?
We are using current_user to path further into internal API Resource that is being called from the app or workflow, and then feed it into internal authorization system to identify if given user is allowed to run the operation they are attempting to run from the app or workflow step.
Specifically for workflows we have build logic assuming that current_user being empty identifies that operation is being run by scheduler or webhook, and we apply dedicated role for such calls, but instead we see one of Retool admin user coming as current_user.
About what comes in current_user - may be your are the admin of the space you tested in, try inviting someone as a less privileged user that can edit Workflows but does not own them and ask them to create a scheduled workflow - my expectation would be that you still will be current_user.
Thank you for the details! Very interesting use case.
Our engineers found that we have a 'feature flag' to ensure that current_user is null in non-manual workflow runs.
If you share your org name, I should be able to look you up and flip the flag to active, if you are hosted on our cloud.
If you are self hosted let me know and I can get more details on how you can flip this flag.
It seems like the flag was created and the docs were written but then the flag was not automatically turned on for all users. We are currently discussing if we should change the docs or apply this flag to all users
On a side note, I have some other users in my org but I am admin so it seems to continue to default to be, but I also created the workflow as well. But you are right it seems to go to admins currently.
@Max_DA Yes that is correct, this flag is managed by Retools license server, there are other variables that are controlled by the container properties.
We have an internal application for feature flags, where once we have the org ID we can toggle it and then it will be applied your self hosted deployment
I saw there were two orgs, one under damien that had an expired key, so I assumed you are using the other one under eningeering-bot@dolarapp.com and added they feature flag to that.
Self hosted instances will get updates from our servers every 6 hours so it should be reflected then.
The other point a teammate of mine brought up is that you likely need to be on our latest stable version, so if you haven't upgraded to 3.114 you may need to do that as well