← All repos

creators-website

Single-page React/TypeScript marketing site for Creators.ae. Email capture posts directly to monday.com from the browser — with a live me:write API token shipped in the JS bundle.

Primary stackCreate React App + TypeScript Last commit2026-01-06 Repo size11 MB Files64 Branchmaster Health Critical

Executive summary

Tech stack

React 18.3 TypeScript 4.9 (strict) Create React App 5 CSS Modules @fontsource/poppins monday.com GraphQL Node tooling: dotenv, ajv
CategoryTechnologyVersionNotes
FrameworkCreate React App (react-scripts)^5.0.1No Vite/Next; REACT_APP_* envs are inlined into bundle.
LanguageTypeScript^4.9.5strict: true, target ES5, jsx react-jsx.
UI libraryReact + React DOM^18.3.1Concurrent root via createRoot.
StylingCSS Modules + global CSSPer-component *.module.css; global in src/index.css.
Tailwind(referenced but not installed)@tailwind directives in index.css — no package, no config. Silently dropped.
Fonts@fontsource/poppins, custom Greycliff (woff)^5.0.14Greycliff files live in public/font/.
RoutingNone. Single page; scroll-to-section via refs.
Datamonday.com GraphQL APIv2Single mutation: create_item on a hard-coded board.
TestingJest + React Testing LibraryCRA defaultsOne test, broken (default placeholder).
Lint/formateslint-config-react-app onlyNo Prettier, no extra rules, no CI.

Architecture

Single-page Create React App. index.tsx mounts <App/> which renders <Page/>. Page owns three refs (home/about/notified) which it passes into the navbar so each nav link can scrollIntoView the corresponding section. The email form section calls monday.com's GraphQL endpoint directly from the browser using the token shipped in the bundle. There is no server, no router, no DB.

creators-website/ ├── .env committed; contains monday.com JWT (P0) ├── package.json CRA + React 18 + TS 4.9 ├── tsconfig.json strict, ES5, react-jsx ├── public/ │ ├── index.html CRA template, sets <title>creators.ae</title> │ ├── powder.jpg, powder2.jpg 1.8 MB + 2.0 MB hero images │ ├── creators_loading.gif 549 KB splash GIF │ ├── cards-icons/, font/, footer-social-icons/ │ └── manifest.json, favicon.ico └── src/ ├── index.tsx ReactDOM.createRoot + StrictMode ├── App.tsx Renders <Page/> ├── App.test.tsx Broken default CRA test ├── page/page.tsx Splash + scroll listener + sections ├── index.css Global; has unused @tailwind directives └── ui/ ├── home/ Hero title + navbar ├── about/ 3 feature cards ├── notified/ Email form → monday.com (P0/P1 risks) └── footer/ Titles, socials, Metasphere signature

Security assessment

This assessment was conducted as a white-box static source review of the full repository, git history, and the locked dependency tree, grounded in the anthropic-cybersecurity-skills playbooks (which encode OWASP WSTG, OWASP API Top 10, and MASVS methodology). Findings were produced by parallel per-dimension scanners — client-side secrets, XSS/client injection, client auth/token handling, supply chain/CI-CD, and misconfiguration/headers — then deduplicated and adversarially verified against the actual code, decoded JWTs, and the package-lock.json. Every finding below is rated with CWE, CVSS 3.1, and OWASP Top 10 2021 mappings.

OWASP Top 10 2021 OWASP WSTG OWASP API Top 10 2023 OWASP MASVS (mobile only) CWE CVSS 3.1 NIST CSF 2.0
Playbooks applied for this repo (frontend JS dimensions):
Client-side secret & data exposure — implementing-secret-scanning-with-gitleaks, testing-for-sensitive-data-exposure, performing-cryptographic-audit-of-application
XSS & client-side injection — testing-for-xss-vulnerabilities, exploiting-prototype-pollution-in-javascript, testing-for-open-redirect-vulnerabilities
Auth & token handling (client) — testing-jwt-token-security, testing-api-authentication-weaknesses, testing-oauth2-implementation-flaws
Dependencies, supply chain & CI/CD — performing-sca-dependency-scanning-with-snyk, analyzing-sbom-for-supply-chain-vulnerabilities, detecting-supply-chain-attacks-in-ci-cd, prioritizing-vulnerabilities-with-cvss-scoring
Misconfiguration, CORS & headers — testing-cors-misconfiguration, testing-for-host-header-injection

Risk narrative

This single-page Create React App marketing site for creators.ae ships a live monday.com personal API JWT (per:"me:write", account 5465124) two ways at once: it is committed in a git-tracked .env and, because of the CRA REACT_APP_ prefix, it is also string-substituted into the production JS bundle and sent verbatim as the Authorization header from every visitor's browser to api.monday.com. Any visitor or anyone who can read the repo obtains a full account-write credential, and git history retains a second, previously-rotated me:write token (uid 50058541) that a "rotation" never revoked — so deleting the file does nothing. The same email form builds its GraphQL create_item mutation by string-concatenating the user-supplied email into the query before a permissive (quote-allowing) regex even runs, giving a client-side GraphQL injection that, combined with the public token, lets an attacker run arbitrary token-authorized mutations (delete_item, change_column_value, reads) directly against the workspace with no rate limit, CAPTCHA, or server boundary. There is no CI/CD, branch protection, or secret scanning, and changes are committed straight to master via the Bitbucket web editor of an external personal org (ParhamandCo), so the path from arbitrary edit to production has no integrity gate. The build toolchain is end-of-life (react-scripts 5.0.1) and freezes a transitive tree with multiple published CVEs, though those are predominantly build/dev-time rather than reachable against the static production artifact.

Overall risk Critical
2 P0 2 P1 2 P2 2 P3

OWASP coverage

CategoryStatusNote
A01:2021 Broken Access Control N/A No backend, no auth, no server-side access control surface in this static SPA; the form posts to monday.com via a client-held token (access-control failure manifests as the leaked credential, tracked under A02).
A02:2021 Cryptographic Failures Vulnerable Live monday.com me:write JWT committed in .env, inlined into the public bundle, and retained in git history (CW-01, CW-02).
A03:2021 Injection Vulnerable GraphQL injection: user email string-concatenated into the create_item mutation before client-only validation (CW-03).
A04:2021 Insecure Design Partial Architecturally insecure: a write-capable token in the browser with no server boundary, no rate-limit/CAPTCHA/CSRF on the only form; the proper design is a server-side proxy (remediation in CW-01/CW-03).
A05:2021 Security Misconfiguration Vulnerable Default-on production source maps (CW-06) and no CSP/security headers (CW-09); also the .gitignore that fails to exclude .env (CW-01).
A06:2021 Vulnerable and Outdated Components Vulnerable EOL CRA 5 toolchain (CW-04), nth-check ReDoS CVE-2021-3803 (CW-07), broad build/dev CVE cluster (CW-08), and no SCA/update automation (CW-10).
A07:2021 Identification and Authentication Failures N/A No user authentication system in the repo (no login, sessions, or password handling).
A08:2021 Software and Data Integrity Failures Vulnerable No CI/CD, no branch protection, direct-to-master web-editor commits on an external personal org, no npm ci/lockfile enforcement (CW-05).
A09:2021 Security Logging and Monitoring Failures Partial No logging/monitoring of form abuse or token misuse; client-side only console.error. Low relevance for a static marketing site but worth noting once a proxy exists.
A10:2021 Server-Side Request Forgery (SSRF) N/A No server-side request construction from user input; the single outbound fetch target (api.monday.com) is hard-coded.

Detailed findings

P0 — Critical P1 — High P2 — Medium P3 — Low / Info
CW-01

Live monday.com me:write API JWT committed in .env and inlined into the public JS bundle

P0 OWASP A02:2021 / A05:2021 CWE-798 CVSS 9.1 EPSS n/a confirmed
Description

The repo commits a real monday.com personal API token (HS256 JWT) in a git-tracked .env that .gitignore does not exclude. The decoded payload confirms a live, non-expiring per:"me:write" token scoped to monday.com account actid=5465124 (user uid=12149628). Because this is Create React App, every REACT_APP_* variable is statically substituted into the compiled JS at build time, so the token is (a) readable by anyone who clones/browses the repo and (b) shipped to and readable by every site visitor via View-Source/DevTools, where it is sent verbatim as the Authorization header to api.monday.com. A me:write token carries the full write capability of the issuing user across the account — enumerate/modify/delete board items, read items (including PII captured by the form), pull account users, and abuse API quota. There is no expiry claim, so it stays valid until manually revoked. This is one canonical issue consolidated from three scanner reports (client_secrets x2 and supply_chain_fe).

Evidence
/Users/2dot4/Projects/alist-projects/creators-website/.env:1 REACT_APP_API_KEY=eyJhbGciOiJIUzI1NiJ9.eyJ0aWQiOjM3NTU0ODkx... decoded payload {tid:37554891, uid:12149628, per:"me:write", actid:5465124, rgn:"use1", iad:2020-02-13} — verified by base64-decoding the JWT body /Users/2dot4/Projects/alist-projects/creators-website/.env:2 REACT_APP_BOARD_ID=6870444819 git ls-files lists .env as tracked; .gitignore (verified) contains only .env.local/.env.development.local/.env.test.local/.env.production.local, NOT .env src/ui/notified/Components/notified-form/notified-form.tsx:28 const apiKey: string = process.env.REACT_APP_API_KEY as string; — CRA inlines REACT_APP_* into the static bundle at build time src/ui/notified/Components/notified-form/notified-form.tsx:43,47 fetch("https://api.monday.com/v2", { headers: { Authorization: apiKey } }) — token sent from the browser
Attack scenario
An attacker opens creators.ae, opens DevTools/Sources (or fetches /static/js/*.js), greps for 'eyJ' to recover the JWT, then calls https://api.monday.com/v2 directly with Authorization: <token> to dump board 6870444819 (all collected subscriber emails) and/or delete/alter items — entirely out-of-band from the form, with no rate limit or auth barrier.
Impact

Full compromise of the monday.com account's write surface for user 12149628: an attacker who extracts the token (trivially, from the public bundle or git) can read every email address captured by the form, create/modify/delete board items, enumerate workspace data, and burn the account's API quota. With no backend proxy, every page load redistributes the credential; combined with the unauthenticated, no-CAPTCHA/no-rate-limit form (CW-05) the leaked write token is a ready-made data-tampering and data-exfiltration channel. The email PII collected via the form is therefore exposed to any token holder — a GDPR-relevant data-protection gap for an .ae marketing audience.

Remediation
1) Immediately revoke/regenerate the token in monday.com (Admin > API), invalidating this JWT (and the prior one in history, see CW-02). 2) Move the form submission behind a server-side proxy (Cloudflare Worker / Lambda / minimal Node endpoint) that holds the token server-side and is the only place it exists; the browser must never receive it. 3) git rm --cached .env and add .env to .gitignore. 4) Scope the replacement token to least privilege (a dedicated integration/service user limited to board 6870444819) rather than a personal me:write token. 5) Add a pre-commit + CI secret scanner (gitleaks/trufflehog).
CW-02

Both current and previously-rotated monday.com me:write tokens persist in git history

P0 OWASP A02:2021 CWE-540 CVSS 8.2 EPSS n/a confirmed
Description

Commit 0bd04c0 ("new api key") rotated the token only in the working tree; the previous token remains in commit e4ad776. That old JWT decodes to a distinct me:write token (uid=50058541) on the same account (actid=5465124), issued 2024-06-20 with no expiry. Anyone with clone access to the Bitbucket repo can recover both tokens by walking history. A rotation that does not also revoke the old token at the provider and scrub history leaves the old credential live; there is no in-repo evidence the old token was revoked at monday.com. Even the current token's deletion from the working tree would not restore confidentiality because it persists in 0bd04c0.

Evidence
git log --oneline -- .env => 0bd04c0 "new api key" and e4ad776 "first commit" (verified) git show e4ad776:.env => REACT_APP_API_KEY JWT whose body decodes to {tid:374594133, uid:50058541, per:"me:write", actid:5465124, iad:2024-06-20T11:48:41Z} — a SECOND me:write token on the SAME account (verified by base64-decode) Current working-tree token (uid 12149628) was introduced by the rotation commit 0bd04c0 literally named 'new api key'; the old value remains intact in e4ad776 git remote -v => git@bitbucket.org:ParhamandCo/creators-website.git (external personal org; history is clone-readable)
Attack scenario
A former contractor (or anyone who ever cloned ParhamandCo/creators-website) runs git show e4ad776:.env, recovers the 2024-06-20 me:write JWT, and — if it was never revoked at monday.com — uses it to read/modify account 5465124 long after the 'rotation' supposedly closed access.
Impact

If the old token (uid 50058541) was not revoked at monday.com it is a second live me:write credential to the same account, recoverable from history by anyone with clone access. Standard 'remove the file' remediation will NOT help; the secrets must be revoked at the provider and history rewritten. This raises the integrity/availability ceiling for any board the account can touch.

Remediation
1) Confirm with monday.com that BOTH tokens (uid 50058541 and uid 12149628) are revoked. 2) Rewrite history with git-filter-repo/BFG to purge .env from all commits, then force-push with team coordination. 3) Enroll the repo in gitleaks pre-commit + CI so .env/JWT patterns are blocked going forward. 4) Document a rotation runbook: revoke at provider FIRST, then scrub, never the reverse.
CW-03

GraphQL injection: user email string-concatenated into monday.com create_item mutation, validated only afterward

P1 OWASP A03:2021 CWE-943 CVSS 7.1 EPSS n/a confirmed
Description

The email-capture form builds its monday.com GraphQL mutation by directly interpolating the user-controlled email into the query string (item_name: "${email}") with no escaping. The query is assembled (line 31) before the validation regex runs (line 37), so validation does not gate construction; moreover the regex only rejects whitespace and '@' and explicitly permits the double-quote, so even a 'valid' value like a"@b.co passes. An attacker types a " to break out of the item_name literal and append arbitrary GraphQL. Because GraphQL accepts multiple top-level fields, an injected payload can chain change_column_value, delete_item, or create_item on other boards (anything the token is authorized for) or alias query fields to read accessible data. Validation is also purely client-side (CW-03 absorbs the standalone 'client-side-only validation' weakness), so an attacker can equally edit the POST body in DevTools/Burp. Scored S:C (changed scope) because the injection executes against a separate system, monday.com, under the bundled token's authority.

Evidence
src/ui/notified/Components/notified-form/notified-form.tsx:31-35 const query = `mutation { create_item (board_id: ${boardId}, item_name: "${email}") { id } }`; — email interpolated unescaped src/ui/notified/Components/notified-form/notified-form.tsx:37 if (!validateEmail(email)) {...} — regex check executes AFTER the query string is already assembled at line 31 src/ui/notified/Components/notified-form/notified-form.tsx:15-19 emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ — only blocks whitespace and '@'; permits the double-quote (") character src/ui/notified/Components/notified-form/notified-form.tsx:49 body: JSON.stringify({ query }) — the raw concatenated string is what is sent CW-01: the same component holds the public me:write token, so the injected mutation runs with full token privileges
Attack scenario
An attacker enters a") { id } delete_item(item_id: <known_id>) { id } create_item(board_id: 6870444819, item_name:"x in the email field (or edits the request body in Burp since validation is client-only). The browser posts the concatenated mutation with the bundled token; monday.com executes both create_item and the injected delete_item. Iterating over enumerated item IDs corrupts or wipes the board; the same payloads also fire directly at api.monday.com using the leaked token, bypassing the form entirely.
Impact

Arbitrary GraphQL operations executed against the client's monday.com workspace within the inlined token's privileges: tampering with or deleting board items, modifying column values, and reading data the token can access. With the token also public (CW-01), there is no authentication barrier — any visitor or bot can issue crafted mutations at scale with no rate limit, CAPTCHA, or CSRF control. Board data integrity impact is high; confidentiality is bounded by token scope.

Remediation
Stop string-building GraphQL. Use parameterized variables: { query: 'mutation($boardId: ID!, $name: String!){ create_item(board_id:$boardId, item_name:$name){ id } }', variables: { boardId, name: email } }. Run validateEmail() and reject BEFORE constructing or sending anything, and tighten the regex to disallow quotes/control chars (or use a strict validator). Critically, move submission behind a server-side proxy so neither token nor raw query is built in the browser; have the proxy validate, parameterize, and rate-limit/CAPTCHA. Treat client-side validation as UX only.
CW-04

End-of-life build toolchain (Create React App / react-scripts 5.0.1) freezes a deep vulnerable transitive tree

P1 OWASP A06:2021 CWE-1104 CVSS 7.5 EPSS n/a confirmed
Description

The entire build pipeline depends on react-scripts@5.0.1 (CRA), which is deprecated and unreleased since 2022, so the build tooling and its pinned transitive graph receive no security fixes. CRA was officially deprecated by the React team (Feb 2025 docs no longer recommend it); react-scripts 5.0.1 (Apr 2022) is the last release. CRA cannot be partially upgraded without eject/migration; the frozen tree is the root cause of the individual CVE clusters (CW-07, CW-08). There is no Vite/Next migration and no SCA automation.

Evidence
package.json:13 "react-scripts": "^5.0.1" package-lock.json (lockfileVersion 3) node_modules/react-scripts -> 5.0.1; ~1530 resolved packages CRA was officially deprecated by the React team (Feb 2025 docs no longer recommend it); react-scripts 5.0.1 (Apr 2022) is the last release — no further security patches Frozen tree confirmed in lockfile: webpack-dev-server 4.15.2, svgo 1.3.2, rollup 2.79.1, postcss 7.0.39 (nested under resolve-url-loader), nanoid 3.3.7, cross-spawn 7.0.3, micromatch 4.0.7, http-proxy-middleware 2.0.6, path-to-regexp 0.1.7 No dependency-update automation present (no dependabot/renovate/snyk config, no CI)
Attack scenario
A newly disclosed webpack/babel/postcss CVE lands; because the tree is pinned by an unmaintained CRA, the team cannot apply a vendor patch without overrides or migration, leaving the build environment exposed and dependency hygiene permanently degraded.
Impact

The project is structurally stuck on EOL build tooling: new CVEs in webpack/svgo/babel/rollup cannot be remediated by simple bumps and each requires overrides or a full migration. Over time the build environment accumulates unpatched vulnerabilities. Practical attack surface is build-time/dev (dev server, source-map/HTML generation), not the anonymous-internet production artifact — hence A-impact via build/CI disruption rather than runtime C/I.

Remediation
Plan migration off CRA to a maintained bundler (Vite is the closest drop-in for a CRA SPA). Short term, add package.json overrides to force patched transitive versions (see CW-07/CW-08), enable npm audit/Snyk in CI, and add Renovate/Dependabot for ongoing updates.
CW-05

No CI/CD pipeline and unprotected direct-to-master pushes via Bitbucket web editor on an external personal org

P1 OWASP A08:2021 CWE-1395 / CWE-353 CVSS 7.1 EPSS n/a confirmed
Description

There is no CI/CD of any kind: no automated build verification, no dependency/secret scanning gate, no npm ci integrity install, no SAST/SCA before deploy. The code lives on a Bitbucket repo under an external personal org (ParhamandCo) and history shows direct commits to master including edits through the Bitbucket web editor, meaning anyone with web access to that account can push production changes (including the api-key change) with no review, branch protection, or pipeline checks. This is a software-integrity/governance failure: the path from arbitrary edit to production has no integrity controls.

Evidence
No .github/workflows, no bitbucket-pipelines.yml, no Jenkinsfile, no .gitlab-ci.yml anywhere in the repo (verified) git remote -v => git@bitbucket.org:ParhamandCo/creators-website.git — an external/third-party org, not an A-List-controlled namespace git log shows direct-to-master one-off edits via the Bitbucket web editor: 41538a2 'footer-signature.tsx edited online with Bitbucket', 0bd04c0 'new api key', plus 52e52be/6b33388 plain master merges Single branch: master; no PR/branch-protection trail in history No npm ci / lockfile-integrity enforcement and no SAST/SCA gate anywhere
Attack scenario
An attacker who phishes or reuses credentials for the ParhamandCo Bitbucket account opens the web editor, edits notified-form.tsx (or adds a dependency) to exfiltrate every submitted email to an attacker domain, commits straight to master, and the change deploys to creators.ae with no review, test, or scan to stop it.
Impact

A compromised or over-privileged Bitbucket account (or a malicious insider) can push arbitrary code straight to the deployed marketing site without review — malicious dependencies, exfiltration scripts, defacement. Absence of npm ci/lockfile enforcement and SCA means a dependency-confusion or compromised-package update could deploy silently. External-org ownership compounds key-rotation and offboarding risk.

Remediation
Add a CI pipeline (Bitbucket Pipelines or GitHub Actions) running npm ci, npm audit --audit-level=high, secret scanning (gitleaks), build, and tests on every PR. Enable branch protection on master (require PR + review, disable direct/web-editor pushes), enforce the lockfile, and move repo ownership into an A-List-controlled namespace with least-privilege access. Pin third-party CI actions to commit SHAs once a pipeline exists.
CW-06

Production source maps enabled by default (GENERATE_SOURCEMAP not disabled) re-expose original source and the inlined token

P2 OWASP A05:2021 CWE-540 CVSS 5.3 EPSS n/a likely
Description

CRA emits production source maps by default. With GENERATE_SOURCEMAP unset and a bare react-scripts build, the deployed /static/js/*.js.map files will contain the original TypeScript source, making the already-inlined token (CW-01) and the injectable GraphQL query (CW-03) trivially readable and exposing the full client source structure. This is a secondary amplifier of the token exposure rather than an independent secret, and is conditional on the deployment actually serving the .map files (most static hosts do), hence 'likely' / medium.

Evidence
No GENERATE_SOURCEMAP=false in .env (verified) or in the build script; package.json build script is the bare 'react-scripts build' CRA/react-scripts default is GENERATE_SOURCEMAP=true, emitting *.js.map alongside the bundle Token reachable in those maps via notified-form.tsx:28 (process.env.REACT_APP_API_KEY inlined)
Attack scenario
An attacker fetches /static/js/main.<hash>.js.map, reconstructs notified-form.tsx with original variable names, reads the inlined REACT_APP_API_KEY and the exact create_item mutation shape, then crafts a precise injection/replay payload.
Impact

Lowers the effort to extract the inlined credential and to understand the injectable GraphQL request shape; aids targeted abuse of the leaked token and of the form injection. No independent impact beyond CW-01/CW-03.

Remediation
Set GENERATE_SOURCEMAP=false for production builds (or strip/deny-list *.map at the CDN/host). This is hardening only; the real fix is removing the token from the client entirely (CW-01).
Verifier note

Rated "likely" — the source-map emission is confirmed by the bare build script and CRA defaults, but exploitation depends on the (unverified) static host actually serving the .map files. Most do.

CW-07

ReDoS in nth-check 1.0.2 (transitive via svgo 1.3.2 / @svgr) — CVE-2021-3803

P2 OWASP A06:2021 CWE-1333 CVSS 7.5 CVE-2021-3803 EPSS ~0.5% confirmed
Description

nth-check < 2.0.1 contains an inefficient regular expression (ReDoS) parsing nth-child expressions, pulled transitively through svgo@1.3.2 via @svgr/webpack (the CRA SVG-as-component loader). This is the well-known high-severity finding npm audit reports on every default CRA 5 project. It is build-time/dev-only reachable here (SVGs are processed at build), not at runtime in the browser, which constrains real-world impact for this static site.

Evidence
package-lock.json: node_modules/svgo/node_modules/nth-check -> 1.0.2 (vulnerable; fixed in 2.0.1) — verified; note top-level node_modules/nth-check is 2.1.1, so only the svgo sub-tree is vulnerable Dependency path: react-scripts > @svgr/webpack 5.5.0 > @svgr/plugin-svgo > svgo 1.3.2 > css-select 2.1.0 > nth-check 1.0.2 node_modules/svgo -> 1.3.2 and node_modules/svgo/node_modules/css-select -> 2.1.0 confirm the vulnerable sub-tree
Attack scenario
A contributor adds a maliciously crafted SVG asset; during npm run build, svgo's css-select invokes vulnerable nth-check on it, pinning a CPU core and hanging the build/CI indefinitely.
Impact

A crafted SVG processed by the build could cause a CPU-bound hang of the build/dev process (DoS of the build pipeline). Not exploitable against site visitors at runtime.

Remediation
Add an npm overrides entry forcing nth-check>=2.0.1 (and css-select>=4) across the tree, or migrate off CRA/svgo 1.x (CW-04). Verify with npm audit post-override. Build only with trusted SVG assets.
CW-08

Cluster of build/dev-time transitive CVEs frozen by CRA 5 (postcss, webpack-dev-server, rollup, express stack, nanoid, cross-spawn, micromatch, http-proxy-middleware)

P2 OWASP A06:2021 CWE-937 CVSS 6.1 CVE-2023-44270 +7 EPSS mostly <2% confirmed
Description

The CRA 5 transitive tree pins numerous packages to versions with published CVEs. Notables: postcss 7.0.39 under resolve-url-loader (CVE-2023-44270 CSS line-parsing/injection), webpack-dev-server 4.15.2 (CVE-2025-30359/30360 — a malicious site visited while the dev server runs can read source via non-allowlisted origins), rollup 2.79.1 (CVE-2024-47068 DOM Clobbering that can inject script into generated bundles), and the express/connect dev-server stack (path-to-regexp ReDoS, send/serve-static path handling, body-parser DoS, cookie name parsing). Most are build-time/local-dev only for a static SPA and are not reachable by anonymous internet users against the deployed artifact (hence P2), though rollup CVE-2024-47068 can theoretically affect generated output and webpack-dev-server source-leak affects any developer running npm start.

Evidence
postcss 7.0.39 [node_modules/resolve-url-loader/node_modules/postcss] -> CVE-2023-44270 (line-parsing, fixed 8.4.31) — verified in lockfile (top-level postcss is 8.4.38, only the nested one is vulnerable) webpack-dev-server 4.15.2 -> CVE-2025-30359 / CVE-2025-30360 (dev-server source-code leak to malicious site; fixed 5.2.1) — verified rollup 2.79.1 -> CVE-2024-47068 (DOM Clobbering XSS in generated bundles; fixed 3.29.5/4.22.4) — verified path-to-regexp 0.1.7 (via express 4.x dev-server stack) -> CVE-2024-45296 ReDoS (fixed 0.1.10); send 0.18.0, serve-static 1.15.0, body-parser 1.20.2, cookie 0.6.0 -> respective 2024 advisories — verified versions nanoid 3.3.7 -> CVE-2024-55565; cross-spawn 7.0.3 -> CVE-2024-21538 (ReDoS, fixed 7.0.5); micromatch 4.0.7 -> CVE-2024-4067 (fixed 4.0.8); http-proxy-middleware 2.0.6 -> 2024 advisories (fixed 2.0.7+) — verified versions
Attack scenario
A developer runs npm start and, in another tab, visits an attacker page that abuses the webpack-dev-server origin weakness (CVE-2025-30359/30360) to read the project's source over the dev-server socket, exfiltrating proprietary code and the inlined token from the dev bundle.
Impact

Primary risk is to developers/build infrastructure: source-code disclosure when running the dev server alongside a malicious site, ReDoS/DoS of build or dev processes, and (rollup) a small chance of DOM-clobbering-injected script in produced bundles. No direct anonymous-internet impact on the static production site beyond the rollup output concern.

Remediation
Pin patched versions via npm overrides: postcss>=8.4.31, rollup>=2.79.2 (or 3.29.5/4.22.4), path-to-regexp>=0.1.10, send>=0.19.0, serve-static>=1.16.0, body-parser>=1.20.3, cookie>=0.7.0, nanoid>=3.3.8, cross-spawn>=7.0.6, micromatch>=4.0.8, http-proxy-middleware>=2.0.9, webpack-dev-server>=5.2.1 (or never browse untrusted sites while npm start runs). Long term, migrate off CRA (CW-04). Run npm audit in CI.
CW-09

No Content-Security-Policy or anti-XSS/clickjacking HTTP headers (defense-in-depth missing)

P3 OWASP A05:2021 CWE-1021 CVSS 3.1 EPSS n/a confirmed
Description

The app ships no CSP (neither a meta tag in index.html nor any server header config in the repo) and no framing/MIME hardening headers. There is currently no DOM-XSS sink in the source (React JSX auto-escapes; no dangerouslySetInnerHTML/innerHTML/eval/document.write), so this is a missing defense-in-depth layer rather than an active vulnerability. A restrictive CSP would contain any future inline-script or third-party-script compromise and is standard for a public marketing site.

Evidence
public/index.html (full file read): no <meta http-equiv="Content-Security-Policy"> and no X-Content-Type-Options/X-Frame-Options/Referrer-Policy grep -rni 'content-security|http-equiv|x-frame|nosniff' public/ -> no matches (verified) No server/host config in repo to set response headers (static CRA build) grep across src for dangerouslySetInnerHTML/innerHTML/eval/document.write -> none found, so no active DOM-XSS sink exists today (React JSX auto-escapes)
Attack scenario
Not directly exploitable today. Becomes relevant if a supply-chain compromise of react-scripts/transitive deps (CW-04/CW-08) or a future feature introduces an injection point; absent CSP, injected script can exfiltrate to any origin and the form can be framed for clickjacking.
Impact

If a future code change or compromised dependency/CDN introduces an injection sink, there is no CSP to contain script execution, no frame-ancestors protection against clickjacking of the email form, and no Referrer-Policy to limit leakage. No exploitable impact today.

Remediation
Add a strict CSP at the hosting/CDN layer (e.g. default-src 'self'; script-src 'self'; connect-src 'self' https://api.monday.com; object-src 'none'; base-uri 'none'; frame-ancestors 'none'). Add X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, X-Frame-Options: DENY. Once the form is proxied (CW-01), drop api.monday.com from connect-src.
CW-10

No Software Composition Analysis / dependency-update automation and no enforced reproducible install

P3 OWASP A06:2021 CWE-1104 CVSS 3.7 EPSS n/a confirmed
Description

There is no continuous dependency monitoring (no Snyk/Dependabot/Renovate) and no npm audit gate, consistent with there being no CI. The lockfile itself is healthy (v3, subresource-integrity hashes, registry-only resolution, only expected install scripts), so there is no evidence of an active implant. But without npm ci enforced anywhere and without automated advisory tracking, newly disclosed CVEs in the 1530-package tree go unnoticed and an npm install could drift from the lockfile. Two declared devDependencies (ajv, dotenv) are unused, adding needless surface.

Evidence
No .snyk, no renovate.json, no .github/dependabot.yml, and no CI at all (verified) package-lock.json present (lockfileVersion 3, ~1530 packages) with integrity hashes and all packages resolved from the npm registry — but nothing enforces npm ci over npm install Only benign install scripts present (core-js postinstall ad, fsevents native build); no unexpected lifecycle scripts — no evidence of an active supply-chain implant devDependencies pin ajv ^7.2.4 and dotenv ^16.4.5 (both unused at runtime per CLAUDE.md) — unnecessary manifest surface
Attack scenario
A widely-used transitive dependency publishes a critical advisory; with no SCA/Dependabot and no audit gate, it goes unnoticed for months, and a stray npm install (rather than npm ci) silently pulls a drifted or malicious patch version into a build that no pipeline scans.
Impact

Slow detection of newly disclosed dependency vulnerabilities and risk of lockfile drift during installs. Low immediate exploitability; a hygiene/governance gap that amplifies the EOL-toolchain risk (CW-04).

Remediation
Add Dependabot or Renovate plus a npm ci && npm audit --audit-level=high (or Snyk) step in CI. Enforce npm ci for all installs/builds to honor the lockfile. Remove unused devDependencies (ajv, dotenv). Use --ignore-scripts where feasible and review lifecycle scripts on dependency bumps.

Remediation roadmap

Immediate
Contain the live-credential exposure (CW-01, CW-02) — treat both tokens as burned.
  • Revoke/regenerate the current token (uid 12149628) in monday.com (Admin > API), and confirm the previously-rotated token (uid 50058541, from commit e4ad776) is also revoked.
  • Issue the replacement as a least-privilege integration/service token scoped to board 6870444819 — never a personal me:write token.
  • git rm --cached .env and add .env to .gitignore.
This week
Close the active code-level vulnerabilities (CW-03) and the integrity gaps (CW-05).
  • Stand up a server-side proxy (Cloudflare Worker / Lambda / minimal Node endpoint) that holds the token; the browser must never receive it. Have the proxy validate, parameterize, and rate-limit/CAPTCHA.
  • Replace string-built GraphQL with parameterized variables, and run validateEmail() (tightened to reject quotes/control chars) BEFORE constructing or sending anything.
  • Rewrite git history with git-filter-repo/BFG to purge .env from all commits, then force-push with team coordination.
  • Move repo ownership into an A-List-controlled namespace and enable branch protection on master (require PR + review, disable direct/web-editor pushes).
This month
Establish integrity automation and reduce dependency risk (CW-04, CW-05, CW-07, CW-08, CW-10).
  • Add a CI pipeline (Bitbucket Pipelines / GitHub Actions) running npm ci, npm audit --audit-level=high, secret scanning (gitleaks), build, and tests on every PR; enforce the lockfile and pin CI actions to commit SHAs.
  • Add package.json overrides to force patched transitive versions: nth-check>=2.0.1, postcss>=8.4.31, rollup>=2.79.2, path-to-regexp>=0.1.10, send>=0.19.0, serve-static>=1.16.0, body-parser>=1.20.3, cookie>=0.7.0, nanoid>=3.3.8, cross-spawn>=7.0.6, micromatch>=4.0.8, http-proxy-middleware>=2.0.9, webpack-dev-server>=5.2.1.
  • Enable Dependabot/Renovate and remove unused devDependencies (ajv, dotenv).
  • Plan migration off the EOL CRA toolchain to a maintained bundler (Vite is the closest drop-in).
Hardening
Defense-in-depth once the token is off the client (CW-06, CW-09).
  • Set GENERATE_SOURCEMAP=false for production builds (or deny-list *.map at the CDN/host).
  • Add a strict CSP at the hosting/CDN layer (default-src 'self'; script-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none') plus X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, X-Frame-Options: DENY.
  • Document a rotation runbook: revoke at provider FIRST, then scrub history — never the reverse.

Code quality

Run / deploy

Local setup

git clone <bitbucket-url>
cd creators-website
npm install
# .env is already in the repo (P0 — see findings). Rotate the key before
# doing anything else, then move it out of git.
npm start                # http://localhost:3000
npm run build            # writes /build (gitignored)
npm test                 # currently fails — broken placeholder test

Environment

Deployment hints

No CI config, no Dockerfile, no infra-as-code in the repo. The Bitbucket remote is ParhamandCo/creators-website. The output of npm run build is a static build/ directory that can be served by any static host (Cloudflare Pages, Netlify, S3+CloudFront, Vercel static). Whatever the current host is, the bundled monday.com token is being served alongside the HTML — fixing that needs a small serverless function in front of the form post.

What to know before editing