getredash/redash · error · ValueError
Scripts can only be run from the configured scripts director
Error message
Scripts can only be run from the configured scripts directory
What it means
Raised in ScriptQueryRunner.__init__ (redash/query_runner/script.py:65) as ValueError when the configured scripts path contains '../', i.e. it is not confined to a single directory. This is a deliberate path-traversal guard: the runner only permits executing scripts from one whitelisted directory, and any configuration that could escape it is rejected at construction time.
Source
Thrown at redash/query_runner/script.py:65
},
"required": ["path"],
}
@classmethod
def type(cls):
return "insecure_script"
def __init__(self, configuration):
super(Script, self).__init__(configuration)
path = self.configuration.get("path", "")
# If path is * allow any execution path
if path == "*":
return
# Poor man's protection against running scripts from outside the scripts directory
if path.find("../") > -1:
raise ValueError("Scripts can only be run from the configured scripts directory")
def test_connection(self):
pass
def run_query(self, query, user):
try:
script = query_to_script_path(self.configuration["path"], query)
return run_script(script, self.configuration["shell"])
except IOError as e:
return None, str(e)
except subprocess.CalledProcessError as e:
return None, str(e)
register(Script)
View on GitHub (pinned to ca79fe988d)
Solutions
- Set the path to the exact directory containing the scripts with no '../' segments (canonicalize it first: realpath)
- If you genuinely need multiple directories, use '*' with the understanding that it disables the confinement entirely
- Alternatively symlink the needed scripts into a single directory and configure that directory
Example fix
# before path: /opt/redash/../shared/scripts # after path: /opt/shared/scripts
Defensive patterns
Strategy: validation
Validate before calling
import os.path
path = os.path.realpath(path)
if path != '*' and '..' + os.sep in path:
raise ValueError('scripts path must not traverse parent directories') Try / catch
try:
runner = ScriptQueryRunner(configuration)
except ValueError as e:
return error_response(400, 'Invalid scripts path: {}'.format(e)) Prevention
- Canonicalize the directory with realpath before saving the data source
- Validate the path in the settings form server-side: must be absolute, existing, no '..'
- Use symlinks to aggregate scripts instead of traversal paths
When it happens
Trigger: Saving a Script data source whose path setting includes a parent-directory segment, e.g. '/opt/redash/../scripts' or 'scripts/../../shared/scripts'. The only path that bypasses the check is the literal '*' (allow anything).
Common situations: Admins trying to point two data sources at a shared parent directory; symlinks not usable so '../' is attempted; mis-typed absolute path that accidentally contains a parent segment.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Username and Password required
- Azure AD Client ID, Client Secret, and Tenant ID are require
- Script '{}' not found in script directory
- Neither password nor private_key_b64 is set.
- You must set the REDASH_COOKIE_SECRET environment variable.
AI-assisted analysis of getredash/redash@ca79fe988d (2026-08-28).
Data as JSON: /api/errors/77d8dd1f26466e44.
Report an issue: GitHub.