Skip to content

Fix/security vulnerabilities#229

Open
codexuttam wants to merge 4 commits into
Stanzin7:masterfrom
codexuttam:fix/security-vulnerabilities
Open

Fix/security vulnerabilities#229
codexuttam wants to merge 4 commits into
Stanzin7:masterfrom
codexuttam:fix/security-vulnerabilities

Conversation

@codexuttam
Copy link
Copy Markdown

@codexuttam codexuttam commented Apr 24, 2026

Summary by CodeRabbit

  • New Features

    • Enhanced permission risk UI with clearer formatting, contextual explanations, and expanded descriptions for high-risk permissions and triggered permission combinations.
  • Chores

    • Updated frontend dependencies to newer versions.
    • Switched deployment target and CI flow to Render; removed prior platform config.
    • Refreshed sitemap last-mod timestamps.

Copilot AI review requested due to automatic review settings April 24, 2026 19:50
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

📝 Walkthrough

Walkthrough

Updates frontend dependencies, refactors LayerModal to render detailed permission risk explanations, adds a Render deployment manifest and replaces Railway deployment workflow, updates sitemap timestamps, and removes the Railway config file.

Changes

Cohort / File(s) Summary
Dependency Updates
frontend/package.json
Bumps axios to ^1.15.2, updates dev deps postcss to ^8.5.10 and vite to ^7.3.2.
UI Component Refactor
frontend/src/components/report/LayerModal.jsx
Reformats FACTOR_HUMAN, adds PERMISSION_RISKS mapping, restructures factor card label/tooltip layout, and adds conditional explanation sections for PermissionsBaseline (renders high_risk_permissions) and PermissionCombos (renders triggered_combos with formatted tokens and descriptions).
Deployment manifest
render.yaml
Adds new Render manifest for extension-shield Docker web service, including build config, runtime env vars (LLM/OpenAI/Supabase keys, PORT, MODE), CORS_ORIGINS: "*", and /health health check.
CI / Deploy workflow
.github/workflows/deploy.yml
Renames workflow/job from "Deploy to Railway" → "Deploy to Render"; removes Railway CLI steps and replaces with a webhook GET to secrets.RENDER_DEPLOY_HOOK and updated step messaging.
Sitemap timestamps
frontend/public/sitemap.xml
Updates all <lastmod> timestamps from 2026-03-15T22:20:40.206Z to 2026-04-24T19:36:11.774Z.
Removed config
railway.toml
Deletes Railway config-as-code file (removes Docker build config, deploy settings, runtime defaults and static section).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐇 I nibbled deps and scaled the stack,
Mapped the risks and straightened the track,
LayerModal shows each permission tale,
Render wakes the ship to set its sail,
Hop on—our shield's anew, no quail!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too vague and generic. While it mentions 'security vulnerabilities,' it doesn't convey the specific primary change: migrating from Railway to Render deployment platform and updating dependencies. Revise the title to be more specific and descriptive, such as 'Migrate deployment from Railway to Render and update dependencies' or focus on the most impactful change if it's intended to highlight only security fixes.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch fix/security-vulnerabilities

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

@github-actions github-actions Bot added bug Bug report or bug fix related work security Security-sensitive issue or change area: frontend Changes to the React frontend labels Apr 24, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds deployment configuration and updates frontend UI/dependencies as part of a “security vulnerabilities” cleanup.

Changes:

  • Add a Render deployment definition for the Docker-based web service.
  • Enhance the report Layer modal to explain permission risks and dangerous permission combinations.
  • Bump frontend dependencies (axios, postcss, vite) and update the lockfile accordingly.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.

File Description
render.yaml Introduces Render service config and environment variables for deployment.
frontend/src/components/report/LayerModal.jsx Adds permission-risk and dangerous-combo explanations in the modal UI.
frontend/package.json Updates dependency versions to address known vulnerabilities.
frontend/package-lock.json Lockfile updates reflecting dependency bumps (incl. transitive deps).
Files not reviewed (1)
  • frontend/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread render.yaml
- key: SUPABASE_SERVICE_ROLE_KEY
sync: false
- key: CORS_ORIGINS
value: "*" # Set specifically after you know your Render URL
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

CORS_ORIGINS is set to "*", but the backend’s CORS config explicitly treats * as invalid for production and always enables allow_credentials=True. Leaving this as * effectively allows credentialed cross-origin requests from any site in non-prod mode and will crash if ENV/EXTENSION_SHIELD_ENV is set to prod. Set this to a comma-separated allowlist of concrete origins (e.g. your Render URL + custom domain).

Suggested change
value: "*" # Set specifically after you know your Render URL
value: "https://extension-shield.onrender.com,https://your-custom-domain.example.com" # Replace with your actual Render URL and any other trusted frontend origins

Copilot uses AI. Check for mistakes.
Comment thread render.yaml
Comment on lines +10 to +12
- key: EXTSHIELD_MODE
value: cloud
- key: LLM_PROVIDER
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

This Render config doesn’t set ENV/EXTENSION_SHIELD_ENV to prod, so the backend will run with non-prod defaults (including relaxed validation). If this is intended for a real deployment, add an explicit production env setting and ensure required prod vars (e.g. EXTENSION_STORAGE_PATH, and CORS allowlist) are provided so Settings.validate() and the stricter CORS rules apply.

Copilot uses AI. Check for mistakes.
Comment thread render.yaml
Comment on lines +18 to +19
- key: SUPABASE_ANON_KEY
sync: false
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

SUPABASE_ANON_KEY is defined here, but the backend codebase does not read this env var (backend uses SUPABASE_SERVICE_ROLE_KEY; the anon key is frontend-only via VITE_SUPABASE_ANON_KEY). Keeping an unused env var in deployment config is confusing and increases the chance of misconfiguration; consider removing SUPABASE_ANON_KEY from this service and only keeping the VITE_ prefixed values for the frontend build.

Suggested change
- key: SUPABASE_ANON_KEY
sync: false

Copilot uses AI. Check for mistakes.
Comment on lines +179 to +183
<div className="lm-check-left" style={{ flexDirection: 'column', alignItems: 'flex-start', gap: '4px' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
<span className="lm-check-name">{item.label}</span>
{item.desc && <InfoTooltip text={item.desc} />}
</div>
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

The new layout changes are implemented with inline styles (flexDirection, alignItems, gap) on .lm-check-left and an extra wrapper <div>. Since these are static (not data-driven), consider moving them into LayerModal.scss as class rules to keep styling centralized and avoid creating new style objects each render.

Copilot uses AI. Check for mistakes.
Comment on lines +186 to +201
{item.raw?.name === 'PermissionsBaseline' && item.raw?.details?.high_risk_permissions?.length > 0 && (
<div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}>
{item.raw.details.high_risk_permissions.map(perm => (
<div key={perm} style={{ display: 'flex', gap: '6px', lineHeight: '1.2' }}>
<span style={{ fontWeight: 600, color: 'var(--risk-warn)', flexShrink: 0 }}>{perm}</span>
<span style={{ opacity: 0.6 }}>&rarr;</span>
<span>{PERMISSION_RISKS[perm] || `Has access to ${perm}`}</span>
</div>
))}
</div>
)}

{/* Dangerous Combos Explanation Engine */}
{item.raw?.name === 'PermissionCombos' && item.raw?.details?.triggered_combos?.length > 0 && (
<div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}>
{item.raw.details.triggered_combos.map(combo => {
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

The permission/combo explanation blocks add large, mostly-static inline style objects inside a nested .map(). This increases render work and makes future visual tweaks harder (styles are duplicated for baseline vs combos). Prefer extracting these styles into SCSS classes (and/or a small subcomponent) so the JSX focuses on content and the CSS handles presentation.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/package.json`:
- Line 75: The package.json now depends on vite@^7.3.2 but the engines.node
constraint still allows Node 18, causing incompatibility; update the
engines.node field to require Node 20.19+ (or Node 22.12+) so it meets Vite 7's
requirements by changing the engines.node constraint (refer to the
"engines.node" field) to something like a minimum of 20.19.0 or a union
">=20.19.0 || >=22.12.0" to ensure environments running "vite" (the "vite"
dependency) meet the supported Node versions.

In `@frontend/src/components/report/LayerModal.jsx`:
- Around line 186-216: The modal assumes high_risk_permissions and
triggered_combos are arrays and calls .map, which can crash if the backend
returns a non-array; update the rendering guards for the PermissionsBaseline and
PermissionCombos blocks (check item.raw?.name === 'PermissionsBaseline' /
'PermissionCombos') to verify
Array.isArray(item.raw?.details?.high_risk_permissions) and
Array.isArray(item.raw?.details?.triggered_combos') respectively (and length >
0) before mapping, or default to an empty array when mapping (e.g.,
(Array.isArray(...)? ... : []) ) so .map is never invoked on non-arrays; keep
references to PERMISSION_RISKS, high_risk_permissions, and triggered_combos in
the same JSX blocks.

In `@render.yaml`:
- Around line 22-23: The CORS_ORIGINS env var is set to the unsafe wildcard "*"
which will be rejected by the backend validation logic; replace the wildcard
with an explicit origin string or comma-separated list of allowed origins (e.g.,
your Render app URL) so the startup validation passes. Update the rendered key
CORS_ORIGINS in the manifest to a specific origin value (or populate it from a
secure secret/parameter) rather than "*", ensuring it matches the expectations
of the backend validation in the API startup code. Ensure the value format
(single origin or CSV) matches how the app parses CORS_ORIGINS.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bf852dae-399d-42a6-a29e-54d5cc8b1ce8

📥 Commits

Reviewing files that changed from the base of the PR and between 84f335c and 6552de7.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • frontend/package.json
  • frontend/src/components/report/LayerModal.jsx
  • render.yaml

Comment thread frontend/package.json
"tailwindcss": "^4.1.18",
"tailwindcss-animate": "^1.0.7",
"vite": "^7.1.7",
"vite": "^7.3.2",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify current engine + vite versions in manifest
jq -r '.engines.node, .devDependencies.vite' frontend/package.json

Repository: Stanzin7/ExtensionShield

Length of output: 84


🌐 Web query:

From official Vite docs, what Node.js versions are required for Vite 7.x?

💡 Result:

Vite 7.x requires Node.js version 20.19+ or 22.12+ (Node 18 is no longer supported).

Citations:


Update Node engine constraint to support Vite 7 requirements.

Line 75 upgrades to vite@^7.3.2, which requires Node.js 20.19+ or 22.12+. Line 9 still permits Node 18 (>=18.0.0), creating an incompatibility that will cause failures in any Node 18 environment.

🔧 Proposed fix
   "engines": {
-    "node": ">=18.0.0"
+    "node": ">=20.19.0"
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/package.json` at line 75, The package.json now depends on
vite@^7.3.2 but the engines.node constraint still allows Node 18, causing
incompatibility; update the engines.node field to require Node 20.19+ (or Node
22.12+) so it meets Vite 7's requirements by changing the engines.node
constraint (refer to the "engines.node" field) to something like a minimum of
20.19.0 or a union ">=20.19.0 || >=22.12.0" to ensure environments running
"vite" (the "vite" dependency) meet the supported Node versions.

Comment on lines +186 to +216
{item.raw?.name === 'PermissionsBaseline' && item.raw?.details?.high_risk_permissions?.length > 0 && (
<div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}>
{item.raw.details.high_risk_permissions.map(perm => (
<div key={perm} style={{ display: 'flex', gap: '6px', lineHeight: '1.2' }}>
<span style={{ fontWeight: 600, color: 'var(--risk-warn)', flexShrink: 0 }}>{perm}</span>
<span style={{ opacity: 0.6 }}>&rarr;</span>
<span>{PERMISSION_RISKS[perm] || `Has access to ${perm}`}</span>
</div>
))}
</div>
)}

{/* Dangerous Combos Explanation Engine */}
{item.raw?.name === 'PermissionCombos' && item.raw?.details?.triggered_combos?.length > 0 && (
<div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}>
{item.raw.details.triggered_combos.map(combo => {
const isBroad = combo === 'broad_host_access';
const comboName = isBroad ? 'Broad Host Access' : combo.split('+').join(' + ');
const comboDesc = isBroad
? 'Can access and modify data on all websites'
: 'High risk when these are used together';
return (
<div key={combo} style={{ display: 'flex', gap: '6px', lineHeight: '1.2' }}>
<span style={{ fontWeight: 600, color: 'var(--risk-warn)', flexShrink: 0 }}>{comboName}</span>
<span style={{ opacity: 0.6 }}>&rarr;</span>
<span>{comboDesc}</span>
</div>
)
})}
</div>
)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard .map() calls with array checks to avoid modal crashes.

Lines 186 and 199 gate with ?.length, but still assume array shape. If backend sends a non-array value, .map will throw and break rendering.

🛡️ Proposed fix
-                          {item.raw?.name === 'PermissionsBaseline' && item.raw?.details?.high_risk_permissions?.length > 0 && (
+                          {item.raw?.name === 'PermissionsBaseline' &&
+                            Array.isArray(item.raw?.details?.high_risk_permissions) &&
+                            item.raw.details.high_risk_permissions.length > 0 && (
                             <div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}>
                               {item.raw.details.high_risk_permissions.map(perm => (
@@
-                          {item.raw?.name === 'PermissionCombos' && item.raw?.details?.triggered_combos?.length > 0 && (
+                          {item.raw?.name === 'PermissionCombos' &&
+                            Array.isArray(item.raw?.details?.triggered_combos) &&
+                            item.raw.details.triggered_combos.length > 0 && (
                             <div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}>
                               {item.raw.details.triggered_combos.map(combo => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{item.raw?.name === 'PermissionsBaseline' && item.raw?.details?.high_risk_permissions?.length > 0 && (
<div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}>
{item.raw.details.high_risk_permissions.map(perm => (
<div key={perm} style={{ display: 'flex', gap: '6px', lineHeight: '1.2' }}>
<span style={{ fontWeight: 600, color: 'var(--risk-warn)', flexShrink: 0 }}>{perm}</span>
<span style={{ opacity: 0.6 }}>&rarr;</span>
<span>{PERMISSION_RISKS[perm] || `Has access to ${perm}`}</span>
</div>
))}
</div>
)}
{/* Dangerous Combos Explanation Engine */}
{item.raw?.name === 'PermissionCombos' && item.raw?.details?.triggered_combos?.length > 0 && (
<div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}>
{item.raw.details.triggered_combos.map(combo => {
const isBroad = combo === 'broad_host_access';
const comboName = isBroad ? 'Broad Host Access' : combo.split('+').join(' + ');
const comboDesc = isBroad
? 'Can access and modify data on all websites'
: 'High risk when these are used together';
return (
<div key={combo} style={{ display: 'flex', gap: '6px', lineHeight: '1.2' }}>
<span style={{ fontWeight: 600, color: 'var(--risk-warn)', flexShrink: 0 }}>{comboName}</span>
<span style={{ opacity: 0.6 }}>&rarr;</span>
<span>{comboDesc}</span>
</div>
)
})}
</div>
)}
{item.raw?.name === 'PermissionsBaseline' &&
Array.isArray(item.raw?.details?.high_risk_permissions) &&
item.raw.details.high_risk_permissions.length > 0 && (
<div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}>
{item.raw.details.high_risk_permissions.map(perm => (
<div key={perm} style={{ display: 'flex', gap: '6px', lineHeight: '1.2' }}>
<span style={{ fontWeight: 600, color: 'var(--risk-warn)', flexShrink: 0 }}>{perm}</span>
<span style={{ opacity: 0.6 }}>&rarr;</span>
<span>{PERMISSION_RISKS[perm] || `Has access to ${perm}`}</span>
</div>
))}
</div>
)}
{/* Dangerous Combos Explanation Engine */}
{item.raw?.name === 'PermissionCombos' &&
Array.isArray(item.raw?.details?.triggered_combos) &&
item.raw.details.triggered_combos.length > 0 && (
<div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}>
{item.raw.details.triggered_combos.map(combo => {
const isBroad = combo === 'broad_host_access';
const comboName = isBroad ? 'Broad Host Access' : combo.split('+').join(' + ');
const comboDesc = isBroad
? 'Can access and modify data on all websites'
: 'High risk when these are used together';
return (
<div key={combo} style={{ display: 'flex', gap: '6px', lineHeight: '1.2' }}>
<span style={{ fontWeight: 600, color: 'var(--risk-warn)', flexShrink: 0 }}>{comboName}</span>
<span style={{ opacity: 0.6 }}>&rarr;</span>
<span>{comboDesc}</span>
</div>
)
})}
</div>
)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/report/LayerModal.jsx` around lines 186 - 216, The
modal assumes high_risk_permissions and triggered_combos are arrays and calls
.map, which can crash if the backend returns a non-array; update the rendering
guards for the PermissionsBaseline and PermissionCombos blocks (check
item.raw?.name === 'PermissionsBaseline' / 'PermissionCombos') to verify
Array.isArray(item.raw?.details?.high_risk_permissions) and
Array.isArray(item.raw?.details?.triggered_combos') respectively (and length >
0) before mapping, or default to an empty array when mapping (e.g.,
(Array.isArray(...)? ... : []) ) so .map is never invoked on non-arrays; keep
references to PERMISSION_RISKS, high_risk_permissions, and triggered_combos in
the same JSX blocks.

Comment thread render.yaml
Comment on lines +22 to +23
- key: CORS_ORIGINS
value: "*" # Set specifically after you know your Render URL
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Replace wildcard CORS_ORIGINS for cloud deployment.

At Line 23, value: "*" is unsafe and conflicts with backend prod validation (src/extension_shield/api/main.py:320-330), which explicitly rejects * and can crash startup.

🔒 Proposed fix
       - key: CORS_ORIGINS
-        value: "*" # Set specifically after you know your Render URL
+        sync: false # Set explicit comma-separated allowlist in Render env (no "*")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- key: CORS_ORIGINS
value: "*" # Set specifically after you know your Render URL
- key: CORS_ORIGINS
value: "https://yourdomain.onrender.com" # Set specifically after you know your Render URL
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@render.yaml` around lines 22 - 23, The CORS_ORIGINS env var is set to the
unsafe wildcard "*" which will be rejected by the backend validation logic;
replace the wildcard with an explicit origin string or comma-separated list of
allowed origins (e.g., your Render app URL) so the startup validation passes.
Update the rendered key CORS_ORIGINS in the manifest to a specific origin value
(or populate it from a secure secret/parameter) rather than "*", ensuring it
matches the expectations of the backend validation in the API startup code.
Ensure the value format (single origin or CSV) matches how the app parses
CORS_ORIGINS.

@github-actions github-actions Bot added the area: infra CI, deployment, database, or repository automation changes label Apr 25, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/deploy.yml:
- Line 4: Update any leftover comments that still reference "Railway" so they
consistently refer to "Render"; search for comment text containing the word
"Railway" near the workflow header (the YAML key name: Deploy to Render) and
elsewhere in the file (including the comment block near the end that previously
referenced Railway) and replace those comment strings with "Render" to avoid
config drift.
- Around line 108-110: Update the "Trigger Render Deploy Hook" step's curl
invocation to include network timeouts and retry controls: replace the bare curl
-f -X GET "${{ secrets.RENDER_DEPLOY_HOOK }}" with a hardened curl that sets a
connect timeout, overall max time, and retry policy (for example:
--connect-timeout 10 --max-time 30 --retry 3 --retry-delay 5 --retry-connrefused
-sS -f -X GET "${{ secrets.RENDER_DEPLOY_HOOK }}"), so transient network issues
are retried but the job fails quickly on persistent errors while preserving the
original non-zero exit behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a7a0532e-4595-4dc5-b51d-a64c7004ca45

📥 Commits

Reviewing files that changed from the base of the PR and between 6552de7 and 8c87a3a.

📒 Files selected for processing (3)
  • .github/workflows/deploy.yml
  • frontend/public/sitemap.xml
  • railway.toml
💤 Files with no reviewable changes (1)
  • railway.toml
✅ Files skipped from review due to trivial changes (1)
  • frontend/public/sitemap.xml

# Deploys to Railway on push to main

name: Deploy to Railway
name: Deploy to Render
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Update remaining Railway references in comments to avoid config drift.

The workflow/job names were correctly moved to Render, but nearby file comments still say Railway (e.g., Line 2 and Line 96). Please align those comments with the new deployment target.

Also applies to: 99-99

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy.yml at line 4, Update any leftover comments that
still reference "Railway" so they consistently refer to "Render"; search for
comment text containing the word "Railway" near the workflow header (the YAML
key name: Deploy to Render) and elsewhere in the file (including the comment
block near the end that previously referenced Railway) and replace those comment
strings with "Render" to avoid config drift.

Comment on lines +108 to +110
- name: Trigger Render Deploy Hook
run: |
curl -f -X GET "${{ secrets.RENDER_DEPLOY_HOOK }}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Harden deploy-hook call with timeout and retry controls.

This external call currently has no timeout/retry strategy, so transient network issues can cause flaky or stalled deploy jobs.

🔧 Proposed patch
       - name: Trigger Render Deploy Hook
         run: |
-          curl -f -X GET "${{ secrets.RENDER_DEPLOY_HOOK }}"
+          curl --fail --silent --show-error \
+            --retry 3 --retry-delay 2 --retry-all-errors \
+            --connect-timeout 10 --max-time 60 \
+            -X GET "${{ secrets.RENDER_DEPLOY_HOOK }}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Trigger Render Deploy Hook
run: |
curl -f -X GET "${{ secrets.RENDER_DEPLOY_HOOK }}"
- name: Trigger Render Deploy Hook
run: |
curl --fail --silent --show-error \
--retry 3 --retry-delay 2 --retry-all-errors \
--connect-timeout 10 --max-time 60 \
-X GET "${{ secrets.RENDER_DEPLOY_HOOK }}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy.yml around lines 108 - 110, Update the "Trigger
Render Deploy Hook" step's curl invocation to include network timeouts and retry
controls: replace the bare curl -f -X GET "${{ secrets.RENDER_DEPLOY_HOOK }}"
with a hardened curl that sets a connect timeout, overall max time, and retry
policy (for example: --connect-timeout 10 --max-time 30 --retry 3 --retry-delay
5 --retry-connrefused -sS -f -X GET "${{ secrets.RENDER_DEPLOY_HOOK }}"), so
transient network issues are retried but the job fails quickly on persistent
errors while preserving the original non-zero exit behavior.

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

Labels

area: frontend Changes to the React frontend area: infra CI, deployment, database, or repository automation changes bug Bug report or bug fix related work security Security-sensitive issue or change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants