- Executive Dashboard no longer auto-triggers POST /risk/compute or shows
the Refresh scores button for roles the backend rejects (viewer), which
was causing a 403 on load
- AuthContext now proactively renews the session cookie every 20 minutes
while the app is open, so an actively-used session doesn't rely solely
on the reactive on-401 refresh racing against its own token's expiry
Direct test removal is now gated to draft-only at the service layer
(active campaigns must go through a modification request that a
manager approves). The trash-icon button on the tests table still
showed for active campaigns and would always fail with a 400 —
restrict it to draft, matching the backend gate.
Adds the 4 backend-logged campaign actions missing from ACTION_LABELS
(delete_campaign, generate_campaign, schedule_campaign,
recurring_campaign_run), and wires campaign-timeline invalidation into
the remaining audit-logging mutations on the page (complete, schedule,
approve/reject modification request) so the timeline panel updates
live instead of only on next reload, consistent with submit/approve/
reject campaign.
Previously action/testId/justification only reset inside the success
handler, so cancelling and reopening the modal left stale form values.
Mirrors the reset-on-close pattern already used by AddTestToCampaignModal.
The backend endpoint no longer accepts a force query param (a draft
campaign can never have a future start_date to force past). No frontend
code currently calls this function, but keep it matching the real
backend contract in case a future admin UI wires it up.
- Single admin Jira account stored in system_configs (jira.admin_email, jira.admin_api_token)
- Admin Tempo token in system_configs (tempo.admin_token)
- get_admin_jira_client() + has_admin_jira_configured() replace per-user auth in all lifecycle hooks
- lookup_user_jira_account_id() auto-discovers each user's Atlassian accountId by email on login
- auto_log_test_worklog() now uses admin Tempo token and logs both red+blue team time
- Settings > Jira: admin credentials fields + test buttons moved to admin Jira tab
- Profile section simplified: jira_account_id shown read-only (auto-detected)
Tar Slip (CWE-22) — 3 import services:
threat_actor, lolbas, caldera: add path validation before extractall()
to prevent malicious zip members with ../ escaping the target directory.
(sigma, elastic, atomic already had this protection)
Path Traversal (CWE-23) — professional_reports.py:
Add _assert_safe_report_path() check on all 5 report endpoints to
verify the generated filepath stays within REPORT_OUTPUT_DIR.
Open Redirect (CWE-601) — sso.py:
Validate IdP redirect URL scheme (must be http/https) before
issuing RedirectResponse, blocking javascript: and data: redirects.
DOM XSS (CWE-79) — 4 frontend pages:
Create src/utils/url.ts with safeUrl() that rejects non-http/https
protocols; apply to actor.mitre_url, ref.url, intel.url.
Sanitize framework name to alphanumeric-only before DOM insertion.
Restrict evidence MIME types to an explicit safe allowlist (png/jpg/gif/webp).
Hardcoded credentials (CWE-798):
verify_gaps.py, create_wiki.py: replace literal passwords with
environment variable reads (AEGIS_ADMIN_PASSWORD, GITEA_PASSWORD).
npm ci installs exact versions from package-lock.json with no implicit
resolution, making builds fully reproducible and guaranteed to use the
audited safe dependency versions.
SystemPage now only shows operational content: MITRE Sync, Intel Scan,
ATT&CK Evaluations, Scheduled Jobs, and Template Management.
Settings gets two new admin-only tabs:
- "SSO / Azure AD": full SAML 2.0 wizard (5-step setup for Azure AD)
- "System": System Status + Version Info + Configuration Export/Import
- sso_service: fix process_callback for Azure AD claim URIs (email, role)
- Default role_attr to full Azure role claim URI
- Fallback email resolution via Azure email claim URI + NameID
- Username defaults to full email (prevents collision with local accounts)
- User lookup also tries email field for existing local accounts
- Logs warning when unknown role received from IdP
- frontend/api/sso.ts: new API module with getSsoStatus, getSsoConfig, updateSsoConfig
- LoginPage: redesigned for SSO-first flow
- Shows Azure SSO button as primary when SSO enabled+configured
- Local login collapsed under "Emergency admin access" section
- Falls back to normal local login form when SSO is disabled
- SystemPage: new SsoConfigSection component (guided 5-step wizard)
- Step 1: Copy SP Entity ID and ACS URL for IT team + metadata XML download
- Step 2: Azure App Roles reference table (6 roles with exact values)
- Step 3: Tenant ID field auto-fills idp_entity_id and idp_sso_url
- Step 4: X.509 certificate paste field
- Step 5: Attribute mapping pre-filled with Azure AD claim URIs
- Enable/disable toggle + save
- Capture Step.Description (HTML stripped), step name/number, substep ref,
criteria, and data sources from MITRE ATT&CK Evaluations API
- _aggregate_by_technique() now accumulates ALL occurrences per technique
(multiple substep refs, criteria, step contexts) instead of keeping only
the best-scoring one
- New helper functions _build_procedure_text(), _build_description(),
_build_red_summary() generate rich narratives from accumulated occurrences
- New re_enrich_evaluation_round() service function + POST endpoint
/system/attck-evaluations/re-enrich to update already-imported tests
without changing detection results or validation state
- Frontend: Re-enrich button per imported round + result banner in SystemPage
- Fallback names now use hyphens matching live API (carbanak-fin7, wizard-spider-sandworm)
- Add APT3 (R1) and Enterprise 2025/er7 (R7) to fallback - verified from live API
- Remove OilRig (R6) from fallback - CrowdStrike did not participate in Round 6
- Orange fallback banner only shows when NO rounds are available at all
- Soft gray note when rounds are loaded but API had transient error
- Check-new and import errors: detect 502/Cloudflare messages and show user-friendly text
instead of raw Cloudflare HTML error messages
- Add browser User-Agent and Referer headers to all evals.mitre.org requests
- fetch_rounds_with_status() returns api_reachable flag + rounds list
- Fallback to 5 known public CrowdStrike rounds (APT29/R2 through OilRig/R6)
when live API is blocked, so UI always shows something actionable
- Router returns {rounds, api_reachable, api_error} instead of plain array
- Frontend shows orange warning banner when using fallback data
- Remove 502 HTTPException - rounds are always returned (live or fallback)
Replaces the minimal bottom legend with a full coverage legend panel
placed above the filters. Each status shows a cell mock matching the
exact colors used in the matrix, a color-coded label, and a short
description of what it means. Includes review_required with its
orange alert-triangle badge. Removes the old minimal bottom legend.
New drag-and-drop section at the bottom of the Import RT page so operators
can convert screenshots to base64 without leaving the page. Includes
thumbnail preview, copy-base64 and copy-JSON-snippet buttons with
2s feedback, per-image delete and clear-all.
Each technique in the RT import JSON now requires at least one evidence
image (PNG/JPG/GIF/WebP/BMP, max 10 MB decoded) embedded as base64.
Backend:
- RTEvidenceEntry model: filename, data (base64), caption (optional)
- RTTechniqueEntry.evidence is now required
- Pre-validation raises 422 if any technique is missing evidence
- After test creation, images are decoded and stored in MinIO as
Evidence records (team=red) linked to the test
Frontend:
- RTEvidenceEntry type added to api/tests.ts
- parseJson() validates evidence presence and structure per technique
- Preview table shows base64 thumbnails (up to 3 + overflow count)
- Format reference updated: evidence fields moved to Required section
- Import result shows total evidence images attached
The previous name implied data from a dedicated threat intelligence team.
The feature actually monitors public RSS feeds and security blogs for
ATT&CK technique mentions, so Security Feed Monitor is more accurate.
Updated description and all references across SystemPage and ReviewQueuePage.
Overall Security Score renamed to Overall Programme Score. Descriptions across
Executive Dashboard and Dashboard page now clarify scores reflect Red/Blue Team
exercise maturity and coverage breadth, not the organisation real-world security
state, to avoid overstating what ATT&CK simulation tests can guarantee.
client.ts: when FastAPI detail is an object, extract .message for the error
string and preserve the full detail on enhancedError.detail so consumers
can inspect structured error payloads (e.g. 409 start_date_in_future).
CampaignDetailPage: use enhancedErr.status (not response.status) and
enhancedErr.detail (not response.data.detail) to detect 409 and show
the confirmation modal instead of the toast.