Static React/CRA marketing page for alist.ae — pushes visitors to an external registration form. No backend, no forms, no API calls.
.env, and no .htaccess anywhere in the repo.<a href> links to https://business.alist.ae/forms/registration-form. All lead capture, validation, and persistence happen in a separate repository.react-scripts 5.0.1 is unmaintained, TS is 4.9, and CRA itself is deprecated. npm audit will return a long list of transitive dev-dep CVEs typical of any unmigrated CRA project.CustomImage component is over-engineered (~220 lines, ~30 props for desktop/medium/mobile/small width × height × spinner × margin variants). It is the single largest piece of complexity in the codebase.| Category | Technology | Version | Notes |
|---|---|---|---|
| UI framework | React + ReactDOM | ^18.3.1 | StrictMode, no concurrent features used |
| Language | TypeScript | ^4.9.5 | strict: true, target: es5, jsx: react-jsx |
| Build tool | react-scripts (CRA) | 5.0.1 | Not ejected. CRA is deprecated upstream. |
| Fonts | @fontsource/poppins | ^5.0.14 | Weights 300, 400, 700 |
| Image loading | blurhash + react-blurhash | ^2.0.5 / ^0.3.0 | Imported but not used by CustomImage (it rolls its own spinner). Dead deps. |
| Testing | @testing-library/react, jest-dom | ^13.4 / ^5.17 | Only the default CRA smoke test exists. |
| Perf telemetry | web-vitals | ^2.1.4 | reportWebVitals() called with no callback — no-op. |
| Dev workaround | ajv | ^7.2.4 (devDep) | Pinned to fix a CRA build break; do not remove blindly. |
| Server / DB / Auth | — | — | None. Pure static SPA. |
Single-page, single-route React app. index.tsx mounts <App/>, which renders one <Page/> that stacks a hero, mobile-only emoji decorations, five "about" sections, and a footer. All CTAs are external links — nothing here calls an API.
Full-surface security review of the tryalist static SPA covering source code, dependency tree, build/dev toolchain, git history, and deployment posture. Every finding below is verified against package.json, package-lock.json, and the committed source; secret, injection, crypto, storage, and network dimensions were each grepped to a clean zero. Findings are mapped to industry frameworks and scored with CVSS 3.1 (environmentally adjusted for this repo's actual build-time-only reachability).
sca-dependency-audit · secrets-and-credential-scan · injection-and-xss-review · security-headers-and-csp · supply-chain-and-cicd-integrity · client-storage-and-crypto-review · source-map-and-build-artifact-review
tryalist is a static Create React App marketing single-page site for alist.ae with no backend, no forms, no API/network calls, no client-side storage, no crypto, and no secrets in source or git history (all verified by grep and the full git-history scan). The entire realistic attack surface is the build/dev toolchain: react-scripts 5.0.1 is deprecated and unmaintained, freezing a web of vulnerable transitive dependencies (nth-check ReDoS, webpack-dev-server source disclosure, postcss/cross-spawn/serialize-javascript) that cannot be patched in place because the project defines no overrides. Critically, none of these vulnerable packages ship to the production static bundle — they execute only at build/dev time — so the worst credible outcome is a build-time denial-of-service on a CI runner or developer machine, or disclosure of already-public marketing source via the dev server. Defense-in-depth gaps (no CSP/anti-framing headers, default-on source maps) and a governance gap (no CI/CD or automated SCA) raise the long-term regression risk but present no exploitable runtime path today. Overall risk is medium, driven entirely by the unmaintained-toolchain governance posture rather than any shipped, attacker-reachable runtime vulnerability.
| Category | Status | Notes |
|---|---|---|
| A01:2021 Broken Access Control | N/A | No server, no auth, no protected resources — static SPA with no access-control surface. |
| A02:2021 Cryptographic Failures | Clean | No crypto, no secrets, no PII, no tokens shipped to the browser (env/key/storage/crypto greps all 0; git history clean). |
| A03:2021 Injection | Clean | No injection sinks: no dangerouslySetInnerHTML, no fetch/axios/XHR, no eval, no user input; image style props are numeric/string dimensions from webpack-imported assets. |
| A04:2021 Insecure Design | N/A | Trivial single-page brochure; no security-relevant design decisions (lead capture lives in the separate business.alist.ae repo). |
| A05:2021 Security Misconfiguration | Partial | No CSP/anti-framing headers (T-06) and default-on source maps (T-07) — defense-in-depth gaps only; no exploitable misconfiguration today. |
| A06:2021 Vulnerable & Outdated Components | Vulnerable | Deprecated CRA 5.0.1 toolchain (T-01) freezing build-time-only vulnerable transitives (T-02 nth-check, T-03 webpack-dev-server, T-04 postcss/cross-spawn/serialize-javascript); no SCA gate (T-05). |
| A07:2021 Identification & Authentication Failures | N/A | No authentication anywhere in the repo. |
| A08:2021 Software & Data Integrity Failures | Partial | No CI lockfile-integrity check, no SBOM, no signed/provenance build (T-05); deploy is manual. No insecure deserialization in app code. |
| A09:2021 Security Logging & Monitoring Failures | N/A | No server-side component to log; static SPA with no telemetry beyond a no-op reportWebVitals. |
| A10:2021 Server-Side Request Forgery | N/A | No server and no outbound request construction from user input. |
The repo's entire build/test/dev pipeline depends on react-scripts 5.0.1, the final release of the now-deprecated and unmaintained Create React App. CRA hard-pins a large web of transitive build dependencies (svgo 1.x, css-select 2.x, nth-check 1.x, postcss 7.x via resolve-url-loader, webpack-dev-server 4.x, rollup-plugin-terser, etc.) and will receive no further security patches. Because the project defines no overrides block, the vulnerable transitives documented in T-02/T-03/T-04 cannot be remediated through normal npm update; they are frozen at the versions CRA last shipped. This is the umbrella/root-cause finding that makes every other dependency CVE in this report unfixable-in-place.
npm run build/start. Because there is no patch channel for CRA, the window stays open indefinitely.Build/dev-time risk only — nothing in this toolchain ships to the production static bundle (npm run build output is plain hashed JS/CSS/assets). Over time the build host and developer workstations accumulate known-vulnerable build/dev tooling with no patch channel, raising the chance a future CI runner or dev build hits a denial-of-service or, worst case, a tooling RCE when processing project assets. The governance consequence is that all transitive CVEs here are stuck until the toolchain is migrated.
vite-plugin-svgr for SVGs). As an interim measure, add an overrides block to package.json forcing the specific vulnerable transitives (nth-check>=2.1.1, postcss>=8.4.31, webpack-dev-server>=5.2.1, cross-spawn>=7.0.5, serialize-javascript>=6.0.2), then npm install + npm run build to validate. Add automated SCA (npm audit / Dependabot) per T-05 so future drift is caught.Confirmed against package.json and package-lock.json. Merged the scanner's P2 'EOL toolchain' finding with the prior audit's P1 'Build tooling deprecated' (same root issue). Kept at P2: the prior P1 over-rated it because the impact is strictly build/dev-time for a static marketing site with no shipped runtime exposure.
nth-check before 2.0.1 contains an inefficient regular expression enabling Regular Expression Denial of Service. It is the canonical high-severity finding from npm audit on a default CRA 5.0.1 install, reachable through the SVG-optimization branch (svgo 1.3.2 → css-select 2.1.0 → nth-check 1.0.2) that @svgr/webpack uses when CRA imports SVGs as React components.
Build-time denial-of-service only. svgo runs at build time over SVG assets in the source tree; there is no runtime path feeding untrusted CSS selectors to nth-check (the production bundle contains no svgo/nth-check code). The repo currently uses static SVG assets, so practical exploitability requires a malicious SVG to be introduced into the asset pipeline.
"overrides": { "nth-check": "^2.1.1" }), then reinstall and rebuild to confirm SVG handling still works. Durable fix: migrate off CRA/@svgr 5.x to maintained SVG tooling (Vite + vite-plugin-svgr). Treat untrusted SVGs entering the repo as a code-review gate.Lockfile path verified exactly. CVSS down-adjusted from the scanner's 7.5 network-exploit base to a local/build-time environmental vector (AV:L, UI:R) because the vulnerable code is build-only and the input is not attacker-controlled at runtime; net 5.3, still P2 as the highest-reachability dep issue.
webpack-dev-server before 5.2.1 performs non-strict origin checks on its dev-server WebSocket/HTTP endpoints, allowing a malicious website a developer visits in the same browser to connect to the running dev server and exfiltrate bundled application source (CVE-2025-30359 via the websocket handshake; CVE-2025-30360 for non-allowed origins).
react-scripts start and, in the same browser profile, visits an attacker-controlled page; that page connects to the local dev server's WebSocket and reads the bundled source. For this repo the exfiltrated source is non-sensitive marketing code.Dev-time only — webpack-dev-server never deploys to production; the shipped artifact is the static npm run build output. The only data leakable is this app's source, which is a public-facing marketing page with no secrets, tokens, or user data (confirmed clean by the secrets-dimension review). Impact is therefore minimal even when triggered.
Version verified. CVSS lowered from scanner's 6.3 to 4.3 (C:H->C:L) because the disclosed asset is confirmed-non-sensitive public marketing source; severity P3 given dev-time-only reach plus zero secret exposure.
Three additional vulnerable transitives are frozen inside the deprecated CRA build tooling (T-01): an EOL postcss 7.0.39 copy carried privately by resolve-url-loader 4.0.0 (CVE-2023-44270 line-break parsing), cross-spawn 7.0.3 (CVE-2024-21538 ReDoS), and a serialize-javascript 4.0.0 copy under the deprecated rollup-plugin-terser (CVE-2024-11831 XSS). In every case the modern top-level copy is already patched; only the loader-/plugin-private legacy copies are affected.
Build/minification-time processing of the project's own CSS/JS only — none of these parse attacker-controlled input in this repo, and none execute in the shipped production bundle. postcss 7.x parses the project's own CSS; cross-spawn parses static build/test commands; serialize-javascript serializes the project's own build artifacts (it produces no HTML rendered to end users). Practical exploitability is near zero; tracked for EOL/deprecated-component hygiene.
postcss>=8.4.31, cross-spawn>=7.0.5, serialize-javascript>=6.0.2, then reinstall and run the build to confirm; or remove resolve-url-loader if no SCSS url() rewriting is needed. All three disappear cleanly once the project migrates off CRA's bundled loader/plugin stack (T-01).All three lockfile paths/versions verified exactly. Consolidated three separate low-severity scanner findings into one canonical entry: identical class (build-only transitive, non-exploitable here), identical remediation (overrides / CRA migration). CVSS reflects the postcss CVE-2023-44270 base; kept P3 to avoid finding-count inflation on non-reachable issues.
There is no CI/CD configuration of any kind. Consequently there is no automated software-composition-analysis gate (npm audit / Dependabot / Snyk) to catch the vulnerable transitives in T-01..T-04, no reproducible build pipeline, no enforced lockfile-integrity check, and no SBOM. Builds and deploys are manual ('tribal knowledge'), weakening supply-chain integrity guarantees.
Governance/process gap, not a directly exploitable flaw (CVSS base 0.0). The practical consequence is that dependency drift and newly disclosed CVEs go undetected, and the absence of a controlled build/deploy pipeline means no automated checkpoint prevents a poisoned dependency or tampered build artifact from reaching the static host serving alist.ae.
npm ci (lockfile integrity), npm audit --audit-level=high, and a Dependabot/Snyk SCA scan on every push/PR, plus the production build. Enable Dependabot/Renovate for automated dependency-update PRs, document the deploy target, pin the Node version, generate and store an SBOM (syft), and pin any third-party CI actions to commit SHAs.Absence of all CI/host config confirmed by full repo listing. CVSS 0.0 retained — this is a process gap with no in-repo attack vector; kept P3 for tracking.
The app ships no Content-Security-Policy and no framing/clickjacking protection. There is no server in this repo and no host-level header config tracked, so unless the static host (alist.ae) injects headers out-of-band, the deployed page runs with browser defaults (no CSP, framable). The current React source has no HTML-injection sink (no dangerouslySetInnerHTML, no fetch, no user input — all verified), so this is purely defense-in-depth.
Defense-in-depth only. No script-execution or framing attack is possible from the current code. A CSP and X-Content-Type-Options/Referrer-Policy would harden the page against future regressions (an added injection sink, a compromised third-party script) and against clickjacking/UI-redress. Low real-world impact for a static brochure with no auth, cookies, or user data.
Content-Security-Policy: default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none', plus X-Content-Type-Options: nosniff and Referrer-Policy: strict-origin-when-cross-origin. CRA inlines a small runtime bootstrap script, so a hash/nonce or an 'unsafe-inline' fallback for script-src may be needed — validate the build before enforcing. A <meta http-equiv> CSP in public/index.html is a fallback if host headers are unavailable.Confirmed: no CSP/headers anywhere, and confirmed there is no injection sink in src (no dangerouslySetInnerHTML, no user input, all external links use rel=noreferrer). Strictly hardening; P3.
Create React App 5.0.1 emits *.js.map source maps in the production build by default because the repo never sets GENERATE_SOURCEMAP=false. Source maps reconstruct the original TypeScript/JSX, including comments. The current source contains no secrets, so today the only exposure is original code and module structure. The finding is a hardening / defense-in-depth concern: this is exactly the path by which a future REACT_APP_* key, analytics token, or inline credential would leak verbatim into a publicly fetchable .map file.
Low today (no secrets in source). Discloses original module structure and developer comments to aid reconnaissance. If any secret is ever introduced into this front-end, it would be exposed in plaintext via the deployed source map with zero additional attacker effort (fetch app.js.map).
cross-env GENERATE_SOURCEMAP=false react-scripts build), or configure the static host not to serve *.map files publicly. Add a gitleaks pre-commit hook + CI secret-scan gate (ties into T-05) so a future secret can never reach the bundle/source map.GENERATE_SOURCEMAP override absent (verified). Confidence 'likely' — whether .map files are actually deployed depends on the un-committed host config, which we cannot inspect from the repo; the build default is the basis.
overrides block forcing nth-check>=2.1.1, postcss>=8.4.31, cross-spawn>=7.0.5, serialize-javascript>=6.0.2 (T-01, T-02, T-04), then npm install + npm run build to validate SVG/CSS handling.GENERATE_SOURCEMAP=false for production builds, or stop serving *.map on the host (T-07).react-scripts start runs (T-03 interim).npm ci, npm audit --audit-level=high, and the production build on every push/PR (T-05).gitleaks pre-commit hook + CI secret-scan gate so a future secret can never reach the bundle or source map (T-07).vite-plugin-svgr for SVGs. This drops T-01..T-04 cleanly and yields an unaffected dev server, fully resolving T-03 (webpack-dev-server >=5.2.1 / Vite).syft) and pin any third-party CI actions to commit SHAs (T-05).Content-Security-Policy (with frame-ancestors 'none'), X-Content-Type-Options: nosniff, and Referrer-Policy: strict-origin-when-cross-origin; validate the build before enforcing CSP given CRA's inline bootstrap script (T-06).customImage.tsx is the only file above ~100 lines. Everything else is small and readable.src/App.css; unused blurhash / react-blurhash deps; reportWebVitals() called with no callback; placeholder alt="..." strings throughout.any/@ts-ignore. Type usage is honest if light.styles.css + global utility classes in src/index.css. Naming is loose (.margin-60, .margin-bottom-ipad) and there is no design-token layer — risk of magic-number drift if the site grows.@types/node pinned to 16 — fine for typing only, but signals neglect.react-app eslint config is in place; no project-specific rules. No prettier config.main.git clone <bitbucket-url> tryalist
cd tryalist
npm install
npm start # http://localhost:3000
npm run build # outputs build/ for static hosting
https://business.alist.ae/forms/registration-form in a new tab; that page lives in a different repo.No deploy config is committed. The build/ output is a fully static SPA (single index.html + hashed JS/CSS/asset bundles), so any static host works — S3+CloudFront, Netlify, Vercel, Cloudflare Pages, or even nginx. Confirm with the team where tryalist.alist.ae (or wherever this is served) currently points. The index.html hard-codes og:url to https://www.alist.ae/, hinting at the production target.
business.alist.ae). Lead capture changes must be made there.home/index.tsx:62 and about-section2/index.tsx:28).useWindowSize.ts and customImage.tsx.public/logo/ and are referenced by literal /logo/* paths, so they bypass webpack hashing. Cache-busting them requires a filename change.src/App.css is imported by App.tsx. Delete the file and the import together.devDependencies.ajv is a pinned CRA peer-dep workaround. Removing it can break npm run build on fresh installs.tryalist ≠ package name react-creator. Rename when you next touch package.json.