Security hardening - #945
Conversation
There was a problem hiding this comment.
Pull request overview
Security hardening pass across Django templates, frontend JS, and Hasura metadata to reduce stored XSS risk from user-controlled values and to align inventory-name validation between Django and Hasura.
Changes:
- Replaced JavaScript-source interpolation with inert
<script type="application/json">blobs (viajson_script) andJSON.parse(...)for multiple autocomplete/data payloads. - Escaped user-controlled values rendered in JavaScript contexts (
escapejs) and tightened client-side escaping/sanitization for previews. - Added Django + Hasura regex validation for Domain and Static Server names, with matching tests.
Reviewed changes
Copilot reviewed 44 out of 44 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| hasura-docker/metadata/databases/default/tables/public_shepherd_staticserver.yaml | Adds Hasura insert/update regex checks for name. |
| hasura-docker/metadata/databases/default/tables/public_shepherd_domain.yaml | Adds Hasura insert/update regex checks for name. |
| ghostwriter/users/templates/users/profile_form.html | Escapes form errors embedded in inline JS. |
| ghostwriter/templates/mfa/webauthn/add_form.html | Escapes form errors embedded in inline JS. |
| ghostwriter/templates/mfa/totp/deactivate_form.html | Escapes form errors embedded in inline JS. |
| ghostwriter/templates/mfa/totp/activate_form.html | Escapes form errors embedded in inline JS. |
| ghostwriter/templates/mfa/reauthenticate.html | Escapes form errors embedded in inline JS; whitespace fix. |
| ghostwriter/templates/mfa/authenticate.html | Escapes form errors embedded in inline JS. |
| ghostwriter/templates/index.html | Escapes username embedded in JSON request body JS. |
| ghostwriter/templates/base_generic.html | Alters banner link rendering (note: current diff removes sanitization). |
| ghostwriter/templates/base_generic_empty.html | Escapes toast message text embedded in inline JS. |
| ghostwriter/templates/account/reauthenticate.html | Escapes form errors embedded in inline JS. |
| ghostwriter/templates/account/login.html | Escapes form errors embedded in inline JS. |
| ghostwriter/static/js/project.js | Expands HTML escaping to include additional characters (>, '). |
| ghostwriter/static/js/oplog.js | Sanitizes/escapes rich-text previews before display. |
| ghostwriter/shepherd/views.py | Scopes tag autocomplete data to the filtered queryset; provides JSON-friendly tag list. |
| ghostwriter/shepherd/validators.py | Introduces centralized regex validators for inventory identifiers. |
| ghostwriter/shepherd/tests/test_views.py | Adds tests asserting autocomplete JSON is inert and tag autocomplete is scoped. |
| ghostwriter/shepherd/tests/test_forms.py | Adds tests for rejecting invalid domain/server names via new validators. |
| ghostwriter/shepherd/templates/shepherd/server_list.html | Moves autocomplete/tag data into json_script and parses as JSON. |
| ghostwriter/shepherd/templates/shepherd/domain_list.html | Moves autocomplete/tag data into json_script and parses as JSON. |
| ghostwriter/shepherd/templates/shepherd/checkout.html | Escapes form errors embedded in inline JS. |
| ghostwriter/shepherd/models.py | Adds validators to Domain.name and StaticServer.name. |
| ghostwriter/shepherd/migrations/0053_alter_domain_name_alter_staticserver_name.py | Migrates model fields to include new validators. |
| ghostwriter/rolodex/views.py | Adds autocomplete_data payloads (names/clients/codenames/tags) alongside scoped tags. |
| ghostwriter/rolodex/tests/test_views.py | Extends tag-scoping tests and adds JS-escaping regression test for calendar titles. |
| ghostwriter/rolodex/templates/rolodex/project_list.html | Switches autocomplete inputs to use JSON-parsed autocomplete_data. |
| ghostwriter/rolodex/templates/rolodex/project_form.html | Escapes form errors embedded in inline JS. |
| ghostwriter/rolodex/templates/rolodex/project_detail.html | Escapes multiple JS-injected values and avoids unsafe HTML assignment for placeholder text. |
| ghostwriter/rolodex/templates/rolodex/client_list.html | Switches autocomplete inputs to use JSON-parsed autocomplete_data. |
| ghostwriter/rolodex/templates/rolodex/client_form.html | Escapes form errors embedded in inline JS. |
| ghostwriter/rolodex/templates/rolodex/client_detail.html | Escapes JS-injected locale/timezone values. |
| ghostwriter/reporting/views2/report.py | Adds scoped tag autocomplete payloads and JSON-safe autocomplete structures for report detail. |
| ghostwriter/reporting/views2/observations.py | Adds JSON-safe autocomplete payloads (titles/tags) and scoped tags. |
| ghostwriter/reporting/views2/finding.py | Adds JSON-safe autocomplete payloads (titles/tags) and scoped tags. |
| ghostwriter/reporting/tests/test_views.py | Adds tests for inert JSON rendering and multiple JS/HTML escaping paths. |
| ghostwriter/reporting/templates/reporting/report_templates_list.html | Escapes template filename in inline JS; switches tags autocomplete to json_script. |
| ghostwriter/reporting/templates/reporting/report_template_form.html | Escapes form errors embedded in inline JS. |
| ghostwriter/reporting/templates/reporting/report_list.html | Switches tags autocomplete to json_script payload. |
| ghostwriter/reporting/templates/reporting/report_detail.html | Escapes filenames and moves autocomplete payloads into json_script. |
| ghostwriter/reporting/templates/reporting/observation_list.html | Switches autocomplete inputs to use JSON-parsed autocomplete_data. |
| ghostwriter/reporting/templates/reporting/finding_list.html | Switches autocomplete inputs to use JSON-parsed autocomplete_data. |
| ghostwriter/commandcenter/templates/user_extra_fields/field.html | Reworks JSON extra field rendering to use inert JSON + JSON.parse(...) (note: current diff misuses json_script). |
| ghostwriter/api/tests/test_hasura_metadata.py | Adds regression test asserting Hasura metadata contains expected regex checks. |
🤖 Augment PR SummarySummary: This PR performs a defense-in-depth security hardening pass focused on safely handling user-controlled values in JavaScript contexts. Changes:
Technical Notes: The approach relies on context-appropriate escaping (notably 🤖 Was this summary useful? React with 👍 or 👎 |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #945 +/- ##
==========================================
+ Coverage 93.93% 93.97% +0.04%
==========================================
Files 431 433 +2
Lines 31992 32192 +200
==========================================
+ Hits 30052 30253 +201
+ Misses 1940 1939 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This is a security hardening pass to add more defense in depth for user-supplied values.
CHANGELOG
[Unreleased]
Security