Skip to content

Develop#509

Merged
kkyusuftk merged 45 commits intomasterfrom
develop
Jan 29, 2026
Merged

Develop#509
kkyusuftk merged 45 commits intomasterfrom
develop

Conversation

@kkyusuftk
Copy link
Collaborator

@kkyusuftk kkyusuftk commented Jan 29, 2026

Changes

Describe the key changes in this PR with the Jira Issue reference

Changes to Public Facing API if any

Please list the impact on the public facing API if any

How Has This Been Tested?

Describe the testing approach and any relevant configurations (e.g., environment, platform)

Checklist

  • Code compiles without errors
  • Version Bump added to package.json & CHANGELOG.md
  • All tests pass
  • Build process is successful
  • Documentation has been updated (if needed)
  • Automation tests are passing

Link to Deployed SDK

Use these url for testing :

  1. https://static.wizrocket.com/staging/<CURRENT_BRANCH_NAME>/js/clevertap.min.js
  2. https://static.wizrocket.com/staging/<CURRENT_BRANCH_NAME>/js/sw_webpush.min.js

How to trigger Automations

Just add a empty commit after all your changes are done in the PR with the command

 git commit --allow-empty -m "[run-test] Testing Automation"

This will trigger the automation suite


Note

Medium Risk
Modifies the core request dispatch path (Fetch/JSONP selection, URL rewriting, response handling) and introduces crypto + localStorage fallback state, which could impact event delivery when the new flags are enabled.

Overview
Adds feature-flagged “Encryption in Transit” support (v2.5.0). When enableEncryptionInTransit is enabled, RequestDispatcher now encrypts the d query parameter using AES-GCM, forces the Fetch transport, and tags requests with an encryption header.

Introduces resilience and state for mixed backend support. Fetch responses now handle specific status codes (402/419 to fall back to JSONP for the session via CT_EIT_FALLBACK, 420 to retry), and attempt to decrypt response bodies before JSON parsing.

Updates SDK version strings to 2.5.0, adds Encryption-in-Transit.md, and updates CHANGELOG.md accordingly.

Written by Cursor Bugbot for commit 86e999a. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

Release Notes v2.5.0

  • New Features

    • Added encrypted data transmission support between SDK and backend, with automatic fallback mechanism
    • Added Fetch API as an alternative transport option for improved performance
    • Introduced configurable logging system with adjustable verbosity levels
  • Tests

    • Added comprehensive unit test coverage for new encryption and transport features
  • Chores

    • Bumped SDK version to 2.5.0
    • Added development dependency for runtime compatibility

✏️ Tip: You can customize this high-level summary in your review settings.

@kkyusuftk kkyusuftk requested a review from a team as a code owner January 29, 2026 10:00
@francispereira
Copy link

francispereira commented Jan 29, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai
Copy link

coderabbitai bot commented Jan 29, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This PR introduces Fetch API support and Encryption-In-Transit (AES-GCM-256) capabilities to the CleverTap Web SDK. It adds a new EncryptionInTransit singleton class for payload encryption, extends RequestDispatcher with encrypted request handling and JSONP fallback logic, implements a centralized Logger singleton, and introduces configuration flags to enable/disable these features. Version bumped from 2.4.0 to 2.5.0.

Changes

Cohort / File(s) Summary
Versioning & Documentation
CHANGELOG.md, package.json, Encryption-in-Transit.md
Version bumped to 2.5.0; new changelog entry added; comprehensive design document for EIT implementation; regenerator-runtime devDependency added.
Core SDK API & Configuration
src/clevertap.js, clevertap.js
Added public accessors (enableFetchApi, enableEncryptionInTransit) to CleverTap class; integrated Logger singleton and EncryptionInTransit singleton; added EIT fallback management methods; version string updated to v2.5.0; new CT_EIT_FALLBACK constant and related fallback control flow for JSONP retry paths.
Encryption & Security
src/util/security/encryptionInTransit.js
New EncryptionInTransit singleton class implementing AES-GCM-256 encryption with 256-bit keys, 12-byte IV, and 128-bit tag; provides encryptForBackend and decryptFromBackend methods; includes Base64 encoding/decoding and random byte generation utilities; instance exported to window.encryptionInTransitInstance.
Request Handling & Transport
src/util/requestDispatcher.js
Added static flags (enableFetchApi, enableEncryptionInTransit) and EIT session management methods (isEITFallbackActive, setEITFallback, clearEITFallback); introduced private methods #prepareEncryptedRequest and #retryViaJSONP; new public handleFetchResponse method for fetch-based request handling with encryption header support; reworked request firing flow to integrate encryption and fallback logic; handles 402/419 server-side EIT disable with automatic JSONP retry.
Constants & Utilities
src/util/constants.js, src/util/encoder.js, src/util/clevertap.js
Added ENCRYPTION_KEY_NAME and CT_EIT_FALLBACK constants; implemented decompressFromBase64 and decompress functions for envelope decompression; minor formatting change in clevertap.js guard condition (no functional change).
Test Infrastructure & Setup
test/setup.js, test/unit/*.spec.js, test/unit/util/*.spec.js
Added global TextEncoder/TextDecoder polyfills for Node.js; extended test mocks for RequestDispatcher, StorageManager, and encryption utilities; introduced regenerator-runtime imports; comprehensive test scaffolding for EIT and fetch flows; new test suite for EncryptionInTransit with mock crypto.subtle API.
Integration & Validation Tests
test-encryption.js
New manual encryption test file demonstrating payload encryption, envelope inspection, decryption round-trips, and string payload handling with error catching.

Sequence Diagrams

sequenceDiagram
    participant Client as CleverTap Client
    participant RD as RequestDispatcher
    participant EIT as EncryptionInTransit
    participant Server as Backend Server

    Client->>RD: fire(url, params)
    RD->>RD: check enableFetchApi && enableEncryptionInTransit
    alt Encryption Enabled
        RD->>EIT: prepareEncryptedRequest(url)
        EIT->>EIT: generateSymmetricKey()
        EIT->>EIT: encryptForBackend(payload)
        EIT-->>RD: {envelope, key, iv} base64
        RD->>Server: fetch(url, encryptedEnvelope)
        Server-->>RD: response (402/419 or 200)
    else Encryption Disabled or Error
        RD->>RD: retryViaJSONP(url)
        RD->>Server: inject script tag (JSONP)
        Server-->>RD: callback($WZRK_WR)
    end
    RD->>Client: handleResponse()
Loading
sequenceDiagram
    participant Client as CleverTap SDK
    participant RD as RequestDispatcher
    participant LS as localStorage
    participant Server as Backend Server

    Client->>RD: enableEncryptionInTransit = true
    RD->>RD: prepareEncryptedRequest()
    alt Encryption Enabled & No Fallback
        RD->>Server: fetch(encrypted payload)
        alt Server Returns 402/419 (EIT Disabled)
            Server-->>RD: 402/419 status
            RD->>LS: setItem(CT_EIT_FALLBACK, true)
            RD->>RD: retryViaJSONP(url)
            RD->>Server: JSONP fallback request
        else Success
            Server-->>RD: 200 response
            RD->>Client: process(decrypted response)
        end
    else Fallback Active
        RD->>LS: check CT_EIT_FALLBACK
        RD->>RD: retryViaJSONP(url)
        RD->>Server: JSONP request (unencrypted)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • KambleSonam
  • darshanclevertap

Poem

🐰 Encryption hops along the wire,
Keys dancing through the AES fire,
JSONP falls back when servers say no,
Fetch API makes the data flow,
Logs now whisper, secrets kept tight,
Version 2.5 shines so bright!

✨ Finishing touches
  • 📝 Generate docstrings

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.3.13)
clevertap.js

The --json option is unstable/experimental and its output might change between patches/minor releases.
{"summary":{"changed":0,"unchanged":1,"matches":0,"duration":{"secs":23,"nanos":129641893},"scannerDuration":{"secs":0,"nanos":4372033},"errors":74,"warnings":0,"infos":0,"skipped":0,"suggestedFixesSkipped":0,"diagnosticsNotPrinted":0},"diagnostics":[{"category":"lint/suspicious/noShadowRestrictedNames","severity":"error","description":"Do not shadow the global "Math" property.","message":[{"elements":[],"content":"Do not shadow the global "Math" property."}],"advices":{"advices":[{"log":["info",[{"elements":[],"content":"Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global."}]]}]},"verboseAdvices":{"advices":[]},"location":{"path":{"file":"clevertap.js"},"span":[15328,15332],"sourceCode":"(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n t

... [truncated 99999795 characters] ...

0;\n H[1] = H[1] + b | 0;\n H[2] = H[2] + c | 0;\n H[3] = H[3] + d | 0;\n H[4] = H[4] + e | 0;\n },\n _doFBiome encountered an unexpected error

This is a bug in Biome, not an error in your code, and we would appreciate it if you could report it to https://github.com/biomejs/biome/issues/ along with the following information to help us fixing the issue.

When opening the issue, please provide a minimal reproduction, or identify and share the file/code that triggers it. Without a way to reproduce the error, the error can't be fixed:

Source Location: crates/biome_console/src/lib.rs:151:14
Thread Name: main
Message: called Result::unwrap() on an Err value: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" }

🔧 ast-grep (0.40.5)
clevertap.js

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@kkyusuftk kkyusuftk merged commit edb7f95 into master Jan 29, 2026
13 of 14 checks passed
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 6 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

This is the final PR Bugbot will review for you during this billing cycle

Your free Bugbot reviews will reset on February 7

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

}

this.logger.error('Fetch error:', error);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing return statement breaks 420 error retry mechanism

High Severity

The handleFetchResponse function doesn't return the fetch promise, causing the 420 error retry mechanism to fail. When a 420 error occurs, the code at line 9320 does return this.handleFetchResponse(...), but since handleFetchResponse doesn't return anything (the fetch chain has no return statement), undefined is returned instead. The subsequent .then() handler receives undefined, bypasses the rawResponse === null || rawResponse instanceof Promise check, and eventually fails with JSON.parse(undefined). The retry happens in the background but its result is lost.

Additional Locations (1)

Fix in Cursor Fix in Web


if (config.enableEncryptionInTransit) {
_classPrivateFieldLooseBase(this, _enableEncryptionInTransit)[_enableEncryptionInTransit] = config.enableEncryptionInTransit;
RequestDispatcher.enableEncryptionInTransit = config.enableEncryptionInTransit;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing null check for config parameter causes crash

Medium Severity

The new config.enableFetchApi and config.enableEncryptionInTransit checks at lines 19761 and 19766 access properties directly on config without null safety. Other config property checks in the same init function use optional chaining (e.g., config === null || config === void 0 ? void 0 : config.customId). If a user explicitly passes null as the config parameter, these new lines will throw TypeError: Cannot read property 'enableFetchApi' of null.

Fix in Cursor Fix in Web

s.async = true;
document.getElementsByTagName('head')[0].appendChild(s);
this.logger.debug('req snt -> url: ' + url);
this.logger.debug('EIT fallback: req snt via JSONP -> url: ' + url);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated JSONP script injection logic

Low Severity

The _retryViaJSONP2 function duplicates the JSONP script injection logic that already exists in _fireRequest2. Both implementations clean up existing ct-jp-cb script elements and create new script tags with identical attributes (type, src, class, rel, async). This redundancy increases maintenance burden and risks inconsistent bug fixes if one location is updated but not the other.

Additional Locations (1)

Fix in Cursor Fix in Web



const encryptionInTransitInstance = new EncryptionInTransit();
window.encryptionInTransitInstance = encryptionInTransitInstance; // Export the singleton instance
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Encryption instance unnecessarily exposed on window global

Low Severity

The encryptionInTransitInstance is assigned to window.encryptionInTransitInstance but this global reference is never read anywhere in the codebase. The internal encryptionInTransitInstance constant is sufficient for all SDK operations. This appears to be leftover debug code that exposes internal implementation details (including the encryption key stored in this.encryptionKey) to the global scope unnecessarily.

Fix in Cursor Fix in Web

}).then(rawResponse => {
// Skip processing if this is a JSONP fallback (null response) or a retry promise
if (rawResponse === null || rawResponse instanceof Promise) {
return rawResponse;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code: Promise instanceof checks never trigger

Low Severity

The checks rawResponse instanceof Promise at line 9333 and processedResponse instanceof Promise at line 9356 are dead code. In JavaScript Promise chains, when a .then() callback returns a Promise, the chain automatically unwraps it—the next .then() receives the resolved value, not the Promise object itself. These conditions can never evaluate to true, making the associated code paths unreachable.

Additional Locations (1)

Fix in Cursor Fix in Web

return Promise.resolve({
url,
method: 'GET',
useFallback: this.isEITFallbackActive()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeated storage reads for fallback check

Low Severity

In _prepareEncryptedRequest2, isEITFallbackActive() is called three times in quick succession (lines 9588, 9589, and 9596). Each call reads from local storage via StorageManager.read(). The result of this method doesn't change during a single function execution, so calling it once and storing the result in a local variable would be cleaner and more efficient.

Fix in Cursor Fix in Web

@coderabbitai coderabbitai bot mentioned this pull request Feb 2, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants