You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
Declarative config seed (CONFIG_SEED_PATH) — rebuild an instance from a yaml file. See docs/seed.md
An empty database creates its own schema at startup
Audit trail (/admin/audit) — append-only, and secrets are never stored
Status page (/admin/status)
Job and job output retention (JOB_RETENTION_DAYS), off by default
Visual editors for Categories, Roles and Constants. Comments and anchors survive a save
The config source is switchable from the UI (config_source) — file or database
A HashiCorp Vault page, with a read-only connection test
Environment variables are editable from the settings page, saved to persistent/.env
Config API — read, write, import, export and convert. See GET /api/v2/docs
The designer was rebuilt — a file tree, and buttons instead of raw YAML
The settings pages were rebuilt — tabbed, with per-field help
Server-wide default language and theme, plus a Color theme
A visual cron editor with presets and a next-runs preview
Schedules can be created from the admin UI
GIT_PUSH_COMMAND env var added, to customize the command used when pushing git repositories
Group filter for LDAP (admin panel > LDAP > Group Filter). A regular expression matched against the group name, the same one Entra ID and OIDC already have — only matching groups are kept, mapped to roles and sent to playbooks. Empty keeps every group, which is what every existing installation does today. A pattern that does not compile is logged and ignored rather than stripping everyone's roles
EXTRAVARS_USER_FIELDS env var and the userExtravars form property, to choose which keys of the launching user are sent to the playbook as ansibleforms_user. Empty keeps the whole object, as before; a comma separated list keeps only those keys and none sends nothing. The form property overrides the environment variable. The frontend __user__ object and every permission check are unaffected. See docs/faq.md
The config seed is re-applied when the file changes (CONFIG_SEED_RELOAD_SECONDS, 60s by default), so a seed edited in git reaches a running instance without restarting it. POST /api/v2/config-seed/apply and SIGHUP force an apply immediately. A failed reload is never fatal: the configuration already in force is kept and the Status page reports it. See docs/seed.md
EXPRESSION_SANITIZER env var, to choose how strictly server expressions (without runLocal) are checked: off refuses every server expression, paranoid allows only direct fn./fnc. calls, strict (default) also allows methods on their result, and legacy restores the 6.2.1 rules. legacy lets any authenticated user run code on the server, so it can only be set in the real environment (not from the settings page), logs a warning at startup and for every expression strict would refuse, and shows as a warning on the Status page
Categories can be moved around the tree — move up, move down, indent and outdent, in the settings Categories page and in the designer, taking the whole subtree along
Constants can hold a list or a nested object — the value box in the designer and on the settings page is read as YAML, so a block list, a list of objects and a nested map are stored as such instead of as their source text
Changed
Permission failures answer 403 instead of 401
PUT /api/v2/settings/ is now a partial update
The settings menu has five sections: System, Forms, Access, Connections, Jobs
Menu entries your role cannot open are hidden
The designer works when the config lives in the database
Backup and restore follow the active config source
LDAP loses its Advanced toggle — the four group fields always apply
Removed
LDAP is_advanced toggle. On upgrade the fields are blanked where it was off, old values logged first
Fixed
A designer save deleted form files the loader had skipped
A repository named forms treated its whole root as a forms folder, so a save deleted unrelated yaml files
Approving a job twice at once launched it twice
A multistep step whose status could not be read counted as passed
A failed backup listed as a valid restore point
Restoring a backup with no usable dump reported success
NIGHTLY_BACKUP_RETENTION=0 deleted every nightly backup
The designer could silently overwrite a form — ids were reused
Designer saves wrote to the local config.yaml while the app read a repository
The designer overwrote a ytt-templated config with its rendered output
Designer edits were discarded when navigating away or reloading
The "Show Extravars" role option never took effect — two spellings
A login with no Authorization: Basic header hung for ever, leaking a socket
A 401 surviving a token refresh looped refresh and retry
LOG_SYSLOG_PROTOCOL never had any effect — misspelt read, so syslog always used UDP
MongoDB datasource queries always failed
Query fields inside a wizard step or list row failed for everyone except an admin
Query placeholders with dot notation, an index path or placeholderColumn stopped working
Query values were escaped with MySQL's rules on every datasource, corrupting backslashes and quotes
Renaming a repository moved its working tree before the change was written, orphaning it if refused
A cron schedule with an inverted range (0 0 * * 5-1) saved and never ran
An invalid MASK_EXTRAVARS_REGEX or REGEX_FILTER_JOB_OUTPUT broke job launching and made every job unviewable
Bulk delete on Known Hosts removed the wrong entries — rows were keyed by position
OLD_BACKUP_DAYS=0 deleted every config restore point. It now keeps everything
GET /api/v2/repository/<name> kept answering with the head from before a pull for up to an hour. The repositories model is cached and findByName reads that cache, while the git operations wrote status, output and head with their own SQL and evicted nothing — so the single record disagreed with GET /api/v2/repository and with the database. Anything polling it to learn whether a commit had landed waited on a value that could not change
Wizard didn't load varsFiles
target="_blank" was stripped from links in html and expression fields, so they opened in the current tab and the form was lost (#480). rel="noopener noreferrer" is now forced on any link that opens a new tab
Startup failed with Failed to create the path for the log files when LOG_PATH's parent folder did not exist — the folder is now created recursively
Prefill bug (relaunch and load from form)
Designer: while a form's YAML was invalid - halfway through typing any line - the form jumped to a "Parsing issues" group in the tree and the editor was rebuilt, losing the cursor and focus
Security
A user without verbose permission could relaunch a verbose job and get its output
Server-side expressions could break out of the evaluator and run commands — the guard only checked how one started
A form you had no access to appeared on the home page when two files shared a name
A server expression reached banned names through string property keys (fn.x['constructor']) — arbitrary code execution for any signed-in user
A group name containing HTML ran as script in the users list
Opening another user's job answered 200 with an empty body instead of refusing, and approve/reject skipped its role check
A git pull that could not read its repository record published the stored password
/api/v1/query accepted arbitrary SQL, bypassing the v2 guard
Form load warnings rendered the form name as HTML on the home page
A failed login revealed whether the username existed
Changing a password needed no proof of the current one
The query endpoint ran any SQL from the request body, with only a login required
A field value reached a form expression as raw text, so a crafted link ran script
Refresh tokens were never verified, re-checked or retired
Anyone could sign in as any user, including admin, through the SSO endpoints
Reserved extravars from the request beat the form, so any playbook could run with any credential. A __x__ key is now accepted only when the form declares a field of that name
Any authenticated user could abort any other user's job
An AWX workflow node name ran as script in the job output
Dropdown option values rendered unescaped while the search box was empty
The ansible-vault password was written to the log in full
VAULT_TOKEN was returned in clear text to any user with showSettings
The v2 log endpoints had no permission check
A duplicate role name in config.yaml granted its rights twice over
The backup's environment filter missed export NAME=value, shipping ENCRYPTION_SECRET beside the dump it decrypts
POST /api/v2/schema required no authentication and drops every table
PUT /api/v2/settings accepted forms_yaml, bypassing the lock, validation and restore point
/admin/schedules and /admin/stored-jobs were reachable with only showSettings
A form's constants came from the request instead of the configuration, so a caller could rescope a query