Skip to content

Releases: BlueLazyFish/Stage-Render

v0.1.1 — Security hardening

05 May 21:16

Choose a tag to compare

Post-release audit pass on top of v0.1.0. No behaviour change for clean inputs — just tighter rails for malicious or accidentally-malformed data. Recommended for everyone running v0.1.0.

What's fixed

🔴 Critical — eval() on persisted user data

stage/core/store_property.py::_eval_path previously ran eval(path, {"bpy": bpy, "__builtins__": {}}) on the data_path strings stored inside Studios. The empty __builtins__ blocked __import__ but bpy.ops.* and bpy.app.* were wide open — a poisoned .blend file could ship Studio.custom_paths[].data_path = "bpy.ops.wm.quit_blender()" (or worse) that fired on Apply Studio with no warning, no opt-in, no toggle.

Now: parse the path with ast.parse(mode='eval'), walk the tree, and refuse anything that isn't Expression / Name / Attribute / Subscript / Constant / Load / Index. Subscripts must use literal str or int indices. The only allowed root identifier is bpy. Calls, comprehensions, lambdas, arithmetic, comparisons, dunder access — all rejected with a new UnsafePathError.

🟠 High — Worker blend-path validation

subprocess.Popen with list-form already prevents argv injection, but Blender's CLI parser could mistake a --prefixed positional for a flag and consume the next argv entry as its value (so a blend_path of "-P" would steal the render-script slot). Defense in depth: refuse blend paths starting with - or containing NUL bytes; mark the job FAILED and try the next pending one.

🟡 Medium — Slack webhook scheme/host validation

slack_webhook accepted any URL, including file:// (read local files via urllib's default opener) and gopher:// (probe internal services). Now limited to http / https schemes with a non-empty netloc; rejected URLs are logged at WARNING and no network call is made.

🟢 Low — Preview cache cleanup is exception-safe

bpy.utils.previews.remove() can raise on shutdown paths where the Blender preview manager has already torn itself down. Wrap in try/except/finally so _pcoll always resets to None. Should clear up the recurring ImagePreviewCollection ... left open ResourceWarning seen in some test sessions.

Tests

13 new tests in tests/blender/test_security.py:

  • 9 cover the AST-walker — accepts real RNA paths, rejects calls / lambdas / arithmetic / dunder access / dynamic subscripts / syntax errors, propagates through resolve_value
  • 4 cover the slack_webhook scheme guard — file://, gopher://, no-host URLs all refused without calling urlopen; valid https:// URL still reaches urlopen as a happy-path sanity check

Total suite: 191/192 (one pre-existing dirty-state reload flake).

Install

Same flow as v0.1.0:

  1. Download stage-0.1.1.zip from the assets below
  2. Edit → Preferences → Get Extensions → Install from Disk…
  3. Pick the zip; Stage will upgrade in place — your settings, Studios, and queued jobs carry over

Same zip works on macOS, Linux, Windows.

Threat model footnote

Blender already runs Python from .blend files when "Auto Run Python Scripts" is enabled, so the broader Blender ecosystem already trusts authors of files you open. Stage's eval() was worse than that baseline because it had no toggle and no warning — it ran on Apply Studio regardless of the user's "auto-run" pref. v0.1.1 brings Stage in line with the safer practice: persisted data is structurally validated before it's evaluated.

v0.1.0 — Initial public release

05 May 20:45

Choose a tag to compare

First public release of Stage. Open source under GPL-3.0-or-later.

What is Stage?

A KeyShot-inspired scene state manager and persistent background render queue for Blender 5.1+.

Set up your scene once. Save unlimited Studios — each a snapshot of camera, lighting, world, visibility, render settings, output path. Switch between them in one click. Queue them all and render overnight while you keep working.

Highlights

  • Studios capturing camera, world, visibility, render settings, output path (each toggleable per-Studio)
  • Right-click → Store in Stage for arbitrary RNA paths
  • Inheritance (parent → child stores deltas only)
  • Locked Studios (refuse Update — for client deliverables)
  • Click-to-preview when selecting a Studio
  • Multi-select + bulk edit popups (group, parent, output, facet, lock, tags)
  • Studio Groups as variant axes
  • Render-settings templates — 5 builtins (Default + Instagram Square/Portrait/Story + YouTube) plus user-saved templates that persist across .blend files
  • Post-render actions — copy / move / delete folder / play sound / Slack webhook, ordered chain
  • Persistent SQLite render queue + background Blender subprocess that keeps the foreground UI responsive and survives Blender restarts
  • Output path templates ({studio}, {studio_uuid}, {frame:04d}, {date_time}, …) with directory-fallback resolver
  • Stored Properties Lister (global searchable view across all Studios)

Install

  1. Download stage-0.1.0.zip from the assets below
  2. In Blender: Edit → Preferences → Get Extensions → Install from Disk… (top-right dropdown)
  3. Pick the zip; tick Stage to enable

The zip is pure Python — same file works on macOS, Linux and Windows.

Tested on

Blender 5.1.0 across macOS (arm64), Linux (x86_64), Windows. CI runs the full suite (178 tests) on every push.

Roadmap

What's not in 0.1.0 (tracked for future releases):

  • Animation queue support (multi-frame jobs — currently single-frame stills only)
  • Material variants per object slot (KeyShot Multi-Material)
  • Studio diff viewer
  • "Studio from Viewport" / "Studio per Selected Camera" ops
  • Render-stamp Studio name burn-in
  • Open Output Folder button per Studio row
  • Skip-if-output-exists / overwrite preflight
  • Import/export Studios as JSON, cross-file Studio Presets

Open an issue at https://github.com/BlueLazyFish/Stage-Render/issues if any of the above lands high on your list — it influences priority.

License

GPL-3.0-or-later (mandatory for any addon importing bpy). Full text in LICENSE.

Acknowledgements

Design borrows from KeyShot (the Studio model), Renderset (right-click property storage, output templating), Blender Queue (persistent queue concept) and B-Renderon (background subprocess pattern). Stage isn't a fork of any — independent codebase — but the prior art shaped the choices.