Skip to content

Ghostwriter v7.0.0

Choose a tag to compare

@chrismaddalena chrismaddalena released this 03 Jun 22:24
· 518 commits to master since this release
918e381

Summary

This release marks a significant turn in automation. It hardens authentication by replacing user-managed JWT API tokens with opaque gwat_ credentials, adding scoped gwst_ service tokens for non-human integrations, tightening JWT/session validation, and moving service-token GraphQL access to a scoped service role. Existing user-managed JWT API tokens should be re-rolled by rotating them to receive a new opaque API token; changing an API token’s expiry now also generates a replacement token and immediately invalidates the old credential, so dependent automation must be updated with the newly shown token. Admin-created user-bound API tokens should be replaced with either user-created API tokens or scoped service tokens, depending on whether the credential should act as a human user or a non-human service.

Read more here: https://www.ghostwriter.wiki/features/access-authentication-and-session-controls/user-profile-and-tokens

CHANGELOG

[7.0.0] - 3 June 2026

Breaking Changes

  • User-managed API tokens are now opaque gwat_ credentials instead of JWTs
    • Existing user-managed JWT API tokens must be rotated to receive an opaque API token
    • API token expiry edits rotate the token prefix, secret hash, and UUID identifier, which immediately invalidates the previous credential
  • Django admin can no longer create user-bound API tokens
    • Use service principals and service tokens for non-human integrations
    • Admin-created user-bound API tokens should be replaced with user-created API tokens or scoped service tokens, depending on whether the credential should act as a user or as a non-human service
  • Login and collaborative editor JWTs now use explicit JWT typing and are accepted only by their intended authentication paths
    • Collaborative editor JWTs authenticate to Hasura only as a restricted collab role for the editor's required read-only queries
    • Login JWTs require a tracked, unrevoked user session bound by the jti claim
  • Service-token GraphQL access now uses the new service role and scoped service-token permissions instead of inheriting a creating user's permissions

Added

  • Scoped Service Tokens: Added service principals and service tokens for non-human automation credentials (Closes #881)
    • Service principals represent durable integrations or automation services
    • Service tokens are opaque gwst_ credentials with hashed secrets, expiration, revocation, and last-used tracking
    • Service token permissions are assigned to the token instead of inheriting the creating user's permissions
    • Added operation log read/write tokens scoped to one operation log and its entries
    • Added project read-only tokens scoped to selected projects or all projects the creator can access now and later
  • Service Token GraphQL Access: Added a Hasura service role for scoped service-token access
    • The shared service role exposes a combined service-token schema; each token's grants still determine which protected rows and Actions it can use
    • Project read access is backed by database views that validate the service token, service principal, creator status, and current project access
    • Service tokens can read project-related data, project-linked operation logs, evidence, reports, findings, observations, and public libraries
    • Service tokens can call selected read-oriented GraphQL Actions when their token grants allow the target resource, including report generation, evidence and recording downloads, tag lookups, and extra field specs
  • Added service-token management to the Django admin
  • Added documentation for API tokens, service tokens, and service-principal concepts
  • Added user-session tracking for login JWTs so administrators can revoke active GraphQL sessions
  • Added a management command to clean up expired Django sessions and tracked GraphQL login sessions

Changed

  • Reworked the user profile page to organize API tokens and service tokens into clearer cards
    • API tokens are described as user-bound automation credentials
    • Service tokens are described as scoped non-human credentials
    • Expired tokens can be hidden, and that preference is remembered in local storage
    • Token expiry dates now use warning styling when expiring within seven days and expired styling after expiration
    • API tokens now show last-used timestamps alongside service tokens
    • API tokens now have lazy-loaded details modals showing the token user's current project access
  • Added profile controls for editing API token and service token expiry dates
    • API token expiry edits now generate a replacement opaque token so the previous credential stops working immediately
  • Added service-token detail modals that show service principal, project read access, direct operation-log access, stale project grants, and token access summaries
  • Improved dark-mode styling for disabled fields
  • Made the sidebar toggle tab sticky while scrolling
  • Added the DJANGO_MFA_PASSKEY_LOGIN_ENABLED environment variable for controlling passkey login support
  • API tokens are now opaque gwat_ credentials with hashed secrets instead of user-managed JWTs
    • Editing an API token expiry rotates the token prefix, secret hash, and UUID identifier
  • Login and collaborative editor JWTs now use explicit JWT typing
    • Login JWTs bind their jti claim to a tracked user-session identifier
    • Collaborative editor JWTs use a dedicated token type and restricted Hasura role

Fixed

  • Fixed observation library create/edit/delete permissions not being checked for the user role in the GraphQL API
  • Fixed token tables showing as empty when Hide Expired hides every API token or service token
  • Fixed hyperlinks not working properly in open Office alternatives like LibreOffice (Fixes #890; Thanks to @wexew-ware)

Security

  • Updated Django from 4.2.16 to 4.2.30 to address CVE-2026-3902 in ASGIRequest (Fixes #896)
  • Added service-token authorization helpers for Django-backed Hasura Actions so service tokens are denied by default unless an action explicitly opts in
  • Login JWT validation now checks the tracked user session after verifying the JWT signature and expiration so sessions can be revoked on demand
  • Collaborative editor JWTs are restricted to a dedicated Hasura role and accepted by the collaborative editor permission-check endpoint
  • API token validation now verifies the opaque token secret against a stored hash and rejects revoked, expired, or inactive-user tokens
  • API token expiry edits now invalidate the previous credential and show the replacement token once
  • Service-token validation now uses explicit secret-checking terminology internally and keeps full lifecycle validation on the manager path
  • Added Hasura metadata validation tests to catch service-role permission drift, legacy service-token headers, and unexpected service mutations
  • Added validation for service-token permission resource, action, and constraint combinations