Skip to content

[BUG] SPA routing is broken: two page components are used without being imported, four route keys are duplicated, and 14 security consoles are unreachable #575

Description

@MOHITKOURAV01

Description

The SPA "router" is a switch in src/routes/AppRoutes.jsx fed by a routeMap object in
src/App.jsx. The two have drifted out of sync. Two page components are rendered without ever being
imported, four route keys are declared twice (so the second declaration is dead), and 14 security
consoles that exist as page components are unreachable from any URL.

Problem 1: two components are used but never imported

case "keyvault-security":
case "keyvault":
  return ProtectedRoute(KeyVaultSecurityPage);   // never imported
...
case "microsegmentation":
  return ProtectedRoute(MicrosegmentationPage);  // never imported

AppRoutes.jsx imports SecurityKeyVaultPage (from ../pages/auth/SecurityKeyVaultPage) but
renders KeyVaultSecurityPage. MicrosegmentationPage is not imported under any name.

At runtime this is an uncaught ReferenceError that the ErrorBoundary turns into a blank screen
the moment a user navigates to /keyvault or /microsegmentation.

Correction to an earlier version of this issue: I first wrote that these are no-undef ESLint
errors that fail npm run build. They are not, and the reason is itself part of the problem:
package.json has no eslintConfig field. react-scripts therefore runs its ESLint plugin with
only eslint-config-react-app/base as the base config, and never loads the full react-app ruleset
where no-undef, no-dupe-keys and no-duplicate-case are set to error. I verified this by
building the branch with both components still undefined:

$ CI=true npm run build
Compiled successfully.

So none of the four defects below are currently caught by anything. Restoring the eslintConfig
field is part of the fix.

Problem 2: duplicate case labels — dead branches

$ duplicate case labels in AppRoutes.jsx: ["keyvault-security", "microsegmentation"]
  • case "keyvault-security": appears twice inside the same group:
    case "keyvault-security":
    case "keyvault":
    case "keyvault-security":     // dead
      return ProtectedRoute(KeyVaultSecurityPage);
  • case "microsegmentation": appears once under the ZTNA group (line ~176) and again under the
    SDP group (line ~198). The first wins, so MicrosegmentationPage is unreachable and
    /microsegmentation silently renders ZeroTrustNetworkPage instead.

no-duplicate-case is part of eslint:recommended, which react-app extends.

Problem 3: duplicate keys in routeMap (src/App.jsx)

$ duplicate routeMap keys: ["help", "microsegmentation"]
help: "help",                       // line 74
...
microsegmentation: "ztna",          // line 106
...
help: "help",                       // line 115  (silently overwrites)
...
microsegmentation: "microsegmentation",  // line 119 (silently overwrites line 106)

The two microsegmentation entries disagree about the target page. In an object literal the last
wins, so /microsegmentation maps to "microsegmentation" — which then hits the dead case from
Problem 2. no-dupe-keys is also an eslint:recommended error.

Problem 4: 14 security consoles are unreachable

These page components exist under src/pages/auth/ and have no case in AppRoutes.jsx and no
routeMap entry in App.jsx:

CspmPage, SbomPage, SoarPage, SecurityPosturePage, SecurityGovernancePage,
SecurityObservabilityPage, SecurityPlaybookPage, SecurityThreatPage,
SecurityVulnerabilityPage, SamlIdentityProviderPage, ThreatIntelligencePage,
ComplianceEvidencePage, ComplianceReportingPage, IncidentResponsePlaybookPage

SecurityPosturePage is even imported by AppRoutes.jsx and then never referenced (no-unused-vars).

Problem 5: UnauthorizedPage never receives its message

const UnauthorizedPage = ({ onNavigate, message }) => ( ... {message || "Your account role is ..."} )

ProtectedRoute calls <UnauthorizedPage onNavigate={onNavigate} /> with no message, so the prop
is dead code and every denial shows the same generic string.

Root Cause

Route information is duplicated in three places — the routeMap object, the switch statement, and
the import list — with nothing keeping them consistent. Every subsystem PR has to edit all three, and
the drift above is the accumulated result.

Expected Result

  • /keyvault, /keyvault-security, /key-vault render the key-vault console.
  • /microsegmentation, /sdp, /perimeter-security render MicrosegmentationPage;
    /ztna, /network-access render ZeroTrustNetworkPage.
  • Every page component under src/pages/auth/ is reachable by at least one URL.
  • npm run build emits no no-undef, no-duplicate-case, no-dupe-keys or no-unused-vars errors.

Proposed Fix

  • Introduce src/routes/routeRegistry.js as the single source of truth: one entry per page holding
    its canonical slug, URL aliases, component, allowed roles and layout flag.
  • Derive both the routeMap in App.jsx and the resolution logic in AppRoutes.jsx from that
    registry, replacing the switch and deleting the duplicated import list.
  • Register the 14 orphaned consoles.
  • Pass a specific message into UnauthorizedPage naming the roles that may access the route.
  • Add routeRegistry.test.js asserting: no duplicate slug or alias across the registry, every
    registered component is defined (not undefined), and every *Page.jsx under src/pages/auth/
    appears in the registry — so orphaned pages and undefined components fail the build instead of
    the browser.

Labels

bug, frontend

Metadata

Metadata

Assignees

Labels

ECSoC26ECSoC 2026 InitiativeFrontendFrontend related changesbugSomething isn't workingenhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions