Skip to content

fix(calling): neutralize SCIM filter injection and restrict Mobius WSS hosts (CAI-8461) - #5175

Draft
mkesavan13 wants to merge 1 commit into
nextfrom
fix/CAI-8461-security-vulnerabilities
Draft

fix(calling): neutralize SCIM filter injection and restrict Mobius WSS hosts (CAI-8461)#5175
mkesavan13 wants to merge 1 commit into
nextfrom
fix/CAI-8461-security-vulnerabilities

Conversation

@mkesavan13

Copy link
Copy Markdown
Contributor

COMPLETES https://jira-eng-sjc12.cisco.com/jira/browse/CAI-8461

This pull request addresses

Three P0 security findings in @webex/calling:

  • U-01 — SCIM filter injection via SIP externalId (CallerId/index.ts:103-122): attacker-controlled value from a SIP header was interpolated raw into id eq "..." filter expressions, allowing injection of arbitrary SCIM filter clauses.
  • U-02 — SCIM filter injection via userExternalId (Utils.ts:1552-1565): same pattern in resolveContact — the callingPartyInfo.userExternalId field was interpolated without escaping.
  • U-03 — Mobius WSS socket with no host allowlist (Utils.ts:139-223, socket-base.ts:238-317): discovery-provided WSS URIs were trusted as socket destinations without validation, enabling a malicious discovery response to exfiltrate the Mobius bearer token to an arbitrary host.

Root cause: Attacker-influenceable identifiers were interpolated raw into SCIM filter expressions, and discovery-provided WSS hosts were trusted as socket destinations without an allowlist. The existing encodeURIComponent(filter) transport-layer encoding does not prevent SCIM filter grammar injection; a value-layer escape is required. No host validation existed before token transmission over WebSocket.

by making the following changes

  • packages/calling/src/common/constants.ts — Added MOBIUS_WSS_ALLOWED_DOMAINS allowlist (webex.com, wbx2.com, webexapis.com, cisco.com)
  • packages/calling/src/common/Utils.ts — Added escapeScimFilterValue helper (escapes \ then "); applied to resolveContact userExternalId; added host-allowlist filter isTrustedMobiusWssHost to filterMobiusUris dropping non-allowlisted WSS URIs
  • packages/calling/src/CallingClient/calling/CallerId/index.ts — Applied escapeScimFilterValue to SIP externalId before SCIM filter interpolation in parseRemotePartyInfo
  • packages/calling/src/mobius-socket/socket/socket-base.ts — Added pre-WebSocket host allowlist gate in open() — rejects with typed ConnectionError before authorize(token) runs
  • packages/calling/src/common/Utils.test.ts — Added UT-1 (resolveContact injection) and UT-4 (filterMobiusUris untrusted host); updated existing tests
  • packages/calling/src/CallingClient/calling/CallerId/index.test.ts — Added UT-2 (parseRemotePartyInfo injection)
  • packages/calling/src/mobius-socket/socket.test.ts — Added UT-3 (socket.open non-allowlisted rejection + allowlisted acceptance)
  • packages/calling/jest.config.js — Updated Jest module name mapper to use new stub mocks
  • packages/calling/package.json — Added pre-build of @webex/legacy-tools to resolve compile dependency
  • packages/calling/test/mocks/ — Added internal-plugin-metrics-stub.js, webex-core-stub.js, empty-stub.js for isolated unit test execution
  • packages/calling/ai-docs/ — Updated SECURITY.md, GETTING_STARTED.md, caller-id-spec.md, mobius-socket-spec.md to document the new controls

Change Type

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Tooling change
  • Internal code refactor

The following scenarios were tested

  • Tests added: 4 new unit tests (UT-1 through UT-4) across 4 test files
  • Gate 1 verification: passed — yarn workspace @webex/calling build:src compiled successfully
  • Gate 2 verification: passed — yarn workspace @webex/calling test:unit 857/857 tests passed
  • Gate 3 verification: not run
  • Coverage outcome: passed

Targeted test results (4 new security-focused suites):

yarn workspace @webex/calling test:unit \
  --testPathPattern="Utils.test.ts|CallerId/index.test.ts|socket.test.ts|mobius-socket.test.ts"

Test Suites: 4 passed, 4 total
Tests:       252 passed, 252 total

Acceptance Criteria

ID Criterion Source JiraToPr status Evidence
AC-1 Attacker-controlled SIP externalId and userExternalId values can no longer alter SCIM filter grammar: values are escaped/validated before being interpolated into id eq "...", so injected filter clauses (e.g. a value containing a double-quote) are neutralized while legitimate identifiers still resolve. Jira findings U-01, U-02 Unit validated escapeScimFilterValue applied at CallerId/index.ts:116 and Utils.ts:1600-1603; UT-1 and UT-2 confirmed passing in Gate 2
AC-2 The Mobius bearer token is only transmitted over a WSS socket whose host is on a trusted allowlist: discovery-provided WSS URIs with non-allowlisted hosts are dropped, and socket open rejects (before authorize) any URL whose host is not allowlisted, so a malicious discovery response cannot exfiltrate the token to an arbitrary host. Jira findings U-03 Unit validated MOBIUS_WSS_ALLOWED_DOMAINS constant + isTrustedMobiusWssHost + filterMobiusUris drop + socket-base.ts pre-connect guard; UT-3 and UT-4 confirmed passing in Gate 2

Contract Discovery Warnings

  • Manifest reference discovery capped at 100 strings

The GAI Coding Policy And Copyright Annotation Best Practices

  • GAI was not used (or, no additional notation is required)
  • Code was generated entirely by GAI
  • GAI was used to create a draft that was subsequently customized or modified
  • Coder created a draft manually that was non-substantively modified by GAI (e.g., refactoring was performed by GAI on manually written code)
  • Tool used for AI assistance (GitHub Copilot / Other - specify)
    • Github Copilot
    • Other - Please Specify: JiraToPr (Claude Sonnet 4.5 via Anthropic API)
  • This PR is related to
    • Feature
    • Defect fix
    • Tech Debt
    • Automation

I certified that

  • I have read and followed contributing guidelines
  • I discussed changes with code owners prior to submitting this pull request
  • I have not skipped any automated checks
  • All existing and new tests passed
  • I have updated the documentation accordingly

Jira: https://jira-eng-sjc12.cisco.com/jira/browse/CAI-8461

…S hosts (CAI-8461)

Jira: https://jira-eng-sjc12.cisco.com/jira/browse/CAI-8461

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@mkesavan13 mkesavan13 added the jira-to-pr Automated PR from JiraToPr workflow label Aug 18, 2026
@aws-amplify-us-east-2

Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-5175.d3m3l2kee0btzx.amplifyapp.com

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

Labels

jira-to-pr Automated PR from JiraToPr workflow

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant