Fork — This is a community-maintained fork of bugy/script-server (original author: @bugy). The upstream project is no longer actively maintained.
The web frontend was upgraded from Vue 2 (Vue CLI + Webpack + Karma) to a modern toolchain:
- Vue 2 → Vue 3: v-model refactor (
value/input→modelValue/update:modelValue),emitsdeclarations, lifecycle hook renames (beforeDestroy/destroyed→beforeUnmount/unmounted), removal ofVue.set/Vue.delete/$set/$delete(Vue 3 Proxy reactivity),:deep()CSS selectors, and Vue Router 4 / Vuex 4. - Vue CLI + Webpack → Vite: faster builds; assets are emitted into a single hashed
web/assets/folder (the server's web-build check was updated accordingly). - Karma + Mocha → Vitest (jsdom): the unit suite runs headless without a browser
(
npm run test:unit-ci). A few materialize-CSS browser-only behaviours (dropdown/modal animations, layout measurements) are skipped under jsdom. - Removed the obsolete
vue.config.js,babel.config.js, and Karma entry point.
Dev commands are unchanged: npm run serve (dev server) and npm run build (production build).
A docker-compose.yml is now included at the root of the repository for quick local deployments:
# Start
docker compose up -d
# Stop
docker compose downMount your script configs in ./conf/runners/ and logs will be written to ./logs/.
See the full docker-compose instructions below.
Unit tests added for the DateField and TimeField Vue components (42 tests total), covering label/input rendering, two-way value binding, and required-field validation.
A Docker image for this fork is now published automatically on every commit to master:
docker run -d \
-p 5000:5000 \
-v /path/to/your/conf/runners:/app/conf/runners \
-v /path/to/your/logs:/app/logs \
ghcr.io/knep/script-server:latestAvailable tags: latest (master), stable, and semver tags (e.g. 1.19.0) on git releases.
See the full installation instructions below.
A new time parameter type shows a native time picker in the UI and passes the selected time to the script in a configurable format.
Configuration example:
{
"name": "start_time",
"type": "time",
"time_format": "%H:%M"
}time_formatis a Python strftime format string. Default:%H:%M(24-hour HH:MM).- The UI always shows a native time picker. The script receives the time in the configured format.
- An invalid
time_format(e.g."HH:MM"instead of"%H:%M") is now detected at startup with a clear error message.
All responses (including WebSocket upgrade responses) now include the following security headers:
| Header | Value | Condition |
|---|---|---|
X-Content-Type-Options |
nosniff |
Always |
Referrer-Policy |
strict-origin-when-cross-origin |
Always |
Content-Security-Policy |
default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss:; frame-ancestors 'none'; object-src 'none' |
Always |
Permissions-Policy |
camera=(), microphone=(), geolocation=() |
Always |
Strict-Transport-Security |
max-age=31536000; includeSubDomains |
HTTPS only (cookie_secure: true) |
X-Frame-Options: DENY was already present; frame-ancestors 'none' in the CSP provides equivalent coverage for modern browsers.
A new date parameter type shows a native date picker in the UI and passes the selected date to the script in a configurable format.
Configuration example:
{
"name": "start_date",
"type": "date",
"date_format": "%d/%m/%Y"
}date_formatis a Python strftime format string. Default:%Y-%m-%d(ISO 8601).- The UI always shows a calendar date picker. The script receives the date in the configured format.
- An invalid
date_format(e.g."DD/MM/YYYY"instead of"%d/%m/%Y") is now detected at startup with a clear error message.
- GitHub Actions CI added (view workflows): Python 3.10/3.11/3.12/3.13 matrix + Node 22 frontend tests on every push and pull request.
- Cookies (
username,token, XSRF) are now set withHttpOnly,SameSite=Lax, andSecureflags. TheSecureflag can be disabled inconf.jsonvia"cookie_secure": falsefor HTTP-only deployments.
Python version support: updated minimum from Python 3.7 (end-of-life since June 2023) to Python 3.9+ (Python 3.13 recommended).
Python 3.13 note: the crypt standard-library module was removed in Python 3.13. If your htpasswd file contains DES-crypt passwords (entries that do not start with $2y$, $apr1$, or {SHA}), the server will refuse to start with a clear error message. Regenerate those passwords using bcrypt (htpasswd -B) or SHA-1 (htpasswd -s).
Fixes:
- Replaced invalid string escape sequences (
\d,\w,\/,\,\|,\p,\[,\.) with raw strings (r'...') in test files — these would becomeSyntaxErrorin Python 3.14 - Replaced deprecated
thread.setDaemon(True)withthread.daemon = Trueinuser_file_storage.pyandauth_abstract_oauth.py
Dependencies (requirements.txt):
- Raised Tornado floor from
>=4to>=6.1(Tornado 4/5 are incompatible with Python 3.12) - Added
requests>=2.28as an explicit dependency (used by HTTP notification destinations) - Documented optional dependencies (
ldap3,bcrypt) with install instructions
Script-server is a Web UI for scripts.
As an administrator, you add your existing scripts into Script server and other users would be able to execute them via a web interface. The UI is very straightforward and can be used by non-tech people.
No script modifications are needed - you configure each script in Script server and it creates the corresponding UI with parameters and takes care of validation, execution, etc.
- Different types of script parameters (text, integer, date, time, flag, dropdown, file upload, etc.)
- Real-time script output
- Users can send input during script execution
- Auth (optional): LDAP, Google OAuth, htpasswd file
- Access control
- Alerts
- Logging and auditing
- Formatted output support (colors, styles, cursor positioning, clearing)
- Download of script output files
- Execution history
- Admin page for script configuration
For more details check how to configure a script or how to configure the server
Python 3.9 or higher (Python 3.12 recommended) with the following modules:
- tornado >= 6.1
- requests >= 2.28
Optional modules (required only for specific features):
| Module | Feature |
|---|---|
ldap3 >= 2.9 |
LDAP authentication |
bcrypt >= 4.0 |
bcrypt password support in htpasswd auth |
Install all dependencies at once:
pip install -r requirements.txtInstall with optional dependencies:
pip install -r requirements.txt ldap3>=2.9 bcrypt>=4.0OS support:
- Linux (main). Tested and working on Debian 10, 11
- Windows (additional). Light testing
- macOS (additional). Light testing
Any more or less up to date browser with enabled JS
Internet connection is not needed. All the files are loaded from the server.
- Download script-server.zip from Latest release (last upstream release: v1.18.0)
- Create a script-server folder anywhere on your machine and extract the zip content into it
- Install dependencies:
pip install -r requirements.txt
For detailed steps on Linux with virtualenv, see the Installation guide.
Images for this fork are published on GitHub Container Registry:
# Pull the latest image (built from master)
docker pull ghcr.io/knep/script-server:latest
# Run with your script configs and logs persisted
docker run -d \
-p 5000:5000 \
-v /path/to/your/conf/runners:/app/conf/runners \
-v /path/to/your/logs:/app/logs \
ghcr.io/knep/script-server:latestAvailable tags:
| Tag | Source |
|---|---|
latest |
master branch — most recent changes |
stable |
stable branch |
1.2.3 / 1.2 |
Git tag v1.2.3 |
A ready-to-use docker-compose.yml is included at the root of the repository:
# Clone or download docker-compose.yml, then:
docker compose up -dPlace your script runner configs in ./conf/runners/ (created automatically on first run).
Execution logs are written to ./logs/.
To customise the server (auth, SSL, port…), uncomment the optional volume lines in docker-compose.yml:
volumes:
- ./conf/runners:/app/conf/runners
- ./logs:/app/logs
# - ./conf/conf.json:/app/conf/conf.json:ro # server config
# - ./conf/.htpasswd:/app/conf/.htpasswd:ro # htpasswd auth
# - ./conf/theme:/app/conf/theme:ro # custom CSS/images- Clone this repository
- Run
tools/init.py --no-npm
init.py should be run after pulling any new changes.
Frontend (web-src/, Vue 3 + Vite). If you are making changes to web files:
npm installonce to install dependenciesnpm run serve— Vite dev server (proxies API calls to the backend on port 5000)npm run build— production build intoweb/npm run test:unit-ci— run the Vitest unit suite (headless, jsdom)
See OpenBSD process termination issues.
- Create configurations for your scripts in the conf/runners/ folder (see script config page for details)
- Launch launcher.py from the script-server folder
- Windows:
launcher.py - Linux/macOS:
./launcher.py
- Add/edit scripts on the admin page
By default, the server will run on http://localhost:5000
All the features listed above and some other minor features can be configured in conf/conf.json. It is allowed not to create this file — default values will be used in that case. See server config page for details.
Cookies (including the XSRF token) are sent with the Secure flag by default, so
they are not stored by the browser over plain HTTP. Combined with the default
token XSRF protection — which requires the browser to read the _xsrf cookie and
echo it back — this makes every POST (e.g. starting an execution) fail with
403 and an "XSRF token missing or invalid" message.
When serving over HTTP (not HTTPS), set cookie_secure to false in conf/conf.json:
{
"security": {
"cookie_secure": false
}
}Alternatively, switch XSRF protection to header mode ("xsrf_protection": "header"),
which validates the X-Requested-With header instead of a cookie token and so does
not depend on cookies at all. Keep the secure defaults for any HTTPS deployment.
Tip: if you previously ran with the secure defaults, clear the stale
_xsrfcookie for the site (or use a fresh browser profile) after changing these settings.
Admin panel is accessible at admin.html (e.g. http://localhost:5000/admin.html)
All web/operating logs are written to logs/server.log.
Each script's logs are written to a separate file in logs/processes. File name format:
{script_name}_{client_address}_{date}_{time}.log
Script-server has bundled configs/scripts for testing/demo purposes, located in the samples folder. You can
link/copy these config files (samples/configs/*.json) to the server config folder (conf/runners).
Script-server is designed to be secure and invulnerable to attacks, injections or user data leaks. However, to be on the safe side, it's better to run Script server only on a trusted network.
Script server guarantees that all user parameters are passed to an executable script as arguments and won't be executed under any conditions. There is no way to inject a fraudulent command from the client side. However, user parameters are not escaped, so scripts should take care of not executing them directly (the general recommendation for bash is to wrap all arguments in double-quotes). Using typed parameters is recommended when appropriate, as they are validated for proper values and are harder to exploit.
Important! Command injection protection is fully supported for Linux, but only for .bat and .exe files on Windows.
(v1.0 - v1.16) Script server is vulnerable to these attacks.
(v1.17+) Script server is protected against XSRF attacks via a special token. XSS protection: the code is written according to OWASP Cheat Sheet and the only known vulnerabilities are:
output_format=html_iframe, see the reasoning in the linked Wiki page
If you find a bug or want to propose a feature, please open an issue on this fork.
Contributions are welcome:
- Bug reports and feature proposals
- Pull requests (fixes, features, documentation)
- Any other improvements you can think of