From ebd23c323c648fe2fc60503368d42e8d5f58a7bf Mon Sep 17 00:00:00 2001 From: Pavan Kumar Reddy B Date: Wed, 5 Aug 2026 22:41:50 +0530 Subject: [PATCH 1/2] RDKB-65597 : [Risk-High] JST (Generic) Security Fuzzing Report Root Cause: ftell() causing calloc() to request an enormous allocation and trigger an OOM abort. Recommendation - Check `ftell()` return value for `-1` before using it as allocation size: Root Cause: `strtok()` on const/env Memory Recommendation - Replace destructive strtok() parsing with read-only boundary detection using strchr(), copy the session ID into a local writable buffer, and use that buffer for validation and file lookup. Root Cause: Session identifier validation can be bypassed, potentially allowing session hijacking. Recommendation - Check Session IDs length and prefix, it should contain only alphanumeric suffix characters, avoid in-place cookie modification during parsing, and are accepted only if the corresponding session file exists. --- source/jst_internal.c | 13 +++++++++++-- source/jst_session.c | 26 ++++++++++++++++++-------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/source/jst_internal.c b/source/jst_internal.c index e7312f0..120f471 100644 --- a/source/jst_internal.c +++ b/source/jst_internal.c @@ -164,6 +164,7 @@ int read_file(const char *filename, char** bufout, size_t* lenout) { FILE* pf; size_t size; + long tell_result; size_t rc; char* buf; @@ -179,8 +180,16 @@ int read_file(const char *filename, char** bufout, size_t* lenout) return 0; } - fseek(pf, 0, SEEK_END); - size = ftell(pf); + fseek(pf, 0, SEEK_END); + tell_result = ftell(pf); + if (tell_result < 0) + { + CosaPhpExtLog("read_file ftell failed:%s error:%s\n", filename, strerror(errno)); + fclose(pf); + fprintf(stderr, "Error: ftell failed %s\n", filename); + return 0; + } + size = (size_t)tell_result; rewind(pf); buf = (char*)calloc(size+1, 1); diff --git a/source/jst_session.c b/source/jst_session.c index 69f542f..9cb7c9d 100644 --- a/source/jst_session.c +++ b/source/jst_session.c @@ -75,6 +75,9 @@ static duk_ret_t session_start(duk_context *ctx) { CosaPhpExtLog("%s: entered\n", __PRETTY_FUNCTION__); const char* cookie; + const char* sesid_end; + size_t sesid_len; + char parsed_sesid[SESSION_ID_LENGTH + 1]; /* if session already created then do nothing */ if(session_identifier) { @@ -112,13 +115,19 @@ static duk_ret_t session_start(duk_context *ctx) if(sesid) { sesid += 7; - int len = strlen(sesid); - if(len >= SESSION_ID_LENGTH) + sesid_end = strchr(sesid, ';'); + sesid_len = sesid_end ? (size_t)(sesid_end - sesid) : strlen(sesid); + if(sesid_len == SESSION_ID_LENGTH) { int idx = SESSION_PREFIX_LEN; int isvalid = 1; + if(strncmp(sesid, SESSION_PREFIX, SESSION_PREFIX_LEN) != 0) + { + CosaPhpExtLog("Invalid SessionID prefix\n"); + isvalid = 0; + } /* Validate session ID*/ - while ( idx < SESSION_ID_LENGTH) { + while (isvalid && idx < SESSION_ID_LENGTH) { if (!isalnum(sesid[idx])) { CosaPhpExtLog("Invalid SessionID\n"); isvalid = 0; @@ -128,19 +137,20 @@ static duk_ret_t session_start(duk_context *ctx) } if(isvalid) { - sesid = strtok(sesid, ";"); - const char filename[SESSION_FILE_MAX_PATH]; - snprintf(filename, SESSION_FILE_MAX_PATH, "%s/%s", SESSION_TMP_DIR, sesid); + memcpy(parsed_sesid, sesid, SESSION_ID_LENGTH); + parsed_sesid[SESSION_ID_LENGTH] = '\0'; + char filename[SESSION_FILE_MAX_PATH]; + snprintf(filename, SESSION_FILE_MAX_PATH, "%s/%s", SESSION_TMP_DIR, parsed_sesid); CosaPhpExtLog("%s: Checking for Session file %s\n", __PRETTY_FUNCTION__, filename); if (access(filename, F_OK) == 0) { CosaPhpExtLog("%s: Session file %s exists\n", __PRETTY_FUNCTION__, filename); - strncpy(session_identifier, sesid, SESSION_ID_LENGTH); + strncpy(session_identifier, parsed_sesid, SESSION_ID_LENGTH); } else { CosaPhpExtLog("%s: Failed to read Session file %s\n", __PRETTY_FUNCTION__, filename); } } - } else { + } else { CosaPhpExtLog("Invalid SessionID Entropy\n"); } } From f623c590fd5c25076f8a2a8d32d6953803b16ff6 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Reddy B <57708013+pavankumar464@users.noreply.github.com> Date: Wed, 5 Aug 2026 22:48:58 +0530 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- source/jst_internal.c | 17 ++++++++++++++++- source/jst_session.c | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/source/jst_internal.c b/source/jst_internal.c index 120f471..4d55f94 100644 --- a/source/jst_internal.c +++ b/source/jst_internal.c @@ -180,7 +180,15 @@ int read_file(const char *filename, char** bufout, size_t* lenout) return 0; } - fseek(pf, 0, SEEK_END); + if (fseek(pf, 0, SEEK_END) != 0) + { + CosaPhpExtLog("read_file fseek failed:%s error:%s\n", filename, strerror(errno)); + fclose(pf); + fprintf(stderr, "Error: fseek failed %s\n", filename); + return 0; + } + + errno = 0; tell_result = ftell(pf); if (tell_result < 0) { @@ -189,6 +197,13 @@ int read_file(const char *filename, char** bufout, size_t* lenout) fprintf(stderr, "Error: ftell failed %s\n", filename); return 0; } + if ((unsigned long long)tell_result > (unsigned long long)(SIZE_MAX - 1)) + { + CosaPhpExtLog("read_file size overflow:%s size:%ld\n", filename, tell_result); + fclose(pf); + fprintf(stderr, "Error: file too large %s\n", filename); + return 0; + } size = (size_t)tell_result; rewind(pf); diff --git a/source/jst_session.c b/source/jst_session.c index 9cb7c9d..5d0d334 100644 --- a/source/jst_session.c +++ b/source/jst_session.c @@ -128,7 +128,7 @@ static duk_ret_t session_start(duk_context *ctx) } /* Validate session ID*/ while (isvalid && idx < SESSION_ID_LENGTH) { - if (!isalnum(sesid[idx])) { + if (!isalnum((unsigned char)sesid[idx])) { CosaPhpExtLog("Invalid SessionID\n"); isvalid = 0; break;