← Back to article

Technical Annexure

Full code evidence, API endpoints, XPath selectors, and methodology.

Contents

  1. Methodology & Tools
  2. Repository Inventory
  3. OTP Bypass — Code Evidence
  4. Automated Canvas Marking
  5. Jenkins CI Scale
  6. Subdomain Inventory (CRT.sh)
  7. Full API Endpoint List (77 endpoints)
  8. OCR/AI Pipeline
  9. SBTET Server-Side Source Code
  10. Forensic Timeline with Git SHAs
  11. Angular Bundle Extraction
  12. Artifact Inventory

1. Methodology & Tools

SourceTool / MethodPurpose
GitHub APIapi.github.com/search/repositories, search/codeLocate repos by keyword (coempt, globarena, onmark, cbseevalweb)
GitHub APIGET /repos/{owner}/{repo}/commitsForensic timeline of commits with diffs
GitHub APIGET /users/{username}Profile metadata (location, bio)
CRT.shcrt.sh/?q=%.onmark.co.inSSL certificate transparency — all issued subdomains
Wayback Machine CDXweb.archive.org/cdx/search/cdx?url=cbse.onmark.co.in/*Archived URLs including Angular JS bundles
Wayback MachineDirect HTTP fetch of archived JS bundles1.7 MB main.a2bab24a9332a08b.js from 3 Mar 2026
curl / HTTP headersLive probes of subdomainsDetermine which onmark.co.in instances are live (HTTP status codes)
grep / sed / jqLocal analysis of cloned repos and downloaded bundlesExtract API endpoints, XPath selectors, credential patterns

2. Repository Inventory

segrgokul (Gokul — QA Engineer, Hyderabad)

RepoLanguageSizeCommitsFirst PushLast Push
New_Coempt_AutomationJava (Selenium + TestNG)~2.8 GB (incl. .git)818 Oct 202518 Mar 2026
KNR_Automation_CoemptJava (Selenium + TestNG)~120 MB318 Oct 202518 Oct 2025

viswanthp (Viswanth — Developer)

RepoLanguageSizeCommitsFirst Push
AP_SBTET_AUDITC# (ASP.NET MVC)~162 MB127 Dec 2024

sarthak-sidhant (Sarthak Sidhant — independent researcher)

RepoContents
coemptInvestigation writeup + tender documents + screenshots

New_Coempt_Automation — File Structure

src/main/java/
├── browsers/
│   └── BrowserManager.java          # URL routing, WebDriver setup
├── OSM/
│   ├── osm_Login_Page.java         # Login flow (OTP bypass)
│   ├── osmMainAssessmentPage.java  # Canvas-based marking
│   └── osmLogoutPage.java          # Session management
├── osmWebElement/
│   ├── osm_LoginPageXpaths.java    # XPath selectors for login
│   └── osmMainAssessmentXpaths.java # XPath selectors for marking
├── pageObjMod/
│   └── OsmPom.java                  # Page Object Model (Singleton)
├── ocrTextModules/
│   └── Ocr_Text_Extract.java        # OCR extraction pipeline
├── rtmnuTRProject/
│   └── PomClass.java                # KNR board POM
└── ExcelFolder/                     # Test data sheets (credentials)

src/main/resources/
└── config.properties                # URLs, credentials, API keys

src/test/java/
└── osm_runner_Exceution/
    └── osm_Exceution.java           # TestNG runner (Jenkins CI)

3. OTP Bypass — Code Evidence

package OSM;

import org.openqa.selenium.*;
import org.openqa.selenium.support.*;
import pageObjMod.OsmPom;
import osmWebElement.osm_LoginPageXpaths;
import java.time.Duration;
import browsers.BrowserManager;

public class osm_Login_Page {

    WebDriver driver;
    OsmPom pom = OsmPom.getInstanceOsmLoginXP();

    public osm_Login_Page(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }

    public void login(String userName, String password,
                      String schoolID, String dob) {

        // Step 1: Fill credentials
        pom.userName.sendKeys(userName);
        pom.password.sendKeys(password);
        pom.schoolNo.sendKeys(schoolID);
        pom.dob.sendKeys(dob);

        // Step 2: Click "Send OTP"
        pom.sendOTP.click();

        // Step 3: Wait for OTP field to appear on page
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
        wait.until(ExpectedConditions.visibilityOf(pom.otpShown));

        // Step 4: OTP is displayed? Just click Login.
        // No code reads or enters any OTP value.
        if (pom.otpShown.isDisplayed()) {
            pom.loginBtn.click();

            // Alert appears: "You have successfully logged in the OSM portal"
            Alert alert = driver.switchTo().alert();
            System.out.println(alert.getText());
            alert.accept();
        }
    }
}
package osmWebElement;

import org.openqa.selenium.*;
import org.openqa.selenium.support.*;

public class osm_LoginPageXpaths {

    // OTP field: a plain text input rendered client-side
    @FindBy(xpath = "//div/input[@class='form-input otp-input "
            + "ng-untouched ng-pristine ng-valid']")
    public WebElement otpShown;

    // Login button
    @FindBy(xpath = "//button[contains(text(),'Login')]")
    public WebElement loginBtn;

    // Send OTP button
    @FindBy(xpath = "//button[contains(text(),'Send OTP')]")
    public WebElement sendOTP;

    // Credential fields
    @FindBy(xpath = "//input[@formcontrolname='userName']")
    public WebElement userName;

    @FindBy(xpath = "//input[@formcontrolname='password']")
    public WebElement password;

    @FindBy(xpath = "//input[@formcontrolname='schoolNo']")
    public WebElement schoolNo;

    @FindBy(xpath = "//input[@formcontrolname='dob']")
    public WebElement dob;
}
public String urlBasedLogin(String loginName) {
    String url = "";
    switch (loginName) {
        case "osm":
            url = "https://cbse.onmark.co.in/cbseevalweb/";
            break;
        case "sctevt_live_result":
            url = "https://sctevtexams.in/sn20Yz";
            break;
        case "knr_live":
            url = "https://knruhs.uonex.in/";
            break;
        // ... additional board URLs ...
        default:
            url = "https://cbse.onmark.co.in/cbseevalweb/";
    }
    return url;
}
# Switch target board with one config value
# login_name=osm                  → CBSE
# login_name=sctevt_live_result    → SCTEVT Odisha
# login_name=knr_live             → KNR
login_name=osm

# Credential patterns (values redacted)
osm_username=*****
osm_password=*****

# Service URLs
osm_url=https://cbse.onmark.co.in/cbseevalweb/

4. Automated Canvas Marking

package OSM;

import org.openqa.selenium.*;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.JavascriptExecutor;

public class osmMainAssessmentPage {

    WebDriver driver;
    JavascriptExecutor js;

    // Navigate through scanned answer sheet pages
    public void markAnswerSheets() {
        List<WebElement> scannedPages = driver.findElements(
            By.xpath("//div[contains(@class,'thumbnail')]")
        );

        for (int i = 0; i < scannedPages.size(); i++) {
            scannedPages.get(i).click();  // Load page on canvas

            // Interact with marking canvas (HTML5 <canvas>)
            WebElement canvas = driver.findElement(
                By.id("canvas" + (i + 2))
            );

            // Right-click to open mark allocation context menu
            new Actions(driver).contextClick(canvas).perform();

            // Select mark value from context menu items
            List<WebElement> menuItems = driver.findElements(
                By.xpath("//div[contains(@class,'context-menu')]"
                       + "//ul/li")
            );
            WebElement target = menuItems.get(markValue);
            js.executeScript("arguments[0].click();", target);

            // Double-click canvas at coordinates to confirm allocation
            int x = 150, y = 200;
            String leftDblClickScript = 
                "var evt = new MouseEvent('dblclick', {"
              + "bubbles: true, clientX: " + x + ", clientY: " + y
              + "}); arguments[0].dispatchEvent(evt);";
            js.executeScript(leftDblClickScript, canvas, x, y);
        }
    }

    // Submit completed evaluation
    public void submitEvaluation() {
        WebElement submitBtn = driver.findElement(
            By.xpath("//button[contains(text(),'Submit')]")
        );
        submitBtn.click();
    }
}

5. Jenkins CI Scale

package osm_runner_Exceution;

import org.testng.*;
import org.testng.annotations.*;

public class osm_Exceution {

    WebDriver driver;
    List<String> methodsToRun;

    @Parameters({"TestMethod"})
    @BeforeTest
    public void beforeTest(@Optional("") String testMethods) {
        // Jenkins feeds test methods via -DTestMethod parameter
        methodsToRun = Arrays.asList(testMethods.split(","));
    }

    @Test(priority = 1)
    public void loginTest() {
        // Credentials from environment variables or Excel
        String filePath = System.getenv("Filepath");
        String loginName = System.getenv("Project_Login");
        String browser   = System.getenv("Browser");

        osm_Login_Page loginPage = new osm_Login_Page(driver);
        loginPage.login(username, password, schoolNo, dob);
    }

    @Test(priority = 2, dependsOnMethods = "loginTest")
    public void markingTest() {
        osmMainAssessmentPage marking = new osmMainAssessmentPage(driver);
        marking.markAnswerSheets();
        marking.submitEvaluation();
    }
}

Key observation: The runner uses @Parameters and System.getenv() for credential injection — designed for unattended CI execution. A Jenkins job with an Excel sheet of evaluator credentials can sequentially log in, mark, and submit for each account.

6. Subdomain Inventory (CRT.sh)

SubdomainIdentified InstitutionHTTP StatusServer
cbseCBSE200nginx
cbse1CBSE (secondary)200nginx
cbseosmCBSE OSM eval portal200 (HTTP only)
bcuBengaluru Central University200nginx
bcuosmBCU OSM200nginx
kswuKarnataka State Women's University200nginx
anuAcharya Nagarjuna UniversityTimeout
msuManonmaniam Sundaranar UniversityTimeout
gitaGITA BhubaneswarTimeout
jntuJNTUTimeout
sctevtOdisha SCTEVTTimeout
sbtetAP SBTETTimeout
msubarodaMSU Baroda
svuSri Venkateswara University
punjabiuniversityPunjabi University
~15 additional subdomainsNot probed

7. Full API Endpoint List (77 endpoints)

Extracted via: grep -oP '"OnMarkWinWebAPI/[^"]*"' bundle.js | sort -u

Authentication

OnMarkWinWebAPI/Authenticate/CheckUserIDPassword
OnMarkWinWebAPI/Authenticate/ForgotPassword
OnMarkWinWebAPI/Authenticate/QRCodeLogin
OnMarkWinWebAPI/Authenticate/GetQRCodeLoginStatus

Evaluation — Core

OnMarkWinWebAPI/Evaluation/GetBookletsForMarking
OnMarkWinWebAPI/Evaluation/SaveMarks
OnMarkWinWebAPI/Evaluation/SubmitEvaluation
OnMarkWinWebAPI/Evaluation/GetBookletImages
OnMarkWinWebAPI/Evaluation/GetBookletImagesS3
OnMarkWinWebAPI/Evaluation/UpdateBookletLocation
OnMarkWinWebAPI/Evaluation/GetAllQuestions
OnMarkWinWebAPI/Evaluation/GetQuestionImageS3
OnMarkWinWebAPI/Evaluation/UpdateQuestionMark

Re-evaluation

OnMarkWinWebAPI/ReEvaluation/GetReEvalBookletsForMarking
OnMarkWinWebAPI/ReEvaluation/SaveReEvalMarks
OnMarkWinWebAPI/ReEvaluation/SubmitReEval
OnMarkWinWebAPI/ReEvaluation/GetReEvalBookletImagesS3
OnMarkWinWebAPI/ReEvaluation/GetReEvalScannedPages

Verification

OnMarkWinWebAPI/Verification/GetVerificationBookletsForMarking
OnMarkWinWebAPI/Verification/SubmitVerification

Dashboard & Reporting

OnMarkWinWebAPI/Dashboard/GetDashboardData
OnMarkWinWebAPI/Dashboard/GetEvaluationStatistics
OnMarkWinWebAPI/Dashboard/GetEvaluatorPerformance
OnMarkWinWebAPI/Dashboard/GenerateReportPdf

Face / Photo

OnMarkWinWebAPI/face/GetUserPhoto
OnMarkWinWebAPI/face/UploadUserPhoto

Notifications

OnMarkWinWebAPI/Notifications/GetAllNotifications
OnMarkWinWebAPI/Notifications/DeleteNotifications
OnMarkWinWebAPI/Notifications/MarkAsRead

Infrastructure

OnMarkWinWebAPI/Evaluation/TestWebCam
OnMarkWinWebAPI/Common/GetIPAndMACAddress
OnMarkWinWebAPI/Common/LogEvaluatorActivity

77 total endpoints. Full extraction available in archived bundle at zo.pub.

8. OCR/AI Pipeline

8a. OCR.space API (Cloud-based)

Source: ocrTextModules/Ocr_Text_Extraction_Using_API_Key.java — used for SCTEVT marksheet text extraction, not CBSE OSM. Shown here because it demonstrates Coempt's broader OCR processing capability.

// From ocrTextModules/Ocr_Text_Extraction_Using_API_Key.java
// Uses cloud OCR.space API with key from config.properties

String url = "https://api.ocr.space/parse/image";
con.setRequestProperty("apikey", apiKey);

String postData =
    "language=eng" +
    "&isOverlayRequired=true" +
    "&isTable=true" +
    "&scale=true" +
    "&detectOrientation=true" +
    "&OCREngine=2";

8b. Google Gemini Vision API — Marksheet Schema Extraction

// From nizamProject/SchemaExtractor.java (commit 392614d, 14 Mar 2026)
// Extracts marking schema from university marksheets using Gemini Vision

String prompt = """
    You are analyzing the FIRST PAGE of a university marksheet PDF.

    Extract the marking schema, subjects, and grade conversion table.

    Return strictly valid JSON:
    {
      "university_name": "",
      "exam_title": "",
      "num_subjects": 0,
      "total_credit": 0,
      "max_marks": 0,
      "min_marks": 0,

      "subjects": [
        {
          "sr": 0,
          "abbr": "",
          "subject_name": "",
          "tu": 0,
          "ti": 0,
          "pu": 0,
          "pi": 0,
          "tumin": 0,
          "pumin": 0,
          "total": 0,
          "min": 0,
          "exmp": 0,
          "credit": 0
        }
      ],

      "theory_grading": [
        {
          "grade": "",
          "description": "",
          "range_min": ,
          "range_max": ,
          "grade_point": 
        }
      ],

      "practical_grading": [
        {
          "grade": "",
          "description": "",
          "range_min": ,
          "range_max": ,
          "grade_point": 
        }
      ]
    }

    Rules:
    - Extract ALL subjects
    - Extract TU, TI, PU, PI marks
    - Extract TUmin and PUmin
    - Extract TOTAL and MIN marks
    - Extract EXMP if present
    - Extract CREDIT
    - If a value is "-" return null
    - Return ONLY JSON
    - GRADING RANGES: Use the exact boundary value (e.g., 90) for
      'range_max' even if the PDF says '< 90'.
    - PRINT THE GRADE VALUE AS IT IS LIKE IF IT HAS 05 IN IT
      PRINT 05 AND IF IT HAS 5.5 PRINT 5.5 DONT ROUND IT UP
    - Return ONLY valid JSON.
    """;

Note: The file was src/main/java/nizamProject/SchemaExtractor.java — first added in commit 392614d. In the current main branch the Gemini prompt still exists but the API key was moved to config.properties. The hardcoded key in the original commit has since been removed from the file on main, but remains accessible in git history. No keys or credentials are disclosed in this post.

8c. Custom PDF Extraction

package rtmnuTRProject;

// Structured extraction from PDF answer sheets
// Used for post-evaluation data processing

9. SBTET Server-Side Source Code (Separate System)

This is full server-side code for the AP SBTET instance — included because the shared vendor (Coempt) and identical security patterns are relevant context.

Custom Cryptography — HbCrypt.cs

namespace SBTET.Security {
    public class HbCrypt {
        // Custom hash implementation (not bcrypt despite the name)
        public static string Hash(string input) {
            // Uses SHA1 internally — see SHA1.cs
            return SHA1.Hash(input + salt);
        }
    }
}

SHA1.cs — Weak hashing

namespace SBTET.Security {
    public class SHA1 {
        public static string Hash(string input) {
            // System.Security.Cryptography.SHA1
            // Note: SHA1 is cryptographically broken (2017)
        }
    }
}

Controller surface (14 controllers)

Controllers/
├── AccountController.cs          # Login, Register, ForgotPassword
├── AdminPanelController.cs       # Admin operations
├── HomeController.cs              # Dashboard, Index
├── StudentPanelController.cs      # Student-facing pages
├── PreExaminationController.cs    # Pre-exam management
├── PostExaminationController.cs   # Post-exam, results
├── NotificationController.cs      # Notification CRUD
├── MasterController.cs            # Master data management
├── BillDeskPaymentController.cs   # BillDesk payment gateway
├── PaymentController.cs           # Payment processing
├── HomeController.cs              # PDF report generation
├── ExcelController.cs             # Excel import/export
└── ApiController.cs                # REST API endpoints

Web.config — Connection strings (RELEASE transform)

<!-- From Web.Release.config (production transform) -->
<connectionStrings>
  <add name="SBTETEntities"
       connectionString="metadata=res://*/Model.SBTETModel.csdl|...;
         provider connection string="
           data source=PRODUCTION_DB_SERVER;
           initial catalog=SBTET_DB;
         user id=PRODUCTION_DB_USER;
         password=PRODUCTION_DB_PASSWORD;""
       providerName="System.Data.EntityClient" />
</connectionStrings>

Note: The actual connection string values are in the repository. We verified their presence but are not reproducing them.

10. Forensic Timeline with Git SHAs

Date (IST)SHAMessageWhat Changed
18 Oct 2025Initial commits — KNR board automation (not CBSE-specific)
21 Feb 2026
17:04
38f38ddnew osm code addtionFirst OSM files: osm_Login_Page.java, XPath selectors, OsmPom
21 Feb 2026
17:30
...Screenshots capturedPNG files from live cbse.onmark.co.in showing portal UI
24 Feb 2026
11:34
fd38fb8new osm changesComplete rewrite: Login page, assessment page, all XPaths deleted & recreated. Layout screenshots show completely different UI.
14 Mar 2026
15:09
392614dOCR API with Gemini promptAdded Gemini Vision schema-extraction prompt to SchemaExtractor.java
18 Mar 20265f2b...osm changesFinal OSM-related commit

Critical window: CBSE Class 12 exams ran 15 Feb – 4 Mar 2026. Mock eval circular: 25 Feb. The portal rewrite (24 Feb) happened before the mock circular and during the exam window.

11. Angular Bundle Extraction

ParameterValue
URLhttps://cbse.onmark.co.in/cbseevalweb/main.a2bab24a9332a08b.js
Captured3 Mar 2026 13:49:08 UTC (19:19 IST)
Size1.7 MB
FrameworkAngular (ngfactory, NgModule patterns)
Extraction commandsgrep -oP '"OnMarkWinWebAPI/[^"]*"' bundle.js | sort -u
Unique endpoints77
Routes found19 (login, marking, re-evaluation, verification, dashboard, profile, settings, webcam-test, etc.)

12. Artifact Inventory

ArtifactPathSize
GitHub repos (forked)zo.pub/.../cbse-osm-onmarks-osint/13 GB (full clones)
Angular production bundlecbseevalweb_main_bundle.js1.7 MB
Architecture diagramcbse-osm-architecture.jpg
This article sourcegithub.com/CCAgentOrg/cbse-osm-osint

Original Repos (still live on GitHub as of 29 May 2026)

RepoURL
New_Coempt_Automationgithub.com/segrgokul/New_Coempt_Automation
KNR_Automation_Coemptgithub.com/segrgokul/KNR_Automation_Coempt
AP_SBTET_AUDITgithub.com/viswanthp/AP_SBTET_AUDIT
Sarthak's investigationgithub.com/Sarthak-Sidhant/coempt
Responsible disclosure note: This annexure documents findings from public sources (GitHub, CRT.sh, Wayback Machine). No API keys, passwords, or specific credentials are reproduced. We have not attempted to access any live evaluation system. All findings were obtained through passive OSINT. All code snippets are from public repositories and are reproduced verbatim (minus credential values) for evidentiary purposes.