Support adding custom script modules when .py file uploads are blocked (API create and/or paste-in-UI) #125

Closed
opened 2026-04-05 16:21:58 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @mrmrcoleman on 3/18/2026

NetBox version

v4.5.4

Feature type

Change to existing functionality

Proposed functionality

Users in locked-down environments often cannot upload files with a .py extension (proxy/DLP/WAF blocks by filename or Content-Disposition) and may not be able to use a Git (or other) data source. Today the only workaround is uploading a different extension and renaming on the server, which is unsupported and fragile.

We propose supporting one of two proposed solutions so NetBox can accept script module content without sending a .py file in the request. Implementers can choose one or both.


Solution A: REST API – create script modules by JSON body

  • Add a script-modules resource under the Extras API (e.g. POST /api/extras/script-modules/).
  • Create is done with a JSON body (no file upload), so the request never carries a .py filename:
    • name (required): string, Python module name; server stores the file as {name}.py. Validate as a valid module name (e.g. ^[a-zA-Z_][a-zA-Z0-9_]*$).
    • content (required): string, full Python source of the script module.
  • Server creates the ScriptModule (and underlying ManagedFile) with file_root=scripts, writes content to the existing script storage as {name}.py, and relies on existing ScriptModule post_save to sync Script rows. Reuse the same storage/path logic as the current "Add script" file upload.
  • Optionally support list and retrieve for script-modules.
  • Permissions: same as adding a script module in the UI (e.g. create on ScriptModule). Overwrite: either create-only (409 if name exists) or upsert; document the chosen behavior.

Solution B: UI – paste script content on Add Script form

  • On the "Add script" form (Scripts → Add), add a third way to provide the module alongside "File upload" and "Data source":
    • New fieldset (e.g. "Paste content") with:
      • Module name (required): text input, valid Python module name → stored as {name}.py.
      • Script content (required): textarea for the full .py file contents.
    • Enforce mutual exclusivity: exactly one of (file upload | data source | paste content). Reuse the same create view and storage path as file upload; content is taken from the form instead of an uploaded file.
    • Optional: max length (e.g. 256 KB) and optional syntax check before save.

Implementation notes (apply to whichever solution is implemented)

  • Shared helper that, given name + content, writes to script storage and creates/updates the ScriptModule, so API and UI can share logic if both are implemented.
  • No new database models or fields; same ScriptModule/ManagedFile and script storage as today.
  • Document the chosen option(s) in the custom scripts documentation.

Use case

Users in locked-down environments cannot upload .py files (corporate proxy/DLP/WAF blocks by filename or extension) and cannot attach a Git (or other) data source. They need a supported way to add custom script modules. Sending script content in a JSON body (Solution A) or pasted in a textarea (Solution B) avoids sending a .py file and is typically allowed by the same security controls. Solution A suits automation and API-only users; Solution B suits users who prefer the UI.

Database changes

None. Both solutions use the existing ScriptModule (proxy over ManagedFile) and script storage; no new models or fields.

External dependencies

None. Uses existing Django storage, NetBox API, and UI patterns. No new Python packages or external services.

*Originally created by @mrmrcoleman on 3/18/2026* ### NetBox version v4.5.4 ### Feature type Change to existing functionality ### Proposed functionality Users in locked-down environments often cannot upload files with a `.py` extension (proxy/DLP/WAF blocks by filename or Content-Disposition) and may not be able to use a Git (or other) data source. Today the only workaround is uploading a different extension and renaming on the server, which is unsupported and fragile. We propose supporting **one of two proposed solutions** so NetBox can accept script module content without sending a `.py` file in the request. Implementers can choose one or both. --- ### Solution A: REST API – create script modules by JSON body - Add a **script-modules** resource under the Extras API (e.g. `POST /api/extras/script-modules/`). - **Create** is done with a JSON body (no file upload), so the request never carries a `.py` filename: - **`name`** (required): string, Python module name; server stores the file as `{name}.py`. Validate as a valid module name (e.g. `^[a-zA-Z_][a-zA-Z0-9_]*$`). - **`content`** (required): string, full Python source of the script module. - Server creates the `ScriptModule` (and underlying `ManagedFile`) with `file_root=scripts`, writes `content` to the existing script storage as `{name}.py`, and relies on existing `ScriptModule` post_save to sync `Script` rows. Reuse the same storage/path logic as the current "Add script" file upload. - Optionally support **list** and **retrieve** for script-modules. - Permissions: same as adding a script module in the UI (e.g. create on ScriptModule). Overwrite: either create-only (409 if name exists) or upsert; document the chosen behavior. ### Solution B: UI – paste script content on Add Script form - On the "Add script" form (Scripts → Add), add a third way to provide the module alongside "File upload" and "Data source": - New fieldset (e.g. "Paste content") with: - **Module name** (required): text input, valid Python module name → stored as `{name}.py`. - **Script content** (required): textarea for the full `.py` file contents. - Enforce mutual exclusivity: exactly one of (file upload | data source | paste content). Reuse the same create view and storage path as file upload; content is taken from the form instead of an uploaded file. - Optional: max length (e.g. 256 KB) and optional syntax check before save. --- **Implementation notes (apply to whichever solution is implemented)** - Shared helper that, given `name` + `content`, writes to script storage and creates/updates the `ScriptModule`, so API and UI can share logic if both are implemented. - No new database models or fields; same `ScriptModule`/ManagedFile and script storage as today. - Document the chosen option(s) in the custom scripts documentation. ### Use case Users in locked-down environments cannot upload `.py` files (corporate proxy/DLP/WAF blocks by filename or extension) and cannot attach a Git (or other) data source. They need a supported way to add custom script modules. Sending script content in a JSON body (Solution A) or pasted in a textarea (Solution B) avoids sending a `.py` file and is typically allowed by the same security controls. Solution A suits automation and API-only users; Solution B suits users who prefer the UI. ### Database changes None. Both solutions use the existing `ScriptModule` (proxy over `ManagedFile`) and script storage; no new models or fields. ### External dependencies None. Uses existing Django storage, NetBox API, and UI patterns. No new Python packages or external services.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#125