Dalam tidur dalam terjaga, ku ucapkan salam sejahtera - Samudera

Hi, recently there was a request by some of you to poke into the MySejahtera App from yours truly non-elected Government.  This writing will only focus on static analysis instead of the dynamic HTTP Traffic observation that we normally do PT. The reason we are not doing any dynamic analysis is because I do not have official engagement to test the app thoroughly. So let's look what a static analysis would offer.

Snippet from news:

Personal Data is Safe

Personal Data safe  term is an assurance that existing  vulnerability that can be leverage (as far as they concern)  to leak out PII data is quite unlikely .

The appid at playstore is : my.gov.onegovappstore.mysejahtera. We can pull the app from apkpure.

apkpure

If you decompiled it you will get the following app structure:

App is using cordova

The app is built using Cordova Framework. Why? For some developers it's easier to build a hybrid app for so that they can published it for IOS and Android quickly. Not going to argue native versus hybrid over here.

Since we know that the app is built on top of Cordova , 90% of  the actual/functionality code for the apps are placed or located at /resources/assets/www/build

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
------         11/2/2021  12:34 PM          90745 0.js
------         11/2/2021  12:34 PM          89585 1.js
------         11/2/2021  12:34 PM           8608 10.js
------         11/2/2021  12:34 PM           8034 11.js
------         11/2/2021  12:34 PM           3671 12.js
------         11/2/2021  12:34 PM          22518 13.js
------         11/2/2021  12:34 PM          12476 14.js
------         11/2/2021  12:34 PM           8569 15.js
------         11/2/2021  12:34 PM          58334 16.js
------         11/2/2021  12:34 PM          27932 17.js
------         11/2/2021  12:34 PM          49361 18.js
------         11/2/2021  12:34 PM          60784 19.js
------         11/2/2021  12:34 PM         113920 2.js
------         11/2/2021  12:34 PM           6445 20.js
------         11/2/2021  12:34 PM           7618 21.js
------         11/2/2021  12:34 PM          14159 22.js
------         11/2/2021  12:34 PM           5652 23.js
------         11/2/2021  12:34 PM          10458 24.js
------         11/2/2021  12:34 PM           7253 25.js
------         11/2/2021  12:34 PM          58053 26.js
------         11/2/2021  12:34 PM          40185 27.js
------         11/2/2021  12:34 PM           5001 28.js
------         11/2/2021  12:34 PM           8068 29.js
------         11/2/2021  12:34 PM          52286 3.js
------         11/2/2021  12:34 PM           4981 30.js
------         11/2/2021  12:34 PM           7821 31.js
------         11/2/2021  12:34 PM           8436 32.js
------         11/2/2021  12:34 PM          31503 33.js
------         11/2/2021  12:34 PM          28442 34.js
------         11/2/2021  12:34 PM           6443 35.js
------         11/2/2021  12:34 PM           8511 36.js
------         11/2/2021  12:34 PM           8200 37.js
------         11/2/2021  12:34 PM          11938 38.js
------         11/2/2021  12:34 PM          27897 39.js
------         11/2/2021  12:34 PM         257809 4.js
------         11/2/2021  12:34 PM          16140 40.js
------         11/2/2021  12:34 PM           7746 41.js
------         11/2/2021  12:34 PM          13175 42.js
------         11/2/2021  12:34 PM           6293 43.js
------         11/2/2021  12:34 PM          27118 44.js
------         11/2/2021  12:34 PM           4746 45.js
------         11/2/2021  12:34 PM          11858 46.js
------         11/2/2021  12:34 PM          13826 47.js
------         11/2/2021  12:34 PM          26889 48.js
------         11/2/2021  12:34 PM           1736 49.js
------         11/2/2021  12:34 PM          81215 5.js
------         11/2/2021  12:34 PM          10087 50.js
------         11/2/2021  12:34 PM           1255 51.js
------         11/2/2021  12:34 PM           1265 52.js
------         11/2/2021  12:34 PM           6300 53.js
------         11/2/2021  12:34 PM          52899 54.js
------         11/2/2021  12:34 PM           5352 55.js
------         11/2/2021  12:34 PM          13549 56.js
------         11/2/2021  12:34 PM           9188 57.js
------         11/2/2021  12:34 PM          11211 58.js
------         11/2/2021  12:34 PM          24870 59.js
------         11/2/2021  12:34 PM         234344 6.js
------         11/2/2021  12:34 PM          14438 60.js
------         11/2/2021  12:34 PM          13267 61.js
------         11/2/2021  12:34 PM           7785 62.js
------         11/2/2021  12:34 PM          10352 63.js
------         11/2/2021  12:34 PM          48148 64.js
------         11/2/2021  12:34 PM          29990 65.js
------         11/2/2021  12:34 PM         153117 66.js
------         11/2/2021  12:34 PM           3013 67.js
------         11/2/2021  12:34 PM           1463 68.js
------         11/2/2021  12:34 PM           6484 69.js
------         11/2/2021  12:34 PM         238071 7.js
------         11/2/2021  12:34 PM         718829 70.js
------         11/2/2021  12:34 PM         230016 8.js
------         11/2/2021  12:34 PM         114373 9.js
------         11/2/2021  12:34 PM        1947666 main.css
------         11/2/2021  12:34 PM        1047137 main.js
------         11/2/2021  12:34 PM          97180 polyfills.js
------         11/2/2021  12:34 PM          15793 sw-toolbox.js
------         11/2/2021  12:34 PM        3221322 vendor.js

Sure enough the jscript is minified/packed and probably obsfucated .

But we can use JSBeautifier to make it easier to read .

Now here's is the interesting part for those who are eager to test the app!

Console.log is  practically everywhere. (Hint spot the sensitive data).

                        }), n || (console.log("Not Found"), e.zoneKey = "HIGH_RISK" == i.a.difference(o, t)[0] ? i.a.difference(o, t)[1] : i.a.difference(o, t)[0], e.zoneDetails = e.districtZoneDetails.zoneMessageMap["ms_MY" == e.translate.currentLang ? e.zoneKey + "_MY" : e.zoneKey], e.passCardColor = e.zoneDetails.cardColourCode), "Low" == e.risk ? e.isGreenBubblePass = !0 : (e.passCardColor = e.districtZoneDetails.zoneMessageMap.HIGH_RISK.cardColourCode, e.isGreenBubblePass = !1), console.log(e.zoneKey, e.passCardColor, e.zoneDetails)
                        }), n || (console.log("Not Found"), e.zoneKey = "HIGH_RISK" == i.a.difference(o, t)[0] ? i.a.difference(o, t)[1] : i.a.difference(o, t)[0], e.zoneDetails = e.districtZoneDetails.zoneMessageMap["ms_MY" == e.translate.currentLang ? e.zoneKey + "_MY" : e.zoneKey], e.passCardColor = e.zoneDetails.cardColourCode), "Low" == e.risk ? e.isGreenBubblePass = !0 : (e.passCardColor = e.districtZoneDetails.zoneMessageMap.HIGH_RISK.cardColourCode, e.isGreenBubblePass = !1), console.log(e.zoneKey, e.passCardColor, e.zoneDetails)
                    }) + " " + this.HSO.createdDate.toLocaleTimeString("en-US"), console.log("HSO data = ", this.HSO))
                    console.log("ProfilePage Tab selected!!"), setTimeout(function () {
                    console.log("getUserDetailsById::", e);
                        console.log("getEmployeeInfo::", e), n.StorageAccess.setValue("empId", e.employeeId), n.StorageAccess.setValue("employeeInfo", e), n.StorageAccess.setValue("empInfo", JSON.stringify(e)), e && (n.riskCategory = e.designationCode, n.user = e, n.risk = n.user.designationCode.includes("LOW") ? "Low" : "High", n.StorageAccess.getValue("districtZoneDetails").then(function (e) {
                        console.log("getEmployee failed!"), n.ReusableUtils.showHttpError(e), n.ReusableUtils.saveErrorLog({}, e)
                        console.log("getEmployeeInfo::", e), e && (n.riskCategory = e.designationCode, n.user = e, "location" in e && e.location ? (n.latCord = e.location.lat, n.longCord = e.location.lng, n.image1 = a.a.devLink + e.location.imageUrl, n.generateQRCode(), n.getStatus()) : n.generateQRCode(), n.displayData = n.user.displayName, n.designationData = n.user.designation ? n.user.designation : "")
                        console.log("getActiveScorecards called:::", e), e.data && (t.activeScorecardWidgets = e.data)
                        console.log(e)
                        })), n.isInfiniteProfileEnabled = e.totalCount > n.widgets.length, n.totalInfoCount = e.totalCount, n.getWidgetOrders(n.widgets), n.loading.dismiss(), console.log("page num::", n.pageNum), t && t.complete()
                        console.log("MyTeam::"), console.log(e), t.team = e, t.mySubordinates = e, e.length > 0 && (t.hasTeam = !0)
                        console.log("MyTeam::"), console.log(e), t.team = e, t.mySubordinates = e, e.length > 0 && (t.hasTeam = !0)
                        console.log("Encrypted Data: "), console.log(JSON.stringify(n)), t.toDataURL(n, {
                        console.log("Encrypted Data: "), console.log(JSON.stringify(n)), t.toDataURL(n, {
                            e.generated = n, console.log("ERROR::: ", t)
                        console.log("ProfileCards::"), console.log(JSON.stringify(t)), t && t.length && i.a.each(t, function (t) {
                        console.log("ProfileCards::"), console.log(JSON.stringify(t)), t && t.length && i.a.each(t, function (t) {
                    e.navParams.data && (e.user = e.navParams.get("employee"), t = e.user), t ? (console.log("employee!!!", t), e.isTabPage = !1, e.isSubordinate = !0, e.incrementCount = e.incrementCount + 1, e.presentEmpId = t.employeeId, e.getUserDetailsById(t.employeeId)) : (e.getProfileCards(), console.log("else employee!!!", t), e.isSubordinate = !1, e.StorageAccess.getValue("empInfo").then(function (t) {
                    e.navParams.data && (e.user = e.navParams.get("employee"), t = e.user), t ? (console.log("employee!!!", t), e.isTabPage = !1, e.isSubordinate = !0, e.incrementCount = e.incrementCount + 1, e.presentEmpId = t.employeeId, e.getUserDetailsById(t.employeeId)) : (e.getProfileCards(), console.log("else employee!!!", t), e.isSubordinate = !1, e.StorageAccess.getValue("empInfo").then(function (t) {
                    console.log("Sync called!");
                    this.widgets = [], this.competencyScorecardWidgets = [], this.activeScorecardWidgets = [], this.scorecardWidgets = [], this.otherWidgets = [], this.HSO = void 0, console.log("refresh loaded"), this.getUserDetailsById(this.presentEmpId, t), this.user.hasTeam && this.getTeam(this.presentEmpId), this.getProfileCards(), e && e.complete()
                    console.log(e);
                    console.log("Keyboard close!"), this.keyboard.close(), this.allSubordinates = this.team, console.log(e)
                    console.log("Keyboard close!"), this.keyboard.close(), this.allSubordinates = this.team, console.log(e)
                    console.log("Info lazy loading");
                    this.totalInfoCount > this.widgets.length ? (this.pageNum++, console.log("page num::", this.pageNum), this.getProfileInformation(this.user.employeeId, e)) : e.complete()
                    console.log("payload =", o), t.StorageAccess.getValue("bAth").then(function (n) {
                            console.log("Success::"), console.log(e), console.log(e.data), "data" in e && (t.StorageAccess.setValue("image2", a.a.devLink + e.data), t.image2 = a.a.devLink + e.data, t.generateQRCode(), console.log("Image 1 =", t.image1), console.log("Image 2 =", t.image2))
                            console.log("Success::"), console.log(e), console.log(e.data), "data" in e && (t.StorageAccess.setValue("image2", a.a.devLink + e.data), t.image2 = a.a.devLink + e.data, t.generateQRCode(), console.log("Image 1 =", t.image1), console.log("Image 2 =", t.image2))
                            console.log("Success::"), console.log(e), console.log(e.data), "data" in e && (t.StorageAccess.setValue("image2", a.a.devLink + e.data), t.image2 = a.a.devLink + e.data, t.generateQRCode(), console.log("Image 1 =", t.image1), console.log("Image 2 =", t.image2))
                            console.log("Success::"), console.log(e), console.log(e.data), "data" in e && (t.StorageAccess.setValue("image2", a.a.devLink + e.data), t.image2 = a.a.devLink + e.data, t.generateQRCode(), console.log("Image 1 =", t.image1), console.log("Image 2 =", t.image2))
                            console.log("Success::"), console.log(e), console.log(e.data), "data" in e && (t.StorageAccess.setValue("image2", a.a.devLink + e.data), t.image2 = a.a.devLink + e.data, t.generateQRCode(), console.log("Image 1 =", t.image1), console.log("Image 2 =", t.image2))
                            t.generateQRCode(), console.log("searchHotSpot error::"), console.log(e), t.ReusableUtils.saveErrorLog({}, e)
                            t.generateQRCode(), console.log("searchHotSpot error::"), console.log(e), t.ReusableUtils.saveErrorLog({}, e)
                        console.log("Error in postMenu")
                        console.log("getInformation!");
                            if (r = !1, void 0 == n.data || null == n.data || "" == n.data || "undefined" == n.data || n.isOffline || (console.log("pageCount before::", t, s.infoPageCount), s.infoPageCount = t + 1, console.log("pageCount after::", t, s.infoPageCount)), n.isOffline && (s.knowOfflinePreviousIndex = s.knowList.length), s.pageSize = n.pageSize ? n.pageSize : 10, s.totalInfoCount = n.totalCount, n.totalCount > s.pageSize && (s.isInfiniteInfoEnabled = !0), s.unreadInfoCount = n.unreadInfoCount, o) if (n.isOffline) s.isKnowDataAvailable = !0, i.a.each(n.tasks, function (e) {
                            if (r = !1, void 0 == n.data || null == n.data || "" == n.data || "undefined" == n.data || n.isOffline || (console.log("pageCount before::", t, s.infoPageCount), s.infoPageCount = t + 1, console.log("pageCount after::", t, s.infoPageCount)), n.isOffline && (s.knowOfflinePreviousIndex = s.knowList.length), s.pageSize = n.pageSize ? n.pageSize : 10, s.totalInfoCount = n.totalCount, n.totalCount > s.pageSize && (s.isInfiniteInfoEnabled = !0), s.unreadInfoCount = n.unreadInfoCount, o) if (n.isOffline) s.isKnowDataAvailable = !0, i.a.each(n.tasks, function (e) {
                                console.log(e, s.knowList[0].id, e != s.knowList[0].id), e != s.knowList[0].id ? (s.StorageAccess.setValue("lastUnread", s.knowList[0].id), s.allRead = !1) : s.allRead = !0
                            e && (e.complete(), e = null), s.spinner = !1, s.spinnerFlag = !1, console.log("First dismiss"), setTimeout(function () {
                            console.log("Second dismiss"), setTimeout(function () {
                        console.log("previous login = ", l), "true" == l && null != l || (console.log("Inside if for setTimeout"), setTimeout(function () {
                        console.log("previous login = ", l), "true" == l && null != l || (console.log("Inside if for setTimeout"), setTimeout(function () {
                            console.log("Error in hub coachin creation nav::", e)
                                console.log("intiCoaching Response::" + JSON.stringify(e))
                                console.log("intiCoaching Error Response::" + JSON.stringify(e))
                            console.log("Error in searchEmployee::" + e)
                                console.log("initCallin Response::" + JSON.stringify(t)), e.resultData = t, e.dismissLoading(), e.navCtrl.push("CallLogDetails", {
                                console.log("initCallin Error Response::" + JSON.stringify(t)), e.dismissLoading(), e.ReusableUtils.showToast("pleaseTryAfterSometime")
                            console.log("Error in searchEmployee::" + e)
                                console.log("initMeetin Response::" + JSON.stringify(t)), e.resultData = t, e.dismissLoading(), e.navCtrl.push("MeetingLogDetails", {
                                console.log("initMeetin Error Response::" + JSON.stringify(t)), e.dismissLoading(), e.ReusableUtils.showToast("pleaseTryAfterSometime")
                            console.log("Error in searchEmployee::" + e)
                        console.log("setFlagFalse()"), e.hubProvider.setFirstLoginFalse().subscribe(function (t) {
                            t.success ? (e.StorageAccess.setValue("firstLoginFlagSet", "isSet"), e.StorageAccess.setValue("loginFirstLogin", !1), e.user.firstLogin = !1, e.StorageAccess.setValue("employeeInfo", e.user), e.StorageAccess.setValue("empInfo", JSON.stringify(e.user)), console.log("Updated firstLogin"), console.log(t)) : t.message && e.ReusableUtils.showHttpError(t.message)
                            t.success ? (e.StorageAccess.setValue("firstLoginFlagSet", "isSet"), e.StorageAccess.setValue("loginFirstLogin", !1), e.user.firstLogin = !1, e.StorageAccess.setValue("employeeInfo", e.user), e.StorageAccess.setValue("empInfo", JSON.stringify(e.user)), console.log("Updated firstLogin"), console.log(t)) : t.message && e.ReusableUtils.showHttpError(t.message)
                                        console.log("OK clicked")
                            console.log("unreadTaskCount =", t), e.unreadTaskCount = t
                            console.log(JSON.stringify(t)), e.ReusableUtils.saveErrorLog({}, t)
                            console.log(JSON.stringify(t)), e.ReusableUtils.saveErrorLog({}, t)
                            console.log("ComplaintPage::", t), e.StorageAccess.setValue("issueTypes", JSON.stringify(t)), e.nav.push("ComplaintPage", {
                            console.log(JSON.stringify(t)), e.StorageAccess.getValue("issueTypes").then(function (t) {
                    }), console.log("Hub loaded!");
                        console.log("***************************refreshEmployeeInfo event called!!!"), k.StorageAccess.getValue("employeeInfoChanged").then(function (e) {
                        console.log(parseInt(e), typeof e, e), k.uName = e.includes("@") ? e : "+" + e
                        console.log(e)
                        console.log("loginFirstLogin getValue::: ", e), console.log("loginFirstLogin is set false"), k.StorageAccess.getValue("firstLoginFlagSet").then(function (t) {
                        console.log("loginFirstLogin getValue::: ", e), console.log("loginFirstLogin is set false"), k.StorageAccess.getValue("firstLoginFlagSet").then(function (t) {
                            console.log("firstLoginFlagSet getValue::: ", t), ("isSet" != t || e) && (k.setFlagFalse(), k.translate.get("welcomeMessage").subscribe(function (e) {
                    return e = t.device.model, console.log("check", e), new Promise(function (n) {
                    console.log("Home Tab selected!! "), this.content.scrollToTop(500)
                            console.log("Info == ", e), n.user = JSON.parse(e), n.isLowRisk = !! n.user.designationCode && !! n.user.designationCode.includes("LOW_RISK"), n.formAnnouncement();
                    console.log("getTasks!");
                    if (r && !! r.includes("LOW_RISK") && !a.user.hasTeam && a.unreadTaskCount <= 0) return console.log("returning from task call due to condition"), a.unreadTaskCount = 0, a.doList = [], a.isDoDataAvailable = !1, setTimeout(function () {
                        console.log("Res AllTasks::", n), a.taskPageCount = t + 1, a.ToDoList = n, n.totalCount > a.pageSize && (a.isInfiniteTaskEnabled = !0), o ? (a.isDoDataAvailable = !0, i.a.each(n, function (e) {
                        if (console.log("Response = ", t), t) {
                    console.log("getUserData called::"), e && this.getEmployeeData(), this.getInformation(null, this.infoPageCount, this.pageSize, !1, !0)
                    console.log("refreshPage");
                    r ? (this.dismissLoading(), e && e.complete()) : (console.log("!firstLoad"), console.log("Entered HUB!!!!"), this.getUserBasicData( !! e), "know" == this.tasks ? (this.infoPageCount = 0, this.getInformation(null, this.infoPageCount, this.pageSize, !1), this.dismissLoading()) : (this.taskPageCount = 0, this.getTasks(null, this.taskPageCount, this.pageSize, !1), this.dismissLoading()), e && e.complete())
                    r ? (this.dismissLoading(), e && e.complete()) : (console.log("!firstLoad"), console.log("Entered HUB!!!!"), this.getUserBasicData( !! e), "know" == this.tasks ? (this.infoPageCount = 0, this.getInformation(null, this.infoPageCount, this.pageSize, !1), this.dismissLoading()) : (this.taskPageCount = 0, this.getTasks(null, this.taskPageCount, this.pageSize, !1), this.dismissLoading()), e && e.complete())
                    this.ReusableUtils.homeScreenScrolltop = this.content.scrollTop, console.log(this.content.scrollTop)
                    console.log("Inside Will Enter");
                        console.log("employeeInfoChanged::", t), t ? (e.StorageAccess.setValue("employeeInfoChanged", !1), console.log("getUserBasicData API::"), e.getUserBasicData(!0)) : (console.log("getUserBasicData local cache::"), e.getUserBasicData(null))
                        console.log("employeeInfoChanged::", t), t ? (e.StorageAccess.setValue("employeeInfoChanged", !1), console.log("getUserBasicData API::"), e.getUserBasicData(!0)) : (console.log("getUserBasicData local cache::"), e.getUserBasicData(null))
                        console.log("employeeInfoChanged::", t), t ? (e.StorageAccess.setValue("employeeInfoChanged", !1), console.log("getUserBasicData API::"), e.getUserBasicData(!0)) : (console.log("getUserBasicData local cache::"), e.getUserBasicData(null))
                    }), e.widgetLangUtils.createLabels(), e.StorageAccess.setValue("listCount", 0), r || (console.log("ionViewWillEnter"), e.updateReadCount(), "do" == e.tasks && e.refreshTasks()), setTimeout(function (t) {
                    console.log("Inside Did Load");
                    e.spinnerFlag = !0, console.log("ionViewDidLoad"), e.StorageAccess.setValue("isDirty", !1), e.getUserData(!0), e.StorageAccess.getValue("PUSHNOTIFICATION").then(function (t) {
                    console.log("presentLoading called", l.length);
                    console.log("Loading presentLoading", this.convertToTimeStamp(Date.now())), r && 0 == l.length && (l.push(c += 1), (s = this.ReusableUtils.presentLoadingCustom()).present())
                    console.log("loading called", l.length);
                    0 == l.length && (l.push(c += 1), console.log("Loading Loading", this.convertToTimeStamp(Date.now())), (s = this.ReusableUtils.presentLoadingCustom()).present())
                    console.log("dismissLoading called", l.length);
                    l.length >= 1 && (s.dismiss(), console.log("Dismissed loading", this.convertToTimeStamp(Date.now())), l.pop())
                    console.log("Info lazy loading");
                    if (console.log("Task lazy loading", this.doList.length), this.totalTaskCount > this.doList.length) {
                    console.log(e);
                    console.log("Keyboard close!"), this.keyboard.close(), this.allSubordinates = this.team, console.log(e)
                    console.log("Keyboard close!"), this.keyboard.close(), this.allSubordinates = this.team, console.log(e)
                    console.log("deleteAnnouncementThread:Home", e);
                                console.log("Cancel clicked")
                                console.log("Accept clicked"), t.network.checkInternetConnection() && t.deleteThread(e)
                        console.log("Error in postMenu")
                        console.log("Error in callPerson::", e)
                        console.log("Error in callPerson::", e)
                                console.log("Deleted entry successfully!")
                            }), console.log("check-in Success in home.ts:: ", JSON.stringify(e))
                        console.log(e)
                            console.log("Deleted entry successfully!")
                        }), console.log("complaintQue Success in home.ts:: ", JSON.stringify(e))
                            if (console.log("checkForUpdate()::\n", JSON.stringify(o)), o) {
                                                    console.log("OK clicked"), window.open(t, "_system", "location=yes")
                                    } else console.log("At the latest version!")
                    console.log("user designation code::", t.user.designationCode);
                    return console.log(o), o.length ? (n.employee.displayName = o[0].ownerName, n.employee.imageUrl = o[0].imageUrl, n.id = "FirstAnnouncementCard1", n.description = o[0].title, n.type = "ANNOUNCEMENT_NOTIFICATION", n.createdOn = (new Date).getTime(), n.isUnread = !1, n.isRemovable = !1, n.actionList = [], n.reference = {
                    console.log("link::", t), window.open(t, "_system", "location=yes")
                    console.log(t);
                    o = (o = "ms_MY" == this.translate.currentLang ? a.a.devLink.includes("https://covid-19malaysia.kpisoft.com") ? "https://covid-19malaysia.kpisoft.com/help" : "https://mysejahtera.malaysia.gov.my/help" : a.a.devLink.includes("https://covid-19malaysia.kpisoft.com") ? "https://covid-19malaysia.kpisoft.com/help_en" : "https://mysejahtera.malaysia.gov.my/help_en") + "?data=" + n, console.log("link::", o), window.open(o, "_system", "location=yes")
                        console.log("ScrollToElement event::"), setTimeout(function () {
                        console.log(parseInt(t), typeof t, t), e.uName = t.includes("@") ? t : "+" + t, e.StorageAccess.getValue("employeeInfoChanged").then(function (t) {
                            console.log("employeeInfoChanged::", t), t ? (e.StorageAccess.setValue("employeeInfoChanged", !1), console.log("getUserBasicData API::"), e.hubProvider.getEmployeeInfo().subscribe(function (t) {
                            console.log("employeeInfoChanged::", t), t ? (e.StorageAccess.setValue("employeeInfoChanged", !1), console.log("getUserBasicData API::"), e.hubProvider.getEmployeeInfo().subscribe(function (t) {
                    n.formType = e.empInfo.designationCode ? "location" in e.empInfo && null != e.empInfo.location ? null : "LOCATION_ASSESSMENT" : "DAY0_REGULAR_ASSESSMENT", console.log("EMPLOYEE DATA::"), console.log(e.empInfo), console.log(":::close:::", e.empInfo.designationCode, e.empInfo.location), (e.empInfo.designationCode || t) && "location" in e.empInfo && null != e.empInfo.location ? e.empInfo.employeeId ? e.nav.push("TabsPage", {
                    n.formType = e.empInfo.designationCode ? "location" in e.empInfo && null != e.empInfo.location ? null : "LOCATION_ASSESSMENT" : "DAY0_REGULAR_ASSESSMENT", console.log("EMPLOYEE DATA::"), console.log(e.empInfo), console.log(":::close:::", e.empInfo.designationCode, e.empInfo.location), (e.empInfo.designationCode || t) && "location" in e.empInfo && null != e.empInfo.location ? e.empInfo.employeeId ? e.nav.push("TabsPage", {
                    n.formType = e.empInfo.designationCode ? "location" in e.empInfo && null != e.empInfo.location ? null : "LOCATION_ASSESSMENT" : "DAY0_REGULAR_ASSESSMENT", console.log("EMPLOYEE DATA::"), console.log(e.empInfo), console.log(":::close:::", e.empInfo.designationCode, e.empInfo.location), (e.empInfo.designationCode || t) && "location" in e.empInfo && null != e.empInfo.location ? e.empInfo.employeeId ? e.nav.push("TabsPage", {
                                console.log("Data =", t);
                                    console.log("Names = ", n)
                    console.log(o);
                            console.log("Location is " + (o ? "enabled" : "disabled")), o ? (n.popFlag = !1, n.loginProvider.saveLog({
                                }), o.cancelled) console.log("cancelled!");
                                    o.text.includes("formType=TRAVELLER") && (n.StorageAccess.setValue("isTraveller", !0), n.StorageAccess.setValue("employeeInfoChanged", !0)), console.log("Barcode data", o);
                                    console.log("Url = ", a), window.open(a, "_system", "location=yes")
                                } else console.log(o.text), n.nav.push("ScanQRCodePage", {
                                }), console.log("Error", e)
                                console.log("Authorization status is now: " + e)
                                console.log("Authorization status is now: " + e), "denied" == e && n.StorageAccess.getValue("iOSCount").then(function (e) {
                                        console.log("Clicked on settings")
                                    console.log("Error ==", e)
                        }), console.log("try catch::", e)
                        console.log(parseInt(t), typeof t, t), e.uName = t.includes("@") ? t : "+" + t, e.StorageAccess.getValue("employeeInfoChanged").then(function (t) {
                            console.log("employeeInfoChanged::", t), t ? (e.StorageAccess.setValue("employeeInfoChanged", !1), console.log("getUserBasicData API::"), e.hubProvider.getEmployeeInfo().subscribe(function (t) {
                            console.log("employeeInfoChanged::", t), t ? (e.StorageAccess.setValue("employeeInfoChanged", !1), console.log("getUserBasicData API::"), e.hubProvider.getEmployeeInfo().subscribe(function (t) {
                                console.log("Data =", t);
                                    console.log("Names = ", n)
                            console.log("Location is " + (i ? "enabled" : "disabled")), i ? (n.popFlag = !1, n.barcodeScanner.scan({
                                if (i.cancelled) console.log("cancelled!");
                                    i.text.includes("formType=TRAVELLER") && (n.StorageAccess.setValue("isTraveller", !0), n.StorageAccess.setValue("employeeInfoChanged", !0)), console.log("Barcode data", i);
                                    console.log("Url = ", a), window.open(a, "_system", "location=yes")
                                } else console.log("barcodeData::", i.text), n.nav.push("ScanQRCodePage", {
                                console.log("Error", e)
                                console.log("Authorization status is now: " + e)
                                console.log("Authorization status is now: " + e), "denied" == e && n.StorageAccess.getValue("iOSCount").then(function (e) {
                                        console.log("Clicked on settings")
                                    console.log("Error ==", e)
                        console.log("try catch::", e)

We can also see some the external url/link used by the app. Seems the app is built by kpisoft.

               }, e.prototype.locateHotSpot = function () {
                    this.nav.push("LocateHotSpot")
                }, e.prototype.onlineHealthClinic = function () {
                    this.nav.push("digitalHealthCarePage")
                }, e.prototype.locateHospital = function () {
                    this.nav.push("LocateHospital")
                }, e.prototype.openSOPDocs = function () {
                    var e = a.a.devLink.includes("https://covid-19malaysia.kpisoft.com") ? "/cdc" : "/register",
                    	t = a.a.devLink + e + "/sop";
                    console.log("link::", t), window.open(t, "_system", "location=yes")
                }, e.prototype.helpDesk = function () {
                    var e = {
                        userName: this.uName,
                        appVersion: this.AppVersionNumber,
                        deviceModel: this.deviceName,
                        userStatus: this.user.designationCode.includes("LOW") ? "Low" : "High",
                        email: this.user.email
                    },
                    	t = JSON.stringify(e);
                    console.log(t);
                    var n = window.btoa(t),
                    	o = "";
                    o = (o = "ms_MY" == this.translate.currentLang ? a.a.devLink.includes("https://covid-19malaysia.kpisoft.com") ? "https://covid-19malaysia.kpisoft.com/help" : "https://mysejahtera.malaysia.gov.my/help" : a.a.devLink.includes("https://covid-19malaysia.kpisoft.com") ? "https://covid-19malaysia.kpisoft.com/help_en" : "https://mysejahtera.malaysia.gov.my/help_en") + "?data=" + n, console.log("link::", o), window.open(o, "_system", "location=yes")
                }, e.prototype.navigateToVaccinePage = function () {
                    this.nav.push("VaccinationPage")

if you go to /register. For Seasonal tester , you will immidietely notice the 2 bugs . This is a common findings that we usually found across enterprise app. Happy hunting!!

Do you see the 2 bugs yet?