1.11.0
✋ Heads-ups
☝️ OctoPrint 1.11.x is the last OctoPrint to support Python 3.7 and 3.8
Python 3.7 has now been EOL since June 27th 2023, and the maintenance overhead caused by still having to support it is becoming unfeasible. Python 3.8 has now been EOL since October 31st 2024, and it is to be expected that the maintenance overhead will further rise due to that.
As a consequence, OctoPrint 1.11.x is the final OctoPrint version to support both Python 3.7 and 3.8. OctoPrint 1.12.0+ will require at least Python 3.9.
How do you know if you will be affected and need to update? A newly added healthcheck mechanism has been added that will now alert you if your environment is outdated and about to be left behind, and a new FAQ entry is in place to help you figure out how to update your runtime environment.
This will be kept updated, so that you will also receive early warnings about future deprecations this way.
🧩 OctoPrint will now auto-escape all internal templates, plugin authors should opt-in as well!
Starting with OctoPrint 1.11.0, OctoPrint will ship with auto-escaping all injected template variables and other included expressions in its template system. For 1.11.0 and 1.12.0, this will only be done for bundled plugins and those third party plugins that have opted into autoescaping. Starting with OctoPrint 1.13.0 however, third party plugins will have to opt out in order to not have autoescaping enabled on their templates.
A new entry has been added to the FAQ that has further details.
🧩 WebcamProviderPlugin.take_webcam_snapshot
has gotten its parameters fixed
If you are the maintainer of a third party plugin using the WebcamProviderPlugin
mixin and have implemented its take_snapshot
method, be advised that an implementation error in OctoPrint has been fixed and the implementation aligned with the documentation: the method will now be called with the webcamName
parameter being a string containing the name of the requested webcam, as documented, not a full webcam configuration object as previously wrongly implemented.
Changes
🔒 Security fixes
-
Severity Moderate (4.3): It was possible to bypass the login redirect and directly access the rendered HTML of certain frontend pages. This was caused by the use of a custom HTTP header that would disable the login redirect on preemptive caching of the frontend HTML, which was not properly stripped from incoming request, thus allowing the same behaviour through manipulating the headers of the requesting browser.
The impact on data exposure was minimal because, typically, data is loaded via API requests that correctly enforce user authentication. In the current codebase, cases where data is directly embedded in the page content are rare. However, one notable exception is the authenticated variant of the reverse proxy test page, which displays the IP addresses of configured reverse proxies.
This has now been fixed by removing the header altogether and implementing the login bypass differently with purely internal flagging.
See also the GitHub Security Advisory and CVE-2025-32788
✨ Features & improvements
Core
- #833: Added a confirmation to the file delete button in the file list. Bulk deletions can still be done easily via the newly added Upload Manager Plugin, see below.
- #1313: Added an option for whether to automatically render captured timelapses. Timelapses can now be set to never render automatically, only in case of a successful or only in case of a failed print, and of course also always (the previous behaviour). See also PR#4994.
- #4864: Added Prusa MMU commands
M707
andM708
to default list of commands that should never be auto-uppercased when sent to the printer through the terminal tab. See also PR#5015. - #4932: Added support for multi factor authentication (MFA) schemes to OctoPrint's login mechanism. A new plugin type
MfaPlugin
allows to hook into that through plugins. A first plugin utilizing that plugin type to implement TOTP authentication can be found at OctoPrint/OctoPrint-MfaTotp and is now also available on the plugin repository! - #4968: Removed
octoprint.server.(loginFromApiKeyRequestHandler|loginFromAuthorizationHeaderRequestHandler)
as they were no longer used and undocumented. - #4973: Include stack traces with fatal errors. Also make
InvalidYaml
exceptions more helpful by including the full message from the triggeringYAMLError
. Also switch to usingFATAL
instead ofERROR
for startup error logging. - #4990: Made
@
commands case insensitive. - #5018: Added support to specify the current extruder as tool for a new target temperature on the API. See also PR#5022.
- #5036: To make the configuration of trusted (reverse) proxies less confusing and error prone, the
server.reverseProxy.trustedDownstream
has been renamed toserver.reverseProxy.trustedProxies
and an additional flagserver.reverseProxy.trustLocalhostProxies
has been added that will ensure that reverse proxies on localhost will always be trusted if set. A configuration migration is in place to automatically migrate existing configurations to these two new settings. - #5063: Added a configurable delay to wait for after print completion & before rendering the just recorded timelapse. If a new print is started while this timer is running, OctoPrint will now enqueue the timelapse for later rendition during idle time. OctoPrint will only start rendering if after the timer has elapsed no new print has been started.
- #5068: OctoPrint will now recognize
.gc~
as a valid GCODE extension. - #5072: The search bar has been extended to support an additional
user:
filter to filter for files uploaded by certain users. Consequently, the core has been adjusted to store the uploading user in the file's metadata, which so far wasn't the case. - #5079: Clarified the wording of the "tool doesn't exist" message.
- #5059: Added an option to allow suppressing the second "hello" command during printer connection initialization.
- PR#5029: Migrated the code to Pydantic 2.x under Python 3.8+. Since OctoPrint 1.11.0 will be the final version to still support Python 3.7, also added a compatibility layer to be able to use the Pydantic 2.x API under Python 3.7 with Pydantic 1.
- PR#5054: Fixed two comma splices.
- PR#5060: Support assigning mapped groups to users based on specific HTTP headers. This is to allow external authentication mechanisms to be put in front of OctoPrint and allow them to be used without manual group assignment in OctoPrint being required on each new user.
- Refactored the plugin interface to use
importlib
instead of the outdated vendoredimp.py
to detect installed plugins from entrypoints. - Added some more aliases for the recovery page and the reverse proxy test page. You may now also find the recovery page under
/recovery
,/rescue/
and/rescue
on top of its canonical/recovery/
, and the reverse proxy test page under/reverse_proxy_test
,/reverse_proxy_check[/]
,/reverse-proxy-test[/]
,/reverse-proxy-check[/]
,/proxy_test[/]
,/proxy-test[/]
,/proxy_check[/]
and/proxy-check[/]
on top of the canonical/reverse_proxy_test/
. - Switched to
ruff
for linting & formatting of the code base. - Refactored the code base to get rid of any
pkg_resources
dependencies, switching over the plugin core system to more modern libraries in the shape ofimportlib
andpackaging
. - Added auto-discovery of common plugin assets following the naming scheme
<type>/<identifier>.<ext>
in theAssetPlugin
mixin. - Ensured that Tornado errors end up in
octoprint.log
. - Enabled auto-escape of template variables for all of OctoPrint's internal templates, those in bundled plugins and those in third party plugins that have opted into auto-escaping. With OctoPrint 1.13.0, this will become the default! Please also see the heads-up above.
- Added support for disabling the warnings about
serial.log
and/orplugin_timings.log
being active by settingplugins.logging.serial_log_warning
and/orplugins.logging.plugintimings_log_warning
tofalse
inconfig.yaml
. This is to support specific setups out there that keep them enabled at all times, disregarding their performance impact. - Improved the plugin list logging in
octoprint.log
. There are now two different lists logged, one for bundled and one for third party plugins, and both also show a counter of total plugins found. This should make for easier checks when looking at logs for certain third party plugins. - Made OctoPrint compatible to Python 3.13.
- Updated several dependencies.
Core UI
- #4951: Extended the
onBeforePrintStart
frontend callback to include the file data of the started print file. See also PR#5073. - Added
data-octoprint-version
to thebody
tag. Will contain the base version (so1.11.0
for1.11.0.dev
,1.11.0rc*
etc). This should allow for easier CSS matching. - Added an additional reload popup that replaces the modal reload overlay on plugin/settings changes, which is way less intrusive and should cause less annoyance.
- Added support for camel-cased versions of the event callbacks. Allows to create
onEventPluginFooTriggered
instead ofonEventplugin_foo_triggered
. The prior callback will also still be checked. - Added links to the reverse proxy test page and the recovery page to the loading error view.
- Gave user settings a fixed minimal height.
- Adjusted the dropdown submenu CSS to support submenus following their parent's orientation. So if the parent opens on the right of the parent, the submenu will now as well.
- Changed
bytes
toB
in file size displays usingformatSize
. - Added a helper
showTextboxDialog
for spawning a text input dialog. - Improved the error message for login failures due to CSRF check failure.
- Custom controls are now read from the settings instead of the dedicated API endpoint, which however will stay for reasons of backwards compatibility.
- Added a new CSS class for labeled controls in inline forms,
control-labeled
.
JavaScript Client Library
- Added tooling to set/delete cookies,
OctoPrintClient.setCookie
andOctoPrintClient.deleteCookie
.
Custom Control Manager Plugin (✨ New!)
Implementing #4526, OctoPrint 1.11.0 now ships with a new bundled plugin called "Custom Control Manager" that will allow you to configure the long existing core feature of custom controls right from within the UI. This plugin is a port of the long abandoned Custom Control Editor plugin by Marc Hannapel. Large parts where completely reimplemented from scratch and the UI and UX saw some heavy changes as well.
Health Check Plugin (✨ New!)
OctoPrint 1.11.0 ships with a new Health Check Plugin that will alert you of any issues with your runtime environment and OctoPrint installation. For now, it checks the following things:
- sufficient file system storage across all configured data folders
- OctoPrint's version not being more than two minor versions behind
- Python version not being EOL or close to EOL
Health checks are kept as unobstrusive as possible in the shape of a little navbar icon. Only high priority issues will cause a popup. Currently that only involves Python versions that are already EOL, and those will only be shown every 30 days (per browser, by the use of a browser cookie).
Additional health checks can be added by plugins through the octoprint.plugin.health_check.get_additional_checks
hook.
A forthcoming update of the bundled PiSupport Plugin adds the results of the throttle check, model support and default password use to the set of health checks.
This is one step towards reducing the amount of outdated environments used by people and giving them early heads-ups that they need to update to not be left behind.
Upload Manager Plugin (✨ New!)
OctoPrint 1.11.0 bundles a new plugin "Upload Manager", which is a plugin derived from the long abandoned Filemanager plugin authored by Marc Hannapel.
This Upload Manager can be accessed through a new button in the file list header and allows various bulk operations to more easily manage a growing file collection.
With the availability of this Upload Manager, confirmation dialogs for file deletion have been added, as requested in #833. With the manager in place and thus a bulk deletion that only prompts for confirmation once, this should not interrupt any existing management workflows too much.
Added functionality vs the Filemanager plugin:
- progress information for bulk operations
- download of multiple files or folders as zip files
- multi select with shift/ctrl-click
- collision detection on file rename
- various UX improvements
Announcements Plugin
- Minor styling change for the notification bubble.
Backup Plugin
- #4961: Fall back to restoring from backup by copying instead of directly unpacking the backed up base dir. This works around issues where the base dir OctoPrint is using is not owned by OctoPrint's process and thus cannot be replaced during the restore.
Classic Webcam Plugin
- #5016: Added support for basic, digest and bearer authentication schemes on the snapshot URL.
Discovery Plugin
- The SSDP xml will no longer contain the version of the OctoPrint server. This is to prevent information leakage that could be used for targeted attacks.
Plugin Manager Plugin
- Added a heads-up about installing third party plugins that needs to be acknowledged by the user prior to being able to install third party plugins via the plugin manager's "Get more" link. This is a one-time message dialog that is meant to educate users about the fact that third-party plugins could cause issues, including security problems, and explain what is done against that.
- Added the labels from the plugin repository to the list of installed plugins and the built-in plugins in the repository browser. "cloud", "commercial", "free-tier" and an additional "abandoned" label will now be shown next to the plugin as applicable.
- The Plugin Manager will now create a backup of the plugin export on startup, in the basedir and named
backup_plugin_export.json
. This might help people recover their installed plugins if all they still have is the basedir.
Software Update Plugin
- Updated the minimum software versions supported for updating. The minimum versions are now Python 3.7, setuptools 44.1 and pip 20.3. OctoPrint 1.12.0 will update that again.
- Removed the
--no-cache-dir
argument from thepip
call used to install plugin packages.
Virtual Printer Plugin
- Support settings
M20
to forced upper case.
Documentation
- PR#5065: Fixed some dead links and improved some wording in the plugin tutorial.
- PR#5069: Added documentation for the
METADATA_STATISTICS_UPDATED
event. - Updated the developing environment documentation for VSCode.
- Documented the
collapsed
attribute on control containers in the custom controls definition.
Development, Testing & CI
- Added a new command
css:watch
on the command line that will auto build less files on modification. - Added
lessc run
to pre-commit to ensure all CSS files have been updated. - Migrated some more unit tests to
pytest
. - Extracted E2E testing workflow into its own custom composite action to be used with plugins as well and added a README to the E2E test suite.
Improvements done during the release candidate phase
- Core
- Improved Tornado and CSRF failure logging.
- Healthcheck Plugin
- #5110: Allow to mark reported health check issues as read.
🐛 Bug fixes
Core
- #5014: Fixed the
webcamName
parameter ofWebcamProviderPlugin.take_snapshot
to align with the documentation. - #5075: Fixed offset of chamber temperature not being applied properly.
- Fixed parsing of the filament diameter from GCODE generated by BambuStudio & OrcaSlicer
- Fixed template sorting
- Fixed logging of exceptions in WSGI
- Fixed error reporting on file upload API in case of errors during copy/move
- Fixed that OctoPrint was sending an
M20
without the printer's storage having been detected as available. - General code clean-up
Core UI
- #4963: Upgraded to Font Awesome 6.5 to work around a glyphbox error in Firefox.
- #5056: Use permission name instead of description as tooltip in the permission list.
- Fixed a hash sync so that the reload overlay/popup should now no longer show on reconnect if the settings have been changed in any way since initial connect.
JavaScript Client Library
- Use the first matching cookie in
OctoPrintClient.getCookie
instead of the last. This is to align the logic with the one found in the backend to reduce the risk of wrong cookie handling due to browser bugs like https://bugzilla.mozilla.org/show_bug.cgi?id=1929881
Achievements Plugin
- Fixed default groups of custom permission
Classic Webcam Plugin
- #5076: Fix stopping of the webcam stream on hiding the tab/windows, by replacing its
src
with a transparent gif instead of setting it to empty.
Error Tracking Plugin
- Removed an unused API endpoint.
GCODE Viewer Plugin
- #5080: Fixed rendering of
G2
/G3
arc commands withoutI
orJ
. - PR#5047: Re-added the web worker API compatibility check, to prevent hard to diagnose issues caused by certain privacy enhancing browser extensions that block said API.
- Limited
skipuntil
check to theGCODE_VIEWER
permission.
Plugin Manager Plugin
- Use a temporary folder for plugin archive uploads instead of a temporary file, so that the name of the uploaded file persists. Otherwise wheels can't be installed.
Software Update Plugin
- Switched the PyPI release check to a new endpoint, as the one so far used was deprecated.
- Ensured that request errors encountered by the PyPI release check will actually bubble up and be reported to the frontend.
Documentation
- Fixed a documentation error in the available types for AssetPlugins, the correct keyword for additional parts for the JS Client Library is
clientjs
, notjsclient
.
Fixes done during the release candidate phase
- Core:
- #5098 & #5100 (regression): Fixed permission fetch and
login_mechanism
setting for incoming requests with API keys. This solves the problem with all requests with an API key being responded to with an HTTP status of 403, and any API key based requests not usingGET
,HEAD
orOPTIONS
methods with a CSRF validation failure and thus an HTTP Status of 400, breaking communication with most third party clients. - #5099 (regression): Fixed templating macros being broken for third party plugins not supporting autoescaping.
- #5105 (regression): Fix the "Remeber me" functionality
- #5109: Fix
octoprint.systemcommands.SystemCommandManager.has_(server_restart|system_restart|system_shutdown)_command
not returningFalse
for empty commands. Not a regression, but a small enough fix to still include in 1.11.0. - #5115: Auto discovered assets for the
AssetPlugin
mixin would be returned containing\
under Windows, leading to 404s when attempting to load them in the browser. This auto discovery is a new feature added in 1.11.0 (used by the bundled Health Check plugin) and thus this was not a regression, but rather a bug in newly added functionality. - #5116: Fix a bug with handling JS errors in the webasset bundler.
- #5117 (regression): Fix warnings logged to the browser console due to mistakes made when upgrading to Font Awesome 6.5.1.
- #5121 (regression): Fix spamming of requests against
/api/files/sdcard/<path>
on selecting a file on the printer's SD card. Also added E2E tests for selecting both local and printer-side files. - #5125 (regression): Fix reauthentication logic to not log out on reauth. This is actually not a real regression and was present in 1.10.x as well, but changes in 1.11.0 made it almost always trigger vs almost never on 1.10.x (due to some race condition), so it feels like a regression and needed fixing in the RC phase.
- #5132 (regression): Fix session keepalive not getting started. Side effect of the fix of #5125.
- Fix a redirect path traversal bug in
validate_local_redirect
. This in theory could have been abused by some manipulated link to redirect a login to a path on the same server as OctoPrint beyond those marked as safe, e.g. a malicious plugin or an external app on another path. Not a regression, but better fix this now than later. Thanks to @jacopotediosi for the discovery and the suggested fix.
- #5098 & #5100 (regression): Fixed permission fetch and
- Custom Control Manager Plugin
- Error Tracking Plugin
- (regression) Silence some Sentry log spam
- (regression) Fix an issue in the ignored exception filter causing no errors to be reported
🎉 Special thanks to all the contributors!
Special thanks to everyone who contributed to this RC, especially to @ccatlett1984, @cp2004, @dawidpieper, @endrift, @Hillshum, @its-leofisher, @jacopotediosi, @jneilliii, @MaienM, @nmschulte, @ofoxus, @WildRikku, @WisdomCode and @zaventh for their PRs!
And an extra shoutout to our 10 first time contributors: @ccatlett1984, @endrift, @its-leofisher, @jacopotediosi, @MaienM, @nmschulte, @ofoxus, @WildRikku, @WisdomCode and @zaventh! 🎉