Skip to content

fix: harden frontend security entrypoints#7601

Open
fairlighteth wants to merge 13 commits into
developfrom
fix/deepsec-high-frontend-hardening
Open

fix: harden frontend security entrypoints#7601
fairlighteth wants to merge 13 commits into
developfrom
fix/deepsec-high-frontend-hardening

Conversation

@fairlighteth

@fairlighteth fairlighteth commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR hardens a set of frontend trust boundaries in cowswap-frontend and shared frontend/widget libraries.

Main changes:

  • validate untrusted external URLs before rendering them as links
  • stop hydrating hidden recipient state from recipientAddress URL params
  • require valid, owned account-proxy recovery inputs before enabling signing flows
  • restrict widget Safe SDK message relaying to the trusted iframe/parent pair
  • stop exposing the Pinata secret env var through browser-facing exports

This addresses the remaining DeepSec HIGH findings that are in scope for frontend and widget code, excluding cow-fi and excluding the larger deferred items listed below.

To Test

  1. Hook and notification links
  • Valid hook website links still render as clickable external links.
  • Invalid hook website URLs render as plain text and are not clickable.
  • CMS speech-bubble CTAs open correctly for valid internal/external URLs.
  • Unsafe notification URLs do not render a clickable CTA.
  1. Bridge / explorer links
  • Valid bridge explorer links still render in bridge progress UI and success notifications.
  • Invalid explorer URLs do not render clickable links.
  • In local dev, http://localhost:... and http://[::1]:... explorer URLs still work when explicitly configured.
  1. Recipient and recovery hardening
  • Opening swap with only recipientAddress=0x... in the URL does not enable recipient mode.
  • Opening the recovery page with an owned proxy + valid token still allows recovery when balance exists.
  • Opening the recovery page with an unowned proxy or invalid token keeps recovery disabled.
  1. Widget Safe SDK bridge
  • Safe SDK messaging still works between the widget iframe and its embedding parent.
  • Unrelated postMessage traffic from other windows/origins is ignored.

Automated coverage added in this PR:

  • safe absolute URL handling, including IPv6 localhost and bare-origin normalization
  • shared explorer URL builders
  • recipient visibility when only recipientAddress is present
  • inert rendering for unsafe hook simulation links

git diff --check passed locally.

Background

Deferred HIGH findings intentionally left out of this PR because they need larger product/flow changes:

  • apps/cowswap-frontend/src/modules/hooksStore/containers/HookDappContainer/index.tsx
    • hook iframe payloads still need semantic validation plus an explicit review/confirmation step before mutating hook state
  • apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts
    • TWAP Safe transaction parsing still needs structural decoding of direct calls and MultiSend inner calls instead of selector substring scanning

Notes:

  • recipient=<value> remains the intended visible custom-recipient param.
  • This PR intentionally removes trust in the hidden recipientAddress param.
  • Full repo lint/test/typecheck were not runnable in the original session worktree because dependencies/tools were not installed there.

- validate external links and bridge explorer URLs before rendering
- stop trusting URL-derived recipients and arbitrary proxy recovery
- scope Safe SDK iframe relaying to trusted widget and parent origins
- remove browser exposure of the Pinata secret export
@vercel

vercel Bot commented Jun 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cowfi Ready Ready Preview Jun 15, 2026 3:16pm
explorer-dev Ready Ready Preview Jun 15, 2026 3:16pm
storybook Ready Ready Preview Jun 15, 2026 3:16pm
swap-dev Ready Ready Preview Jun 15, 2026 3:16pm
widget-configurator Ready Ready Preview Jun 15, 2026 3:16pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
cosmos Ignored Ignored Jun 15, 2026 3:16pm
sdk-tools Ignored Ignored Preview Jun 15, 2026 3:16pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Introduces safe URL parsing utilities that validate protocol schemes, reject credentials, and normalize bare origins; applies them to link rendering across hook components, bridge/transaction/notification UI, manifest validation, and explorer helpers. Hardens the iframe SDK bridge to use explicit trusted origins for message posting instead of wildcards. Also includes account proxy input validation, trade state field consolidation, and Pinata environment variable updates.

Changes

URL Safety Validation & Security Hardening

Layer / File(s) Summary
Safe link utility and tests
libs/common-utils/src/safeLink.ts, libs/common-utils/src/safeLink.test.ts, libs/common-utils/src/index.ts
New getSafeAbsoluteUrl (https always allowed, http only in dev for localhost) and getSafeSameOriginOrAbsoluteUrl (marks external links by origin comparison) with comprehensive test coverage and re-export.
Explorer link normalization
libs/common-utils/src/getExplorerLink.ts, libs/common-utils/src/getExplorerLink.test.ts, libs/common-utils/src/legacyAddressUtils.ts, libs/common-utils/src/legacyAddressUtils.test.ts
Explorer base URLs normalized via safe parsing; prevents double slashes when origin lacks trailing slash; tests verify correct formatting.
Hook component safe rendering
apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.tsx, .../index.test.tsx, apps/cowswap-frontend/src/modules/hooksStore/pure/AppliedHookItem/index.tsx, .../index.test.tsx, apps/cowswap-frontend/src/modules/hooksStore/pure/HookDappDetails/index.tsx
HookItem, AppliedHookItem, and HookDappDetails derive safe simulation and website URLs; external anchors render only when validation succeeds; tests assert unsafe hrefs render as inert text.
Hook manifest validation & localization
apps/cowswap-frontend/src/modules/hooksStore/validateHookDappManifest.tsx, apps/cowswap-frontend/src/modules/hooksStore/pure/AddCustomHookForm/constants.tsx, apps/cowswap-frontend/src/locales/en-US.po
Manifest website field validated with getSafeAbsoluteUrl; new INVALID_WEBSITE_URL error message specifies https required and http only in dev; locale entries updated.
Bridge, transaction & notification links
apps/cowswap-frontend/src/modules/bridge/pure/TransactionLink/TransactionLinkDisplay.tsx, apps/cowswap-frontend/src/modules/bridge/pure/contents/BridgingProgressContent/index.tsx, apps/cowswap-frontend/src/modules/orders/containers/BridgingSuccessNotification/index.tsx, apps/cowswap-frontend/src/modules/application/containers/AppContainer/CowSpeechBubble/CowSpeechBubbleNotificationBanner.tsx
Explorer and notification URLs sanitized via safe helpers; external links render only when validation succeeds; unsafe links return null or render as plain text.
Bridge analytics & survey sanitization
apps/cowswap-frontend/src/modules/bridge/updaters/PendingBridgeOrdersUpdater.tsx
Explorer URLs normalized before sending snackbar events, analytics payloads, and Appzi survey data (nps, pending-too-long).
SDK bridge trusted-origin routing
libs/widget-lib/src/IframeSafeSdkBridge.ts, libs/widget-lib/src/cowSwapWidget.ts
IframeSafeSdkBridge now validates event.source and event.origin against explicit iframe/parent origins, posts messages only to trusted origins, and rejects mismatched window relationships. New getTrustedParentOrigin helper derives parent from document.referrer. Widget wiring updated with computed origins.

Input Validation, Trade State, & Environment Configuration

Layer / File(s) Summary
Account proxy validation
apps/cowswap-frontend/src/modules/accountProxy/containers/AccountProxyRecoverPage/index.tsx
Proxy and token addresses validated from URL params before wiring into recovery hooks; validated token used for balance updates; button disabled state requires valid proxy and token.
Trade state recipient consolidation
apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeStateFromUrl.ts, apps/cowswap-frontend/src/modules/trade/hooks/useWithRecipient.test.ts
Remove recipientAddress from URL parsing; consolidate to recipient field. Test added for recipientAddress-only input.
Pinata environment variable
libs/common-const/src/ipfs.ts, apps/cowswap-frontend/src/legacy/state/application/localWarning.ts
Rename PINATA_SECRET_API_KEY to PINATA_API_KEY; update local warning to check API key and instruct server-side configuration.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • cowprotocol/cowswap#7460: Related Safe SDK bridge origin validation and trusted parent-origin derivation in widget initialization.
  • cowprotocol/cowswap#7298: Related iframe communication hardening using validated/trusted origins instead of wildcards across widget bridge and transport layers.
  • cowprotocol/cowswap#7631: Overlaps in widget iframe setup modifications within libs/widget-lib, including bridge initialization paths.

Suggested reviewers

  • Danziger
  • alfetopito
  • kernelwhisperer
  • shoom3301

Poem

🐰 Rabbit's hop toward safer clicks:
URLs parsed with care and tricks,
https hops and localhost picks,
Iframe bridges now trust origins true—
Safe message forwarding breaks through! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: harden frontend security entrypoints' directly aligns with the main objective of the PR, which addresses security findings by validating external links, controlling access to trusted origins, and removing secret exposure.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed PR description follows the template structure with Summary, To Test section with checkboxes, and Background context explaining the scope and deferred items.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/deepsec-high-frontend-hardening

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 3, 2026

Copy link
Copy Markdown

Deploying explorer-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: 88f524e
Status: ✅  Deploy successful!
Preview URL: https://42ec195f.explorer-dev-dxz.pages.dev
Branch Preview URL: https://fix-deepsec-high-frontend-ha.explorer-dev-dxz.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 3, 2026

Copy link
Copy Markdown

Deploying swap-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: 88f524e
Status: ✅  Deploy successful!
Preview URL: https://ab7b67c5.swap-dev-5u6.pages.dev
Branch Preview URL: https://fix-deepsec-high-frontend-ha.swap-dev-5u6.pages.dev

View logs

- stop checking an unprefixed secret env var from browser code
- warn only on missing client-visible Pinata config
fairlighteth and others added 2 commits June 3, 2026 16:40
…rontend-hardening

# Conflicts:
#	apps/cowswap-frontend/src/modules/bridge/pure/TransactionLink/TransactionLinkDisplay.tsx
#	libs/widget-lib/src/cowSwapWidget.ts
- normalize bracketed IPv6 localhost before allowlist checks
- add a regression test for http://[::1] development URLs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/cowswap-frontend/src/modules/hooksStore/pure/AppliedHookItem/index.tsx (1)

40-135: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reduce AppliedHookItem complexity to unblock CI.

Line 40 currently fails lint (complexity 21, max 20), so this PR won’t pass CI until this component is split/refactored.

Suggested minimal refactor (extract simulation status branch)
+interface SimulationStatusContentProps {
+  safeSimulationUrl: string | null
+  simulationStatus: string
+}
+
+function SimulationStatusContent({ safeSimulationUrl, simulationStatus }: SimulationStatusContentProps) {
+  return safeSimulationUrl ? (
+    <a href={safeSimulationUrl} target="_blank" rel="noopener noreferrer">
+      {simulationStatus}
+      <ExternalLinkIcon size={14} />
+    </a>
+  ) : (
+    <span>{simulationStatus}</span>
+  )
+}
+
 export function AppliedHookItem({
   account,
   hookDetails,
@@
-          {safeSimulationUrl ? (
-            <a href={safeSimulationUrl} target="_blank" rel="noopener noreferrer">
-              {simulationStatus}
-              <ExternalLinkIcon size={14} />
-            </a>
-          ) : (
-            <span>{simulationStatus}</span>
-          )}
+          <SimulationStatusContent safeSimulationUrl={safeSimulationUrl} simulationStatus={simulationStatus} />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/cowswap-frontend/src/modules/hooksStore/pure/AppliedHookItem/index.tsx`
around lines 40 - 135, AppliedHookItem exceeds linted complexity; extract the
simulation-status rendering branch into a new child component to reduce
complexity. Create a new component (e.g., HookSimulationStatus) that accepts
props used by the branch (isBundleSimulationReady, account, simulationData,
safeSimulationUrl, simulationStatus, simulationTooltip) and moves the JSX that
renders styledEl.SimulateContainer / SVG / link / InfoTooltip into that
component; keep the TenderlySimulate / OldSimulateContainer logic in
AppliedHookItem but replace the inlined bundle-simulation JSX with
<HookSimulationStatus ... /> and pass through isValidating/mutate usage
unchanged (leave useTenderlyBundleSimulation/useSimulationData calls in
AppliedHookItem and pass needed values down). Ensure prop names match
hookDetails.uuid usage and that aria-labels/attributes (e.g., target/rel) remain
identical so behavior and tests stay the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/cowswap-frontend/src/legacy/state/application/localWarning.ts`:
- Around line 4-12: The variable warningMsg is implicitly any; update its
declaration to have an explicit type (string | undefined) and optionally
initialize to undefined so it respects noImplicitAny, and ensure the exported
localWarning has the matching type (string | undefined) — locate the warningMsg
declaration and the export of localWarning and add the type annotation to both
places (or initialize warningMsg to undefined) to fix the type error.

In
`@apps/cowswap-frontend/src/modules/bridge/pure/TransactionLink/TransactionLinkDisplay.tsx`:
- Around line 3-4: Reorder the top-level imports so the asset import comes
before the utility import to satisfy the import/order rule: move the import of
iconReceiptSrc from '`@cowprotocol/assets/cow-swap/icon-receipt.svg`' above the
import of getSafeAbsoluteUrl from '`@cowprotocol/common-utils`' (references:
iconReceiptSrc and getSafeAbsoluteUrl) and run the linter to confirm the
violation is resolved.

In `@apps/cowswap-frontend/src/modules/hooksStore/validateHookDappManifest.tsx`:
- Around line 3-4: The imports are out of order causing an import/order lint
failure: swap the two imports so that getChainInfo from
'`@cowprotocol/common-const`' is imported before getSafeAbsoluteUrl from
'`@cowprotocol/common-utils`', preserving module boundaries and existing import
direction constraints; update the import statements that reference getChainInfo
and getSafeAbsoluteUrl accordingly to satisfy the linter.

---

Outside diff comments:
In `@apps/cowswap-frontend/src/modules/hooksStore/pure/AppliedHookItem/index.tsx`:
- Around line 40-135: AppliedHookItem exceeds linted complexity; extract the
simulation-status rendering branch into a new child component to reduce
complexity. Create a new component (e.g., HookSimulationStatus) that accepts
props used by the branch (isBundleSimulationReady, account, simulationData,
safeSimulationUrl, simulationStatus, simulationTooltip) and moves the JSX that
renders styledEl.SimulateContainer / SVG / link / InfoTooltip into that
component; keep the TenderlySimulate / OldSimulateContainer logic in
AppliedHookItem but replace the inlined bundle-simulation JSX with
<HookSimulationStatus ... /> and pass through isValidating/mutate usage
unchanged (leave useTenderlyBundleSimulation/useSimulationData calls in
AppliedHookItem and pass needed values down). Ensure prop names match
hookDetails.uuid usage and that aria-labels/attributes (e.g., target/rel) remain
identical so behavior and tests stay the same.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d9a4de0c-ccfc-4b58-94f1-535fde82a4a0

📥 Commits

Reviewing files that changed from the base of the PR and between ac553e6 and b8cfaa6.

📒 Files selected for processing (27)
  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.test.tsx
  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.tsx
  • apps/cowswap-frontend/src/legacy/state/application/localWarning.ts
  • apps/cowswap-frontend/src/locales/en-US.po
  • apps/cowswap-frontend/src/modules/accountProxy/containers/AccountProxyRecoverPage/index.tsx
  • apps/cowswap-frontend/src/modules/application/containers/AppContainer/CowSpeechBubble/CowSpeechBubbleNotificationBanner.tsx
  • apps/cowswap-frontend/src/modules/bridge/pure/TransactionLink/TransactionLinkDisplay.tsx
  • apps/cowswap-frontend/src/modules/bridge/pure/contents/BridgingProgressContent/index.tsx
  • apps/cowswap-frontend/src/modules/bridge/updaters/PendingBridgeOrdersUpdater.tsx
  • apps/cowswap-frontend/src/modules/hooksStore/pure/AddCustomHookForm/constants.tsx
  • apps/cowswap-frontend/src/modules/hooksStore/pure/AppliedHookItem/index.test.tsx
  • apps/cowswap-frontend/src/modules/hooksStore/pure/AppliedHookItem/index.tsx
  • apps/cowswap-frontend/src/modules/hooksStore/pure/HookDappDetails/index.tsx
  • apps/cowswap-frontend/src/modules/hooksStore/validateHookDappManifest.tsx
  • apps/cowswap-frontend/src/modules/orders/containers/BridgingSuccessNotification/index.tsx
  • apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeStateFromUrl.ts
  • apps/cowswap-frontend/src/modules/trade/hooks/useWithRecipient.test.ts
  • libs/common-const/src/ipfs.ts
  • libs/common-utils/src/getExplorerLink.test.ts
  • libs/common-utils/src/getExplorerLink.ts
  • libs/common-utils/src/index.ts
  • libs/common-utils/src/legacyAddressUtils.test.ts
  • libs/common-utils/src/legacyAddressUtils.ts
  • libs/common-utils/src/safeLink.test.ts
  • libs/common-utils/src/safeLink.ts
  • libs/widget-lib/src/IframeSafeSdkBridge.ts
  • libs/widget-lib/src/cowSwapWidget.ts
💤 Files with no reviewable changes (1)
  • libs/common-const/src/ipfs.ts

Comment on lines 4 to 12
let warningMsg

if ((!PINATA_SECRET_API_KEY || !PINATA_API_KEY) && isLocal) {
if (!PINATA_API_KEY && isLocal) {
warningMsg =
"Pinata env vars not set. Order appData upload won't work! " +
'Set REACT_APP_PINATA_API_KEY and REACT_APP_PINATA_SECRET_API_KEY'
"Pinata public env var not set. Order appData upload won't work! " +
'Set REACT_APP_PINATA_API_KEY and configure the required server-side Pinata credentials separately.'
}

export const localWarning = warningMsg

@coderabbitai coderabbitai Bot Jun 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify TypeScript strictness and check implicit-any patterns around this file.
fd -i 'tsconfig.*json' -x sh -c 'echo "--- $1"; jq ".compilerOptions | {strict, noImplicitAny}" "$1"' sh {}
rg -n -C2 'let\s+warningMsg\s*$|let\s+\w+\s*$' apps/cowswap-frontend/src/legacy/state/application/localWarning.ts

Repository: cowprotocol/cowswap

Length of output: 7535


Avoid implicit any for warningMsg (apps/cowswap-frontend/src/legacy/state/application/localWarning.ts:4)

let warningMsg has no initializer or type annotation, so with noImplicitAny: true it becomes implicitly any. Type it as string | undefined.

Proposed fix
-let warningMsg
+let warningMsg: string | undefined
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/cowswap-frontend/src/legacy/state/application/localWarning.ts` around
lines 4 - 12, The variable warningMsg is implicitly any; update its declaration
to have an explicit type (string | undefined) and optionally initialize to
undefined so it respects noImplicitAny, and ensure the exported localWarning has
the matching type (string | undefined) — locate the warningMsg declaration and
the export of localWarning and add the type annotation to both places (or
initialize warningMsg to undefined) to fix the type error.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not applying this one.

let warningMsg here is not a demonstrated noImplicitAny failure in TypeScript; this pattern is accepted as an evolving type in this control flow. Adding : string | undefined would be harmless cleanup, but I am keeping this PR scoped to the actual lint blockers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fairlighteth, understood — TypeScript's control flow analysis infers the evolving string | undefined type correctly here without an explicit annotation, so the existing pattern is fine. Happy to leave it as-is.

🐇 (mild acceptance)


✏️ Learnings added
Learnt from: fairlighteth
Repo: cowprotocol/cowswap PR: 7601
File: apps/cowswap-frontend/src/legacy/state/application/localWarning.ts:4-12
Timestamp: 2026-06-05T11:04:07.197Z
Learning: In `apps/cowswap-frontend/src/legacy/state/application/localWarning.ts`, the `let warningMsg` declaration without an explicit type annotation is intentional. TypeScript's control flow analysis correctly infers the evolving `string | undefined` type, so adding `: string | undefined` is purely cosmetic cleanup and should not be flagged as a required fix or a `noImplicitAny` violation in this file.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: lgahdl
Repo: cowprotocol/cowswap PR: 7394
File: .env.local.example:3-5
Timestamp: 2026-04-24T20:02:41.035Z
Learning: In `cowprotocol/cowswap`, the `.env.local.example` comment for `REACT_APP_SAFE_API_AUTH_TOKEN` intentionally says "required" (not "optional") even though `getSafeApiHeaders()` treats it as optional at runtime. The rationale is that unauthenticated calls to `api.safe.global` still work but are subject to monthly quota limits (429 Too Many Requests), so the strong wording is meant to proactively encourage developers to obtain and set a token. Do not flag this comment wording as misleading.

Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 7504
File: .github/workflows/vercel.yml:86-86
Timestamp: 2026-05-13T18:35:50.478Z
Learning: In the cowprotocol/cowswap frontend (pure SPA), do not treat `REACT_APP_*` environment variables (e.g., `REACT_APP_SAFE_API_AUTH_TOKEN`) as a security vulnerability by itself just because they are included in the built frontend bundle. In CRA-style setups, `REACT_APP_*` values are injected at build time into the client bundle, and this repository has no server-side execution layer that could safely keep these values secret. Only flag an issue if there is additional evidence of unintended privilege exposure or missing authorization/validation beyond the expected build-time injection of `REACT_APP_*` tokens.

Learnt from: CR
Repo: cowprotocol/cowswap PR: 0
File: apps/cowswap-frontend/AGENTS.md:0-0
Timestamp: 2026-05-22T12:57:32.776Z
Learning: Applies to apps/cowswap-frontend/**/*.{ts,tsx} : Use explicit return types where they improve safety/readability. Keep local trivial internals inferred; keep exported APIs aligned with root `AGENTS.md` requirements

Learnt from: crutch12
Repo: cowprotocol/cowswap PR: 6969
File: apps/cowswap-frontend/src/lib/localeMessages.ts:12-20
Timestamp: 2026-02-04T18:23:26.408Z
Learning: In apps/cowswap-frontend/src/lib/localeMessages.ts, the loadActiveLocaleMessages() function runs before initial render (in initApp()), at which point feature flags like isInternationalizationEnabled are not yet available. This early locale loading is intentional to avoid white screens and extra rerenders.

Learnt from: fairlighteth
Repo: cowprotocol/cowswap PR: 7044
File: apps/cowswap-frontend/src/modules/wallet/utils/getWalletConnectionErrorMessage.ts:25-37
Timestamp: 2026-04-07T15:30:41.352Z
Learning: In `apps/cowswap-frontend/src/modules/wallet/utils/getWalletConnectionErrorMessage.ts`, the `JSON.stringify` fallback inside `getNormalizedWalletConnectionErrorMessage` is intentional. The function is only invoked when `getProviderErrorMessage()` does not return a string, so structured/non-string message payloads are already handled upstream. The `JSON.stringify` call is kept to preserve diagnostic detail for truly unknown error objects, rather than collapsing them to `[object Object]` or a generic string. Do not flag this as a leakage/noise risk.

Learnt from: CR
Repo: cowprotocol/cowswap PR: 0
File: apps/cowswap-frontend/AGENTS.md:0-0
Timestamp: 2026-05-22T12:57:32.776Z
Learning: Applies to apps/cowswap-frontend/**/modules/**/index.ts : Public module API must be re-exported via the module `index.ts`

Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6009
File: apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/HighFeeWarning/HighFeeWarningTooltipContent.tsx:23-33
Timestamp: 2025-07-24T16:42:53.154Z
Learning: In apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/HighFeeWarning/HighFeeWarningTooltipContent.tsx, the use of toFixed(2) for percentage formatting in tooltip content is intentional and differs from the banner message formatting that uses toSignificant(2, undefined, Rounding.ROUND_DOWN). This formatting difference serves different UX purposes and should not be flagged as inconsistent.

Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 7216
File: libs/common-utils/src/environments.ts:45-45
Timestamp: 2026-03-24T15:01:01.995Z
Learning: In `libs/common-utils/src/environments.ts`, the `forceProdApi` and `forceStagingApi` localStorage keys are intentionally unversioned. They are internal developer/hack overrides (not user-facing keys) and are exempt from the `camelCaseBase:v{number}` versioning convention that applies to regular user-facing or data-shape-sensitive localStorage keys.

Learnt from: CR
Repo: cowprotocol/cowswap PR: 0
File: apps/cowswap-frontend/AGENTS.md:0-0
Timestamp: 2026-05-22T12:57:32.776Z
Learning: Applies to apps/cowswap-frontend/**/*.{ts,tsx} : Prefer `unknown` to `any`

Learnt from: CR
Repo: cowprotocol/cowswap PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-26T08:28:03.489Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : MUST NOT use `any` or non-null assertions (`!`) in production code

Learnt from: CR
Repo: cowprotocol/cowswap PR: 0
File: apps/cowswap-frontend/AGENTS.md:0-0
Timestamp: 2026-05-22T12:57:32.776Z
Learning: Applies to apps/cowswap-frontend/**/*.{ts,tsx} : Prefer `as const`, `satisfies`, and `as const satisfies` where they improve literal safety

Learnt from: CR
Repo: cowprotocol/cowswap PR: 0
File: apps/cowswap-frontend/AGENTS.md:0-0
Timestamp: 2026-05-22T12:57:32.776Z
Learning: Applies to apps/cowswap-frontend/**/*.{ts,tsx} : Avoid generic type names like `Props`/`Options`; use specific names (for example, `TradeWidgetContainerProps`)

Learnt from: kernelwhisperer
Repo: cowprotocol/cowswap PR: 7228
File: libs/widget-lib/src/types.ts:447-448
Timestamp: 2026-04-01T21:32:33.975Z
Learning: In `libs/widget-lib/src/types.ts` (cowprotocol/cowswap PR `#7228`), `WidgetHookPayload<T>` intentionally remains a generic interface rather than a discriminated union over `WidgetHookEvents`. The team considered converting it to a distributive conditional type but found it too complex; correctness of event/payload pairings is enforced via unit tests instead of TypeScript. Do not flag `WidgetHookPayload<WidgetHookEvents>` or the `[WidgetMethodsEmit.PROCESS_HOOK]` mapping as a type-safety issue in this repository.

Learnt from: Danziger
Repo: cowprotocol/cowswap PR: 7153
File: apps/cowswap-frontend/src/modules/advancedOrders/pure/Settings/AdvancedOrdersSettings.tsx:25-25
Timestamp: 2026-03-16T16:33:33.440Z
Learning: In `apps/cowswap-frontend/src/modules/advancedOrders/pure/Settings/AdvancedOrdersSettings.tsx`, the comment `// TODO: we should use limit orders settings in Advanced Orders!` (line 25) is a pre-existing TODO that predates PR `#7153`. It is intentionally deferred and should not be flagged as a blocker in reviews of that PR or subsequent PRs unless there is a dedicated effort to address it.

Learnt from: CR
Repo: cowprotocol/cowswap PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-26T08:28:03.489Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Avoid introducing new `common/** -> modules/**` imports; treat existing cases as legacy debt and track cleanup in `docs/QUALITY.md`

Learnt from: Danziger
Repo: cowprotocol/cowswap PR: 6997
File: apps/cowswap-frontend/src/common/state/fetchTokens.utils.ts:37-49
Timestamp: 2026-03-20T18:17:17.482Z
Learning: In `apps/cowswap-frontend/src/common/state/fetchTokens.utils.ts`, the use of `Promise.all` (instead of `Promise.allSettled`) for batching `fetchTokenFromBlockchain` calls in `fetchTokens` is intentional. The app cannot function correctly when any tokens are missing, so failing the entire batch on a single rejection is the desired fail-fast behavior. Do not flag this as a missing error-handling issue.

Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 7581
File: libs/wallet/src/wagmi/Web3Provider.tsx:160-174
Timestamp: 2026-06-04T07:39:09.775Z
Learning: In cowprotocol/cowswap (`libs/wallet/src/wagmi`), `SafeConnectionHandler` contains an internal early-return guard: if the currently connected connector is `COW_WIDGET_CONNECTOR_ID` (the widget connector), `SafeConnectionHandler` skips its Safe auto-connection/reconnection logic entirely. Therefore, `Web3Provider` does not need to gate `SafeConnectionHandler` on `standaloneMode` — even in dappMode, where the widget connector is active, `SafeConnectionHandler` will not override it. Do not flag the unused `standaloneMode` prop in `Web3ProviderProps` as a bug; the defence is implemented inside `SafeConnectionHandler`.

Comment thread apps/cowswap-frontend/src/modules/hooksStore/validateHookDappManifest.tsx Outdated
- restore import ordering in bridge and hook manifest modules
- extract hook simulation status rendering to reduce component complexity
@fairlighteth

Copy link
Copy Markdown
Contributor Author

Addressed the CodeRabbit outside-diff complexity note in f5bd41c59820c67ffe5e90d982684ea91a45ee03.

I extracted the bundle simulation status rendering out of AppliedHookItem into a small helper component to reduce the main component complexity without changing behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants