Skip to content

fix: harden Zscaler containment and API handling - #46

Open
phantom-jacob wants to merge 11 commits into
mainfrom
jacobd-codex-espm-5228-zscaler-nz-wave
Open

fix: harden Zscaler containment and API handling#46
phantom-jacob wants to merge 11 commits into
mainfrom
jacobd-codex-espm-5228-zscaler-nz-wave

Conversation

@phantom-jacob

Copy link
Copy Markdown
Contributor

Written by Codex.

Bug Fixes

  • Make denylist behavior reflect ZIA allowlist precedence and normalize internationalized hostnames before list operations.
  • Narrow user-group lost-update races, encode department query parameters, validate authentication and JSON response shapes, preserve rate-limit failures, and restore finite request timeouts.
  • Use ZIA category delta operations and asset-local ownership records so shared list updates preserve concurrent and foreign entries.

This is the refreshed N-Z remediation wave under PAPP-38310 and ESPM-5228. PAPP-38310 was reconciled and expanded because PRs #41 and #44 are merged historical work and do not cover these later findings. PSAAS-33953 remains excluded as platform work, and PSAAS-34406 remains excluded for human review; this PR does not change Jira labels.

Finding provenance

PSAAS VULN FS Fix
PSAAS-32519 VULN-95242 FS-4082 Honor allowlist precedence for block and lookup actions.
PSAAS-33768 VULN-100507 FS-6813 Fetch the user immediately before the required full-object group update and compare memberships by group ID.
PSAAS-33816 VULN-100556 FS-6861 Convert internationalized hostname labels using IDNA2008 and UTS-46.
PSAAS-33898 VULN-100638 FS-6943 Replace stale full-category writes with documented delta operations.
PSAAS-33954 VULN-100696 FS-6999 Encode department search and pagination through Requests parameters.
PSAAS-34202 VULN-101726 FS-7710 Return a controlled error when authentication omits the session cookie.
PSAAS-34297 VULN-101821 FS-7805 Restrict shared-list removals to entries recorded by the current asset.
PSAAS-34786 VULN-102310 FS-8293 Restrict shared-list removals to entries recorded by the current asset.
PSAAS-34869 VULN-102393 FS-8376 Reject unexpected scalar JSON and malformed rate-limit bodies safely.
PSAAS-35035 VULN-103656 FS-8589 Preserve the original failure for unparseable Retry-After values.
PSAAS-35091 VULN-103712 FS-8645 Preserve concurrent category entries and keyword configuration with delta writes.
PSAAS-35134 VULN-104261 FS-9011 Restore the connector's bounded request timeout.

Sources and implementation decisions

The cached patches were treated as recommendations. The category fix uses the vendor's delta API instead of replaying a fetched category, and the shared-list fix uses an asset-local ownership ledger rather than a caller-controlled force parameter. Entries created before this version cannot be inferred as owned and are intentionally protected from removal.

Checks

  • pre-commit autoupdate
  • Docker-backed pre-commit baseline; every hook passed except the release-note hook while the unreleased file was intentionally empty, then the tooling refresh was committed separately.
  • pre-commit run --all-files after all functional commits: passed, including app lint, compile/static checks, Semgrep, secrets, packaging, NOTICE, and release-note validation.
  • In-memory focused smoke checks for IDNA conversion, category delta payloads, ownership filtering, allowlist precedence, department parameters, scalar JSON rejection, and malformed rate-limit handling: passed.
  • Direct Python compilation of zscaler_connector.py and zscaler_consts.py: passed.
  • Integration tests are deferred because connector asset labs are not a reliable acceptance gate for this repository.

Breaking changes: none. No action parameters, outputs, asset configuration, defaults, or actions were removed or made required.

Merge strategy: merge commit only; do not squash

Manual Documentation

Have you made any changes that should be documented in manual_readme_content.md?

The following changes require documentation in manual_readme_content.md:

  • New, updated, or removed REST handlers
  • New, updated, or removed authentication methods, especially complex methods like OAuth
  • Compatibility considerations with respect to deployment types (e.g. actions that cannot be run on cloud or an automation broker)
  • I have verified that no manual documentation change is required.

Other information

  • PAPP: PAPP-38310
  • Epic: ESPM-5228
  • Color: Certified Apps

Please refer to our Contribution Guide for any questions on submitting a pull request.

Thanks for contributing!

Update Ruff, djLint, and dev-cicd-tools to the current configured versions.

The Docker-backed baseline passed every hook except the release-notes hook, which rejects the intentionally empty unreleased file before functional work is added. Tracks PAPP-38310.

Written by Codex.
Refuse denylist additions that the ZIA allowlist would override and report lookup entries as blocked only when they are effectively denied.

Tracks PSAAS-32519 (VULN-95242, FS-4082). Source: https://help.zscaler.com/zia/adding-urls-denylist

Written by Codex.
Fetch the user after the group lookup and compare embedded memberships by ID before sending the full user update required by the ZIA API.

Tracks PSAAS-33768 (VULN-100507, FS-6813). Source: https://help.zscaler.com/zia/user-management

Written by Codex.
Convert non-ASCII hostname labels with IDNA2008 and UTS-46 before block, unblock, allow, unallow, and lookup requests reach ZIA.

Tracks PSAAS-33816 (VULN-100556, FS-6861). Sources: https://help.zscaler.com/legacy-apis/configuring-url-categories-using-api and https://github.com/kjd/idna

Written by Codex.
Send only requested URL and IP list deltas while retaining the custom-category identity, super-category, and keyword fields required by the ZIA API.

Tracks PSAAS-33898 and PSAAS-35091 (VULN-100638, VULN-103712; FS-6943, FS-8645). Source: https://help.zscaler.com/legacy-apis/configuring-url-categories-using-api

Written by Codex.
Pass search and pagination values through the Requests query-parameter API so reserved characters cannot alter the authenticated departments request.

Tracks PSAAS-33954 (VULN-100696, FS-6999). Source: https://requests.readthedocs.io/en/latest/user/quickstart/

Written by Codex.
Handle a successful authentication response without Set-Cookie as a controlled action error instead of indexing the optional header and raising.

Tracks PSAAS-34202 (VULN-101726, FS-7710). Source: https://requests.readthedocs.io/en/latest/user/quickstart/

Written by Codex.
Record entries added by the current connector asset and refuse unblock or unallow requests that would remove only entries created by another tenant writer.

Tracks PSAAS-34297 and PSAAS-34786 (VULN-101821, VULN-102310; FS-7805, FS-8293). Source: https://help.zscaler.com/zia/security-policy-settings

Written by Codex.
Reject scalar success bodies before handlers consume them and handle missing or malformed Retry-After JSON without raising from the shared REST helper.

Tracks PSAAS-34869 (VULN-102393, FS-8376). Source: https://requests.readthedocs.io/en/latest/user/quickstart/

Written by Codex.
Return the original failed status whenever the ZIA Retry-After value cannot be parsed so arbitrary response text cannot become a truthy connector status.

Tracks PSAAS-35035 (VULN-103656, FS-8589). Source: https://help.zscaler.com/legacy-apis/understanding-rate-limiting

Written by Codex.
Let URL-category updates and user pagination inherit the shared 30-second timeout instead of explicitly disabling client-side recovery.

Tracks PSAAS-35134 (VULN-104261, FS-9011). Source: https://requests.readthedocs.io/en/latest/user/quickstart/#timeouts

Written by Codex.
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Merging this PR will release 3.0.5 with the following release notes:

3.0.5 (2026-08-04)

Connector release changes

  • Block and lookup actions now account for ZIA allowlist entries that override the advanced-threat denylist.
  • Group membership updates now fetch the user immediately before writing and compare existing memberships by group ID.
  • URL list actions now convert internationalized hostnames to IDNA2008 A-labels before sending them to ZIA.
  • URL category actions now use incremental list updates that preserve concurrent entries and existing keyword configuration.
  • The get departments action now encodes its search and pagination query parameters through the HTTP client.
  • Authentication now returns a controlled error when the ZIA response omits its required session cookie.
  • Unblock and unallow actions now remove only shared-list entries recorded as added by the current connector asset.
  • Unexpected scalar JSON and malformed rate-limit response bodies now return controlled action errors.
  • Unparseable Retry-After values now preserve the original rate-limit failure instead of being treated as success.
  • URL category updates and user listing now inherit the connector's finite request timeout.

@phantom-jacob
phantom-jacob marked this pull request as ready for review August 4, 2026 15:19
@phantom-jacob

Copy link
Copy Markdown
Contributor Author

Blocking upgrade path: installation_added_entries is new and starts empty. Existing URLs added by this same asset before upgrade are indistinguishable from foreign entries, and rerunning block or allow cannot seed the ledger because the existing-entry path returns before the ownership ledger update. The connector can therefore never unblock or unallow those pre-upgrade entries. Please add a safe migration or reconciliation path, or an explicit administrator-controlled claim or override. If this restriction remains, the functional commit should declare a breaking change because existing action capability is removed.

— Written by Codex.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant