Feature Description
Modify Ghostwriter’s Django-Q scheduled task administration flow to support an allowlist of approved scheduled task callables.
Django-Q scheduled tasks currently allow an administrator to specify a dotted Python function path, arguments, and an optional hook. Django-Q then imports and executes that callable through the worker process.
This behavior is part of Django-Q’s intended design and is useful for Ghostwriter because it allows trusted administrators to schedule documented Ghostwriter background tasks and deployment-specific maintenance tasks. However, because the callable path is administrator-controlled, the feature can also be misused if a Django superuser account is compromised or if a malicious insider has superuser access.
This issue proposes adding a defense-in-depth control that limits scheduled task execution to known-good callables.
Are you intending to implement this feature?
Open for discussion.
Current Behavior
Ghostwriter exposes Django-Q scheduled tasks through the Django admin interface.
A Django superuser can create or modify a scheduled task by specifying:
- A function path
- Arguments
- Keyword arguments
- An optional hook
- Schedule timing and repeat behavior
Django-Q accepts the configured function path and executes it on schedule using the Django-Q worker.
This gives Django superusers a powerful administrative capability. In Ghostwriter’s current trust model, Django superusers are treated as fully trusted application administrators with complete access to Ghostwriter.
Desired Behavior
Ghostwriter should optionally restrict Django-Q scheduled tasks to an allowlist of approved callable paths.
For example, Ghostwriter could allow documented background task functions while rejecting arbitrary importable Python callables that are not intended to be used as scheduled tasks.
A rejected task should fail validation before it is saved or executed.
Example desired behavior:
- Allowed: documented Ghostwriter background task functions
- Allowed: explicitly configured deployment-specific maintenance functions
- Rejected: arbitrary Python callables outside the allowlist
This would not remove the need to trust Django superusers, but it would add a guardrail against accidental misuse, compromised administrator sessions, and malicious administrators who do not also control the deployment environment.
Use Case
A community member raised a concern that the existing Django-Q scheduled task feature could be misused by a compromised Django superuser account or a malicious insider.
An allowlist would reduce that risk by ensuring that only known-good scheduled task functions can be launched through the Django admin interface.
For example, if the allowlist only contained Ghostwriter’s documented scheduled task functions, an administrator attempting to configure an unrelated Python callable would receive a validation error and the task would not be saved or executed.
This would be especially useful in deployments where:
- Django superusers manage Ghostwriter application data but do not have host-level access
- Organizations want stronger separation between application administration and runtime code execution
- Operators want to reduce the blast radius of a compromised Django superuser account
- Teams want scheduled tasks to be limited to documented and reviewed maintenance actions
Implementation Suggestions
Django-Q does not appear to provide a built-in allowlist mechanism for scheduled task callables, so Ghostwriter would likely need to implement this as an application-level control.
Potential approaches:
Settings-based allowlist
Add a Ghostwriter setting for allowed scheduled task callables.
Example:
GHOSTWRITER_DJANGO_Q_ALLOWED_SCHEDULE_FUNCS = [
"ghostwriter.reporting.tasks.example_task",
"ghostwriter.shepherd.tasks.example_task",
]
Additional Information
Part of this issue is placing the trust boundary. In Ghostwriter, we treat the administrator (a Django user with the superuser tag) as the most trusted and privileged entity in the application. Placing guardrails isn't a bad idea, but the guradrails will likely be within the admin's influence. We'd have to take more drastic action to eliminate this capability.
For example, with the allowlist concept, an admin with access to the host server could add unwanted commands to this allowlist. Admins without access to the host server would be bound to the allowlist.
Feature Description
Modify Ghostwriter’s Django-Q scheduled task administration flow to support an allowlist of approved scheduled task callables.
Django-Q scheduled tasks currently allow an administrator to specify a dotted Python function path, arguments, and an optional hook. Django-Q then imports and executes that callable through the worker process.
This behavior is part of Django-Q’s intended design and is useful for Ghostwriter because it allows trusted administrators to schedule documented Ghostwriter background tasks and deployment-specific maintenance tasks. However, because the callable path is administrator-controlled, the feature can also be misused if a Django superuser account is compromised or if a malicious insider has superuser access.
This issue proposes adding a defense-in-depth control that limits scheduled task execution to known-good callables.
Are you intending to implement this feature?
Open for discussion.
Current Behavior
Ghostwriter exposes Django-Q scheduled tasks through the Django admin interface.
A Django superuser can create or modify a scheduled task by specifying:
Django-Q accepts the configured function path and executes it on schedule using the Django-Q worker.
This gives Django superusers a powerful administrative capability. In Ghostwriter’s current trust model, Django superusers are treated as fully trusted application administrators with complete access to Ghostwriter.
Desired Behavior
Ghostwriter should optionally restrict Django-Q scheduled tasks to an allowlist of approved callable paths.
For example, Ghostwriter could allow documented background task functions while rejecting arbitrary importable Python callables that are not intended to be used as scheduled tasks.
A rejected task should fail validation before it is saved or executed.
Example desired behavior:
This would not remove the need to trust Django superusers, but it would add a guardrail against accidental misuse, compromised administrator sessions, and malicious administrators who do not also control the deployment environment.
Use Case
A community member raised a concern that the existing Django-Q scheduled task feature could be misused by a compromised Django superuser account or a malicious insider.
An allowlist would reduce that risk by ensuring that only known-good scheduled task functions can be launched through the Django admin interface.
For example, if the allowlist only contained Ghostwriter’s documented scheduled task functions, an administrator attempting to configure an unrelated Python callable would receive a validation error and the task would not be saved or executed.
This would be especially useful in deployments where:
Implementation Suggestions
Django-Q does not appear to provide a built-in allowlist mechanism for scheduled task callables, so Ghostwriter would likely need to implement this as an application-level control.
Potential approaches:
Settings-based allowlist
Add a Ghostwriter setting for allowed scheduled task callables.
Example:
Additional Information
Part of this issue is placing the trust boundary. In Ghostwriter, we treat the administrator (a Django user with the superuser tag) as the most trusted and privileged entity in the application. Placing guardrails isn't a bad idea, but the guradrails will likely be within the admin's influence. We'd have to take more drastic action to eliminate this capability.
For example, with the allowlist concept, an admin with access to the host server could add unwanted commands to this allowlist. Admins without access to the host server would be bound to the allowlist.