Skip to content

Security hardening - #945

Merged
chrismaddalena merged 11 commits into
masterfrom
hotfix/security-hardening
Jul 22, 2026
Merged

Security hardening#945
chrismaddalena merged 11 commits into
masterfrom
hotfix/security-hardening

Conversation

@chrismaddalena

Copy link
Copy Markdown
Collaborator

This is a security hardening pass to add more defense in depth for user-supplied values.

CHANGELOG

[Unreleased]

Security

  • Hardened user-controlled values rendered in JavaScript contexts to prevent stored cross-site scripting
    • Autocomplete data is now serialized as inert JSON instead of being interpolated into JavaScript source
    • Tag autocomplete suggestions are scoped to objects the current user can access
    • Additional inline JavaScript values and activity-log rich-text previews are escaped or sanitized for their output context
  • Added matching Django and Hasura validation for domain and static server names while preserving user access to create and manage shared inventory

Copilot AI review requested due to automatic review settings July 22, 2026 18:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 (via json_script) and JSON.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.

Comment thread ghostwriter/templates/base_generic.html Outdated
Comment thread ghostwriter/commandcenter/templates/user_extra_fields/field.html Outdated
@augmentcode

augmentcode Bot commented Jul 22, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR performs a defense-in-depth security hardening pass focused on safely handling user-controlled values in JavaScript contexts.

Changes:

  • Reworked multiple autocomplete implementations to embed server-provided data via json_script (inert application/json) and consume it with JSON.parse, instead of interpolating strings into JS source.
  • Scoped tag autocomplete suggestions to tags attached to objects in the current (accessible) queryset for findings, observations, reports, templates, clients, projects, domains, and servers.
  • Escaped additional user-controlled values used in inline JavaScript (e.g., filenames passed into JS functions; form/toast error strings; timezone/locale strings; project calendar titles).
  • Hardened activity log rich-text previews by sanitizing (when available) and ensuring output is escaped/truncated before display.
  • Added shared Django validators for inventory identifiers (domain and static server names) and applied them at the model layer with a migration.
  • Added corresponding Hasura metadata regex checks for insert/update permissions, plus tests to validate the metadata contracts.
  • Added targeted regression tests covering XSS edge-cases (e.g., </script> payloads) and tag scoping behavior.

Technical Notes: The approach relies on context-appropriate escaping (notably escapejs and json_script) and aligns Django-side validation with Hasura permission checks for inventory name fields.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. No suggestions at this time.

Comment augment review to trigger a new review at any time.

Copilot AI review requested due to automatic review settings July 22, 2026 18:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 47 out of 47 changed files in this pull request and generated no new comments.

@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.52381% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 93.97%. Comparing base (8582609) to head (75a1b3c).

Files with missing lines Patch % Lines
ghostwriter/commandcenter/models.py 88.88% 1 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@chrismaddalena
chrismaddalena merged commit 941325e into master Jul 22, 2026
12 checks passed
@chrismaddalena
chrismaddalena deleted the hotfix/security-hardening branch July 22, 2026 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants