elastic / elastic/integrations
ssi: Links panels forward dashboard-level filters, breaking navigation between dashboards
- Dominant language
- Handlebars
- Stars
- 333
- Forks
- 647
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 225
Description
## Summary
Several packages ship dashboards that use a Links panel for navigation and also carry app-state filters at the dashboard level (typically `data_stream.dataset`). The Links panel forwards the current dashboard's filters to the destination by default, and Kibana merges them with the destination dashboard's own saved filters. When two linked dashboards have different values for the same filter key, the result is a contradictory filter set and empty panels.
Concrete example from `axonius`: open **[Logs Axonius] Ticket**, then click **Network Assets** in the links panel. The Network dashboard loads with both `data_stream.dataset: axonius.ticket` and `data_stream.dataset: axonius.network` applied and shows no data. Each further click appends another dataset filter.
## Root cause
Every `dashboardLink` in the affected links panels is defined without an `options` block, for example:
```json
{
"destinationRefName": "link_aad8cdde-fe5e-494a-8623-6453d7752827_dashboard",
"id": "aad8cdde-fe5e-494a-8623-6453d7752827",
"label": "Adapter",
"order": 0,
"type": "dashboardLink"
}
```
Two Kibana behaviours then combine:
1. The links plugin defaults to forwarding filters. `DEFAULT_DASHBOARD_NAVIGATION_OPTIONS` is `{ open_in_new_tab: false, use_time_range: true, use_filters: true }` ([dashboard-navigation-options-common/index.ts](https://github.com/elastic/kibana/blob/main/src/platform/packages/private/dashboard/dashboard-navigation-options-common/index.ts)), and `dashboard_link_component.tsx` sets `params.filters = use_filters ? filters : filters.filter(isFilterPinned)` ([source](https://github.com/elastic/kibana/blob/main/src/platform/plugins/private/links/public/components/dashboard_link/dashboard_link_component.tsx)).
2. The dashboard locator merges rather than replaces: `state.filters = [...savedFiltersOfDestination, ...forwardedFilters]` unless `preserveSavedFilters === false`, which the links panel never sets ([locator.ts](https://github.com/elastic/kibana/blob/main/src/platform/plugins/shared/dashboard/common/locator/locator.ts)).
This is Kibana working as designed for drilldown-style links. The defect is in the package dashboards: they rely on dashboard-level filters for correctness while also forwarding them.
## Affected packages
Audit method: for each package with `owner.github: elastic/security-service-integrations`, find dashboards that (a) contain a `links` panel with at least one `dashboardLink` lacking `"useCurrentFilters": false`, and (b) have at least one `appState` filter in `kibanaSavedObjectMeta.searchSourceJSON`. Then check whether the forwarded filters conflict with the destination's saved filters or data.
| Package | Dashboards with links panel | Dashboard-level filters | Impact |
|---|---|---|---|
| `axonius` | 11 / 11 | `data_stream.dataset: axonius.` (different per dashboard), `labels.is_transform_source: false` | Every cross-dashboard navigation produces contradictory dataset filters and empty panels. Reported by a user. |
| `ti_abusech` | 5 / 5 | `threat.indicator.type` (url / file / software,x509-certificate / domain-name,ipv4-addr,ipv6-addr), plus `event.kind: enrichment` and `threat.indicator.file.hash.ssdeep: exists` on some | Navigating between URLs, Files, Software and X-509 Certificates, and Domains and IP Addresses produces contradictory `threat.indicator.type` filters. Files → any other dashboard also carries the `ssdeep exists` filter. |
| `jamf_pro` | 5 / 5 | Four inventory dashboards: `labels.is_transform_source: false`. Real time: `jamf_pro.events.webhook.id: exists` | Both directions break. Inventory → Real time carries `labels.is_transform_source: false`, which the `events` data stream does not set (the label is added by the `latest_inventory` transform only). Real time → inventory carries `webhook.id: exists`, which inventory documents do not have. |
| `m365_defender` | 7 / 7 | Only Vulnerability has `data_stream.dataset: m365_defender.vulnerability`; the other six have no dashboard-level filter | Vulnerability → any other dashboard carries the vulnerability dataset filter, so Alert, Incident, Email, Device and App & Identity render empty. The other six dashboards navigate correctly among themselves. |
| `jupiter_one` | 2 / 2 | Both: `data_stream.dataset: jupiter_one.risks_and_alerts`, `labels.is_transform_source: false`. Risks and Alerts adds `jupiter_one.asset.entity._class: Alert,Finding,Vulnerability` | Dataset filters are identical so no contradiction. Risks and Alerts → Overview narrows Overview to those three entity classes, which silently hides other asset classes. Lower severity. |
### Checked and not affected
These SSI packages have links panels that forward filters but have no dashboard-level app-state filters, so there is nothing to collide. They are consistent with the decision in [#15437](https://github.com/elastic/integrations/pull/15437#discussion_r2374328822) to keep forwarding user-applied filters, and need no change for this issue: `auditd_manager`, `dataminr_pulse`, `greenhouse`, `network_traffic`, `osquery`, `prisma_cloud`, `sentinel_one`, `system_audit`, `tychon`.
All other SSI packages with links panels already set `"useCurrentFilters": false`.
Audit run against the repository at `5a5a6816d4`; packages added or changed since may need re-checking.
## Proposed fix
Two options, both consistent with existing practice in the repo.
**Option A (minimal): stop forwarding app-state filters.** Add explicit options to every `dashboardLink` in the affected dashboards:
```json
"options": {
"openInNewTab": false,
"useCurrentDateRange": true,
"useCurrentFilters": false
}
```
With `useCurrentFilters: false` the panel still forwards pinned filters, so an analyst who wants a filter to follow them across dashboards can pin it. This is how [#14974](https://github.com/elastic/integrations/pull/14974) fixed the same problem across the obs-infraobs packages and how most SSI packages are already configured. `useCurrentDateRange` can be `true` or `false`; the existing packages are split and it does not affect this bug.
**Option B (structural): move correctness filters into the visualisations.** Keep forwarding filters, but put `data_stream.dataset` and similar constraints inside each Lens panel rather than at dashboard level, as argued in [#15437](https://github.com/elastic/integrations/pull/15437#discussion_r2377285142). This removes the collision and stops users accidentally removing the filter, but has two costs: options-list controls take their suggestions from the dashboard-level filters and would offer values from every dataset on the data view, and `search` embeddables (saved searches) and Discover pivots lose the constraint. It also needs many more panel edits.
Recommendation: apply Option A to the five affected packages now. Treat Option B as a repo-wide dashboard guideline discussion rather than a per-package fix.
## Related
- [#15437](https://github.com/elastic/integrations/pull/15437#discussion_r2374328822) — discussion of whether links panels should forward filters; concluded "keep the default" on the premise that dashboards do not carry dashboard-level correctness filters.
- [#15016](https://github.com/elastic/integrations/pull/15016) — earlier fix disabling filter forwarding on links.
- [#14974](https://github.com/elastic/integrations/pull/14974) — same fix applied across obs-infraobs packages.
- [#15075](https://github.com/elastic/integrations/issues/15075) — links panel migration tracking issue.
Contributor guide
Research direction
Start by auditing the dashboard JSON in the affected axonius, ti_abusech, jamf_pro, m365_defender, and jupiter_one packages for links panels and dashboard-level appState filters. Read dashboard-navigation-options-common/index.ts, dashboard_link_component.tsx, and locator.ts to understand the existing behavior, then compare the patterns from #14974 and #15016. Done means affected dashboard links explicitly disable current-filter forwarding while retaining the intended navigation behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- json
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100