elastic / elastic/integrations
[bug-hunter] zscaler_zia firewall appends server ports into source/destination.port
- Dominant language
- Handlebars
- Stars
- 333
- Forks
- 647
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 209
Description
## Impact
`zscaler_zia` firewall events can emit incorrect network tuples by mixing client and server ports into ECS `source.port` and `destination.port` simultaneously. This breaks assumptions for detections/correlations that expect `source.ip:source.port -> destination.ip:destination.port` to represent one flow endpoint pair.
## Reproduction Steps
1. Run this command from the repo root:
```bash
python /tmp/gh-aw/agent/repro_zia_firewall_ports.py
```
2. Observe the failure:
```text
Traceback (most recent call last):
File "/tmp/gh-aw/agent/repro_zia_firewall_ports.py", line 24, in
assert dest_port == expected_dest_port, (
AssertionError: BUG: destination.port should represent client destination flow with destination.ip (2a02:cf40::) and cdport (22), but got [22, 443].
```
## Expected vs Actual
**Expected:** For the sample where `destination.ip` is mapped from `cdip` and `source.ip` is mapped from `csip`, ECS ports should align to those same client-side endpoints (`destination.port=cdport`, `source.port=csport`).
**Actual:** Pipeline appends both client and server ports, producing arrays (for sample 2: `destination.port=[22,443]`, `source.port=[25,22]`).
## Failing Test
```python
#!/usr/bin/env python3
import json
from pathlib import Path
repo = Path("/home/runner/work/integrations/integrations")
log_path = repo / "packages/zscaler_zia/data_stream/firewall/_dev/test/pipeline/test-firewall.log"
expected_path = repo / "packages/zscaler_zia/data_stream/firewall/_dev/test/pipeline/test-firewall.log-expected.json"
# Use the second sample event (IPv6 + distinct server/client ports).
raw_event = json.loads(log_path.read_text().splitlines()[1])["event"]
expected_doc = json.loads(expected_path.read_text())["expected"][1]
dest_ip = expected_doc["destination"]["ip"]
src_ip = expected_doc["source"]["ip"]
dest_port = expected_doc["destination"]["port"]
src_port = expected_doc["source"]["port"]
assert dest_ip == raw_event["cdip"], f"sanity check failed: destination.ip={dest_ip} != cdip={raw_event['cdip']}"
assert src_ip == raw_event["csip"], f"sanity check failed: source.ip={src_ip} != csip={raw_event['csip']}"
expected_dest_port = int(raw_event["cdport"])
expected_src_port = int(raw_event["csport"])
assert dest_port == expected_dest_port, (
"BUG: destination.port should represent client destination flow with destination.ip "
f"({dest_ip}) and cdport ({expected_dest_port}), but got {dest_port}."
)
assert src_port == expected_src_port, (
"BUG: source.port should represent client source flow with source.ip "
f"({src_ip}) and csport ({expected_src_port}), but got {src_port}."
)
print("No bug reproduced.")
```
## Evidence
- Client endpoint mappings are written to ECS endpoint fields:
- `packages/zscaler_zia/data_stream/firewall/elasticsearch/ingest_pipeline/default.yml:205-208` (`destination.ip <- client.destination.ip`)
- `packages/zscaler_zia/data_stream/firewall/elasticsearch/ingest_pipeline/default.yml:259-263` (`source.ip <- client.source.ip`)
- Client ports are appended:
- `.../default.yml:232-237` (`destination.port` append from `client.destination.port`)
- `.../default.yml:286-291` (`source.port` append from `client.source.port`)
- Server ports are also appended into the same ECS fields:
- `.../default.yml:842-846` (`destination.port` append from `server.destination.port`)
- `.../default.yml:890-894` (`source.port` append from `server.source.port`)
- Current expected fixture captures the mixed-port output:
- `packages/zscaler_zia/data_stream/firewall/_dev/test/pipeline/test-firewall.log-expected.json:257-261` (`destination.port` is `[22, 443]`)
- `packages/zscaler_zia/data_stream/firewall/_dev/test/pipeline/test-firewall.log-expected.json:349-352` (`source.port` is `[25, 22]`)
> [!NOTE]
>
> 🔒 Integrity filter blocked 4 items
>
> The following items were blocked because they don't meet the GitHub integrity level.
>
> - [#3111](https://github.com/elastic/integrations/pull/3111) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#2459](https://github.com/elastic/integrations/pull/2459) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#7937](https://github.com/elastic/integrations/pull/7937) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
> - [#10252](https://github.com/elastic/integrations/pull/10252) `search_pull_requests`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
>
> To allow these resources, lower `min-integrity` in your GitHub frontmatter:
>
> ```yaml
> tools:
> github:
> min-integrity: approved # merged | approved | unapproved | none
> ```
>
>
---
[What is this?](https://ela.st/github-ai-tools) | [From workflow: Bug Hunter](https://github.com/elastic/integrations/actions/runs/27346375737)
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
> - [x] expires on Jun 18, 2026, 12:41 PM UTC
Contributor guide
Assessment
This issue has not been assessed yet.