Sync/upstream 2026 07#11
Merged
Merged
Conversation
Che4ter
commented
Jul 7, 2026
Collaborator
- Sync the latest upstream changes
[FIX] Fixed order of authentication methods for timeline filter endpoint.
…interactive editors
… with user case-access gating
…se-access, customers, audit, MFA reset and API-key rotation
…solutions, analysis statuses, event categories and task statuses
…e PUT and POST backup, deprecating the legacy /manage/settings routes
… credentials from user schemas and marking sensitive fields load-only Backport of f1d41f4 from v2.4.29. UserSchema, UserFullSchema, and BasicUserSchema were leaking mfa_secrets and webauthn_credentials in serialized responses, letting an attacker bypass MFA or impersonate the user (CWE-201, SBA-ADV-20260126-04). user_password is now load-only on UserSchema, and DSFileSchema.file_local_name (server-side path) is declared load-only at the schema layer instead of being del'd in the route handler. The matching v2 schema (UserSchemaForAPIV2) already had these guards; this commit aligns the legacy schemas still in use.
…er, profile and taxonomy admin endpoints Backport of f84b7b9 from v2.4.29, extended to cover the v2 surface that didn't exist when the original fix shipped. The legacy /manage/users, /manage/asset-type, /manage/ioc-types, /profile/update endpoints accepted the raw request body and handed it straight to the marshmallow schema. The schemas' `unknown = EXCLUDE` drops unknown keys but every declared field on the schema is still accepted — so a caller could overwrite the primary key (mass-assignment of asset_id / type_id), self-promote to admin via user_isadmin on the profile endpoint, or set arbitrary attributes the GUI never exposes (SBA-ADV-20260128-01 / CWE-915). Each writable endpoint now goes through an explicit per-resource allowlist before the schema is loaded. The taxonomy CRUD on rest/v2/manage_routes/case_objects.py declares the allowlist on the shared TaxonomyConfig so the asset-type, ioc-type, classification, state and evidence-type sub-blueprints all inherit the protection without duplication. GHSA-g588 already made user_password load_only on UserSchema, so the legacy /manage/users/add no longer needs the `del udata['user_password']` guard either; remove it.
… allowlist Backport of 371c640 from v2.4.29, adapted to develop's _is_safe_url in business/auth.py. The previous check only verified that urlparse(target).scheme and urlparse(target).netloc were empty. urlparse treats `attacker.com?cid=1` as a path with an empty netloc, so the guard accepted attacker-controlled hosts; browsers resolving the resulting `Location: attacker.com` header route the user to the attacker's origin (CWE-601 / SBA-ADV-20260126-02). _is_safe_url now requires the target to be a non-empty string starting with a single `/` (rejecting both protocol-relative `//evil.com` and backslash variants like `/\\evil.com`) and free of control characters, with the urlparse check kept as defense in depth.
…TASTORE_PATH and allowlisting writable upload fields Backport of 57c1b80 from v2.4.29, extended to the v2 datastore route that didn't exist when the original fix shipped. datastore_delete_file and datastore_get_local_file_path now resolve the recorded file_local_name and refuse to operate on a path outside the configured DATASTORE_PATH. Even though the dsf row is legitimately fetched through (file_id, case_id), a stored path pointing elsewhere (stale row from a different mount, attacker-seeded value) would let an unlink or send_file escape the datastore — CWE-22. The legacy /datastore/file/add + /datastore/file/update routes and the v2 add_file + update_file methods now project the multipart form down to an allowlist before the schema is loaded, blocking mass-assignment of file_id, file_local_name, file_case_id, file_sha256, file_size, added_by_user_id, file_date_added and friends.
…requiring POST on logout Backport of b202f54 from v2.4.29, extended to cover the v2 alerts update endpoint that didn't exist when the original fix shipped. Alert update (legacy single + batch, and v2 PUT /alerts/<id>) now strips alert_id, alert_customer_id and alert_creation_time from the payload before the schema is loaded. Allowing those via the API let a user with write access to one customer re-attribute an alert to a customer they cannot see — silently hiding it from the rightful owner and planting it under another tenant's view (CWE-863 / SBA-ADV-20260128-05). The logout endpoint moves from GET to POST. A plain <img src="/logout"> on a third-party page would otherwise log the user out without consent (RFC 7231 §4.2.1: GET must be safe; CWE-650 / SBA-ADV-20260128-03). The sidenav link wraps a hidden form so existing accessibility / styling keeps working.
…-log endpoint; server-side search on /chat
…/unarchive endpoints, open-first sort
…rences/<key> endpoints
…k + single-use session flag
…IRIS_HOSTNAME single-source-of-truth, certbot deploy-hook
…lteKit UI service
…service + hook listeners + /api/v2/notifications endpoints + /notifications SocketIO namespace + /users/mentionable directory for analyst mention search
…nt/both target, deploy-to-existing) + incident-rules with nested AND/OR conditions, back-fill, JSONB path support (alert_context.foo.bar)
…igation-flows (getters/list/create/update/deploy/backfill), server-owned rule_created_by/flow_created_by attribution, public proxies for cross-module access-control helpers
…ident-statuses endpoint, escalate crash fix
…and detect stopped iriswebapp_db container
… add war_room_id scoping and /_diag notifications endpoint
…r and multi-GB datastore uploads aren't truncated
…_room relationship that broke gunicorn boot (WarRoom unresolvable at mapper-config time)
…expose source-incident on cases
…om case, business helpers
…c gap - Add merge migration for the second alembic head introduced by the upstream sync (war_room_id_to_user_activity vs our prior merge point). - Import WarRoom explicitly in models.py so it's registered in the declarative registry before UserActivity.war_room is mapper-configured (was crashing gunicorn boot with an unresolvable relationship). - Add worker-src 'self' blob: to the CSP header so Ace editor's syntax-highlighting web worker (blob: URL) isn't blocked.
…26-07 # Conflicts: # source/requirements.txt
user_activity.war_room_id had no ON DELETE behavior, so Postgres blocked deleting any war room with logged activity against it — which is every real war room, since creating one is itself logged. The existing war_room_delete() code already assumed the FK would go NULL (see its comment), it just wasn't configured that way at the DB level.
The auto-merge kept both our and upstream's copies of two blocks that should have collapsed into one: the MFA brute-force lockout helpers in login_routes.py (plus a duplicate `import time`), and the alert-update readonly-fields guard in alerts_routes.py. Functionally harmless since Python just re-defines the same names, but confusing and worth cleaning up. Kept the better-commented (upstream) copy in each case; verified py_compile and a container boot after each removal.
… port 443 Running as www-data (re-added in bc6f071 for hardening) blocks binding to privileged ports without this capability, causing the container to exit immediately whenever INTERFACE_HTTPS_PORT is left at its default 443 (as in .env.tests.model) instead of a dev override like 8443. This broke the Test API, Database migration tests, and End to end tests CI jobs, which all depend on the nginx container starting successfully. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- business/auth.py: remove duplicate `import time` left by the 3-way merge (same pattern already fixed in login_routes.py/alerts_routes.py) - access_control/utils.py, alembic/versions/e5d79b8c4a55_...py: drop stray extra blank lines left where overlapping merge hunks joined Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cleans up ruff UP032 findings in our own docx report generation code (not present upstream). Report generation tests still pass.
/collab/ used a static proxy_pass to "collab", resolved at nginx startup. CI's docker-compose.dev.yml (upstream's own file) has no collab service, so nginx refused to start at all: nginx: [emerg] host not found in upstream "collab" Switch to a variable + Docker's embedded resolver so DNS is resolved per-request instead. nginx now starts fine without collab present; only requests to /collab/ fail if it's genuinely absent, which is correct since it's an optional BV-only feature. Verified locally: nginx stays up with collab stopped, and successfully proxies through to it once collab is running again.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.