Skip to content

Conversation

@github-actions
Copy link
Contributor

This is an automated pull request to merge mariano/smart-suggestions into dev.
It was created by the [Auto Pull Request] action.

- Load .env manually before NestJS bootstrap
- Add automatic JWKS retry on key mismatch
- Remove redundant ConfigModule envFilePath
- Auto-refresh token and retry request on 401
- Add race condition protection and cooldown
- Fix useTask hook to wait for orgId from URL params
- Generate task-specific suggestions using GPT-4o-mini
- Load suggestions asynchronously for faster page load
- Add loading state for automation page
- Ensure suggestions match exact task topic
- Exclude screenshots, require API integrations only
- Add fallback for broken vendor logo images
- Show animated skeleton cards while AI suggestions are loading
- Match card structure and layout for smooth transition
- Load suggestions asynchronously without blocking page render
@vercel
Copy link

vercel bot commented Nov 12, 2025

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

Project Deployment Preview Comments Updated (UTC)
app Ready Ready Preview Comment Nov 12, 2025 11:26pm
portal Ready Ready Preview Comment Nov 12, 2025 11:26pm

@comp-ai-code-review
Copy link

comp-ai-code-review bot commented Nov 12, 2025

🔒 Comp AI - Security Review

🔴 Risk Level: HIGH

OSV: GHSA-rwvc-j5jr-mgvh affecting ai@5.0.0. Code issues: hardcoded client token in EmptyState.tsx and unsanitized route/header params used in DB/URL concatenation.


📦 Dependency Vulnerabilities

🟢 NPM Packages (LOW)

Risk Score: 2/10 | Summary: 1 low CVE found

Package Version CVE Severity CVSS Summary Fixed In
ai 5.0.0 GHSA-rwvc-j5jr-mgvh LOW N/A Vercel’s AI SDK's filetype whitelists can be bypassed when uploading files 5.0.52

🛡️ Code Security Analysis

View 13 file(s) with issues

🔴 apps/api/src/auth/hybrid-auth.guard.ts (HIGH Risk)

# Issue Risk Level
1 Unvalidated BETTER_AUTH_URL trusted for JWKS (malicious JWKS possible) HIGH
2 Forced fresh JWKS fetches (cacheMaxAge=0) enable SSRF/DoS amplification HIGH
3 Audience/issuer tied to BETTER_AUTH_URL; misconfig can allow token misuse HIGH
4 X-Organization-Id header used directly without validation HIGH
5 Request header values used in DB query; risk if ORM misconfigured (injection) HIGH
6 No rate limiting on API key auth allows brute-force or enumeration HIGH
7 Verbose verification logs may leak internal infrastructure details HIGH

Recommendations:

  1. Validate and whitelist BETTER_AUTH_URL / hosts before building the JWKS URL. Only allow known, trusted hosts (and require HTTPS). Fail closed if the configured host is not allowed.
  2. Avoid forcing unbounded fresh JWKS fetches. Use reasonable cache times and exponential backoff on retries. Limit the number of immediate retry attempts (e.g., retry once) and add request timeouts to avoid DoS/SSRF amplification.
  3. Do not rely on a mutable config value alone for issuer/audience checks. Configure explicit expected issuer and audience values (separate from a URL used for network calls) and validate them strictly.
  4. Validate and canonicalize X-Organization-Id (e.g., ensure it matches expected UUID format and belongs to the requesting tenant) before using it. Prefer deriving organization context from server-side user->org relationships rather than trusting headers.
  5. Although most ORMs parameterize queries, do not assume protection. Coerce and validate header-derived values (types/formats) before using them in DB queries. Add application-level checks that userId and organizationId correspond to a real relationship.
  6. Add rate limiting / throttling for API key authentication paths and requests that attempt API key validation. Implement per-key and per-IP limits, and incremental backoff to mitigate brute-force and enumeration attempts.
  7. Reduce log verbosity for authentication failures. Avoid printing internal URLs, stack traces, or detailed error codes to client-facing logs. Keep detailed errors in internal logs with access controls and surface generic messages to clients.

🔴 apps/api/src/main.ts (HIGH Risk)

# Issue Risk Level
1 Permissive CORS (origin: true) with credentials=true — CSRF risk HIGH
2 Public Swagger UI (/api/docs) enabled in all envs, exposing endpoints HIGH
3 Swagger persistAuthorization=true may store auth in browser HIGH
4 Missing HTTP security headers (no helmet/CSP/HSTS) HIGH
5 Large JSON/body limit (15mb) may enable DoS or resource exhaustion HIGH
6 OpenAPI written to repo in dev may leak API details or secrets HIGH

Recommendations:

  1. Restrict CORS: set origin to an explicit allowlist (not true). If you must allow multiple origins, validate the Origin header and only echo allowed origins. Avoid credentials: true unless strictly necessary; prefer token-based auth in Authorization header or use SameSite=strict cookies and CSRF protections.
  2. Enable CSRF protections for cookie-based auth (CSRF tokens, SameSite cookies, double-submit cookie, or frameworks' CSRF middleware).
  3. Disable or restrict Swagger UI in non-development environments. Protect /api/docs with authentication (IP allowlist or auth middleware) or gate it behind a VPN.
  4. Set swaggerOptions.persistAuthorization to false so the UI does not persist tokens in browser storage.
  5. Add security HTTP headers via middleware (helmet) and configure CSP/HSTS/Referrer-Policy/X-Frame-Options as appropriate.
  6. Add rate limiting, request size quotas, timeouts and validation for large payloads. Lower the body-parser limits if possible and implement streaming/uploads for large files instead of large JSON bodies.
  7. Avoid writing OpenAPI/json with potentially sensitive details into the repository. If you must export docs in development, store them outside the project tree or ensure they are gitignored and do not contain secrets (redact server URLs, API keys, internal-only endpoints). Consider generating docs in a protected CI artifact store instead.

🔴 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/actions/generate-suggestions.ts (HIGH Risk)

# Issue Risk Level
1 No authorization check for organizationId; callers can access any org data HIGH
2 taskDescription used unsanitized in LLM prompt (prompt injection risk) HIGH
3 DB content (vendors/context) embedded in prompts without sanitization HIGH
4 No input validation for organizationId and taskDescription before queries HIGH
5 Verbose logs include timings and counts that may leak sensitive info HIGH

Recommendations:

  1. Enforce authorization: verify the caller is authorized to access the provided organizationId before performing any DB queries. If authorization is enforced elsewhere, assert it or document the contract—do not rely on implicit upstream guarantees.
  2. Validate inputs: apply strict validation to organizationId (e.g., UUID v4 check or internal ID format) and taskDescription (type, max length). Use a validation library (zod is already present—add schemas for inputs) and reject or sanitize invalid values before use.
  3. Sanitize/normalize content embedded in prompts: redact or normalize potentially sensitive/hostile content from vendor.name, vendor.website, vendor.description, and context.question/answer before concatenating into the LLM prompt. Actions include truncation, removal/redaction of PII (emails, tokens, secrets), escaping/newline normalization, and removing control sequences that could influence the model (e.g., instruction-like markers). Maintain a whitelist of allowed fields/characters where feasible.
  4. Mitigate prompt injection: treat taskDescription and DB-derived strings as untrusted. Prefer structured prompts that clearly separate user content from system instructions, and use explicit system-level guardrails instructing the model to ignore embedded instructions. Additionally, run user content through a content/moderation filter prior to inclusion and consider sanitizing or encoding user content (e.g., base64 or JSON-escape) and then presenting it in a controlled manner to the model.
  5. Limit prompt size and complexity: enforce truncation/summary of long context or vendor lists (e.g., include top N vendors or a summarized version) to avoid leaking large amounts of data and to reduce exposure to malicious content.
  6. Log hygiene: reduce log verbosity in production. Avoid logging full DB contents, exact counts, prompt contents, or precise timing metrics that could be sensitive. If timing/metrics are needed, aggregate or redact them and restrict logs to authorized personnel. Do not log raw taskDescription or DB fields in plain text.
  7. Rate limiting and auditing: add per-user and per-organization rate limits on calls that trigger AI generation, and maintain immutable audit logs (who requested suggestions, orgId, timestamp) stored securely for incident investigation.
  8. Continue/extend schema validation for model outputs: keep using structured schema (zod + generateObject) to validate AI outputs. Also handle validation failures gracefully and log them (without leaking sensitive inputs).
  9. Secure DB access patterns: although the ORM prevents raw SQL injection in these calls, still validate inputs before using them in queries. Ensure the database layer enforces row-level security or tenant scoping as an additional guard (e.g., RLS policies that enforce org ownership).
  10. Apply defense-in-depth: combine the above (authorization, validation, sanitization, logging policy, rate limits, RLS) so no single missing control can expose other orgs' data or allow model manipulation.

🟡 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/chat.tsx (MEDIUM Risk)

# Issue Risk Level
1 Unvalidated user input sent to validateAndSubmitMessage/sendMessage MEDIUM
2 Possible stored XSS if Message renders unescaped content MEDIUM
3 Prompt injection risk: raw prompts forwarded to AI/backend MEDIUM
4 Potential secret exposure via onSecretAdded handler/storage MEDIUM
5 Ephemeral automationId 'new' state may be manipulated MEDIUM

Recommendations:

  1. Sanitize and escape message content before rendering
  2. Validate and normalize inputs server-side before processing
  3. Redact or mask secrets client/server-side before storing
  4. Enforce auth checks on automationId updates and actions
  5. Apply CSP and avoid unsafe innerHTML/eval in components

🟡 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/AutomationPageClient.tsx (MEDIUM Risk)

# Issue Risk Level
1 No input validation before sending taskDescription/orgId to backend MEDIUM
2 Potential XSS via suggestions passed to Chat MEDIUM
3 No abort/timeout for generateAutomationSuggestions request MEDIUM

Recommendations:

  1. Enforce server-side validation and sanitization for taskDescription and orgId. Never trust client input; validate length, allowed characters, and content on the server before use.
  2. Add client-side validation as a convenience (e.g., trim, max length) but do not rely on it for security.
  3. Treat suggestion content as untrusted. Ensure the Chat component properly escapes or sanitizes suggestion text before rendering. Prefer rendering plain text rather than injecting HTML. If HTML must be rendered, sanitize with a vetted library (e.g., DOMPurify) on the server or before insertion, and avoid dangerouslySetInnerHTML.
  4. If you control the Chat component, audit it to confirm it does not use innerHTML/dangerouslySetInnerHTML on untrusted content or that it sanitizes inputs. If you cannot confirm sanitization, assume XSS is possible and sanitize at the boundary (server or immediately before rendering).
  5. Add request cancellation and timeouts when calling generateAutomationSuggestions: use an AbortController to cancel on component unmount or when a new request is started, and implement a sensible client-side timeout fallback. Also ensure the server enforces reasonable request timeouts/rate limiting.
  6. Avoid logging potentially sensitive payloads. Although this file currently only logs timing and error objects, review other code paths to ensure task descriptions, org IDs, or user data are not logged in plain text to the console in production.

🔴 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/chat/EmptyState.tsx (HIGH Risk)

# Issue Risk Level
1 Hardcoded API token in image URLs HIGH
2 Unvalidated vendorWebsite/vendorName used to build image URL HIGH
3 Exposed token combined with user-controlled domain sent to third party HIGH
4 Unvalidated suggestion prompts passed to onExampleClick HIGH

Recommendations:

  1. Remove hardcoded token from client bundles. Do not embed secret or privileged tokens in frontend code.
  2. Move token-protected logo fetches to a backend proxy/service. The frontend should request logos from your backend, which attaches any tokens, enforces rate-limits, and can validate/whitelist domains.
  3. Validate and canonicalize vendorWebsite/vendorName server-side. Parse vendorWebsite with a safe URL parser and enforce a whitelist of allowed hostnames before using it to request resources.
  4. URI-encode and strictly validate any domain/path segments before interpolating into URLs. Never directly concatenate raw user input into third-party request URLs.
  5. Sanitize and validate suggestion data before use or render. Treat suggestions as untrusted input — escape any values rendered into the DOM and validate prompts before passing them to handlers that perform further actions.
  6. Rotate the exposed token immediately if it was used in production. Monitor for misuse and treat the token as compromised.
  7. Add logging/monitoring on backend proxy for suspicious domains/requests and enforce rate limits to mitigate abuse.

🟡 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/chat/message-part/prompt-secret.tsx (MEDIUM Risk)

# Issue Risk Level
1 Client sets organizationId from orgId prop (possible IDOR/auth bypass) MEDIUM
2 No CSRF token or auth header sent with POST /api/secrets MEDIUM
3 Only client-side sanitization of secret name (can be bypassed) MEDIUM
4 AI-provided input (input prop) used without validation MEDIUM
5 Secret value may be retained in client memory or error logs MEDIUM

Recommendations:

  1. Server-side: Always enforce organization ownership/authorization for /api/secrets and ignore or verify any client-supplied organizationId. Treat the client orgId as untrusted.
  2. Authentication/CSRF: Require authenticated requests to /api/secrets (e.g., Authorization header or session cookie) and validate CSRF tokens or use SameSite=strict cookies + anti-CSRF tokens depending on your auth model. Ensure the endpoint rejects unauthenticated or invalid sessions.
  3. Server-side validation: Normalize and validate secret names on the server (e.g., enforce uppercase, allowed charset, length limits, uniqueness). Do not rely solely on client-side replace()/regex transformations.
  4. Validate AI/user input: Treat the input prop as untrusted. Validate and sanitize description, category, exampleValue, and any AI-provided names on the server. Apply length limits, allowed characters, and reject/escape unexpected content.
  5. Protect secret values in transit and at rest: Ensure TLS, encrypt secrets server-side, and do not log secret values. Minimize retention on the client (clear state immediately after use) and avoid including secret values in error messages or console logs.
  6. Fetch options: Ensure requests include appropriate credentials if relying on cookies (fetch with credentials: 'include' when required) and ensure CORS and server-side auth checks are configured correctly.
  7. Audit & monitoring: Add server-side rate limiting, anomaly detection, and audit logging (without sensitive values) to detect abuse or IDOR attempts.

🟡 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/evaluation/EvaluationCriteriaCard.tsx (MEDIUM Risk)

# Issue Risk Level
1 Unvalidated user input sent to updateEvaluationCriteria MEDIUM
2 Backend error messages displayed directly to users MEDIUM

Recommendations:

  1. Validate and sanitize criteria on client and server
  2. Enforce input length and character limits before send
  3. Do not display raw backend errors; show generic messages
  4. Server-side validate and escape input to prevent injections

🔴 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/page.tsx (HIGH Risk)

# Issue Risk Level
1 Missing auth/authorization check before DB read HIGH
2 Unsanitized URL params used in DB query (possible SQL injection) HIGH
3 Unvalidated automationId passed to loadChatHistory HIGH
4 Possible stored XSS: messages or taskDescription sent to client unsanitized HIGH

Recommendations:

  1. Enforce authentication and authorization before DB access: verify the request/session belongs to a user who has access to orgId and the task (e.g., middleware or server-side session check). Return 403/redirect if unauthorized.
  2. Validate and coerce route params before use: apply strict schemas (zod/joi) or explicit checks (UUID regex / parseInt) for orgId, taskId, automationId. Fail fast on invalid types/lengths.
  3. Keep using parameterized ORM queries but still validate params: although most ORMs parameterize queries, validate inputs for type/format to prevent logic errors and to satisfy the principle of fail-safe defaults.
  4. Validate automationId before calling loadChatHistory: ensure it matches expected format and that callers are authorized to view that automation; treat special values (like 'new') explicitly.
  5. Sanitize/escape any user-controllable content before rendering: avoid rendering raw HTML on the client; do not use dangerouslySetInnerHTML with untrusted strings. If HTML is required, sanitize server-side or client-side with a proven sanitizer (e.g., DOMPurify) and enforce an allowlist.
  6. Apply size limits and rate limiting for params and payloads to mitigate resource abuse and potential DoS from extremely large inputs.
  7. Add robust error handling and logging: return safe error responses for invalid params and unexpected failures, avoid leaking internal details.
  8. Add unit/integration tests that exercise authorization and input validation paths for these endpoints/handlers.

🟡 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/hooks/use-task.ts (MEDIUM Risk)

# Issue Risk Level
1 Unvalidated orgId/taskId used directly in API path and SWR key MEDIUM

Recommendations:

  1. Validate orgId and taskId as soon as you read them from the URL (allowlist characters, enforce length limits, e.g. /^[A-Za-z0-9-_]{1,64}$/). Reject or normalize anything that doesn't match.
  2. Encode path segments before building URLs: use encodeURIComponent(taskId) and encodeURIComponent(orgId) when constructing /v1/tasks/${taskId} (or let a well-tested router/HTTP client do the encoding).
  3. Sanitize values used in client-side cache keys (e.g. normalize or hash IDs) to avoid cache poisoning/confusion: use a canonical representation rather than raw user input.
  4. Avoid propagating raw server error strings to the UI. Log or send full error details to server logs/monitoring, and surface a generic error message to the user (e.g. 'Failed to fetch task').
  5. Enforce strict server-side validation and authorization on orgId/taskId. The server must never trust client-provided IDs — validate format, existence, and that the caller is authorized for the requested org/task.
  6. Ensure server-side handlers use parameterized queries or ORM APIs to avoid injection if these IDs are ever used in DB queries, and validate types before use in backend code.
  7. Apply rate limiting and other abuse controls on the API endpoints to limit impact of repeated malformed requests.
  8. Add unit/integration tests that exercise malformed or malicious orgId/taskId values to confirm safe handling and error messages.

🟡 apps/app/src/hooks/use-organization-members.ts (MEDIUM Risk)

# Issue Risk Level
1 Unsanitized orgId used in API request and SWR cache key MEDIUM
2 User-controlled orgId may enable server-side injection if backend is unsafe MEDIUM
3 Backend error details logged to console risking info disclosure MEDIUM

Recommendations:

  1. Validate and canonicalize orgId on the client: apply a strict allowlist/regex (e.g., UUID or numeric ID) before using in cache keys or sending to the API. Reject or normalize unexpected values early.
  2. Ensure the client encodes the orgId when constructing requests (e.g., use encodeURIComponent or pass as a structured query/body param via your API client) rather than concatenating raw strings.
  3. Avoid logging raw backend error payloads to the browser console in production. Log only safe, generic error messages client-side and send detailed errors to secure server-side logs/monitoring.
  4. Enforce server-side validation and strong input sanitization for orgId. Treat any client value as untrusted and validate/allowlist on the backend.
  5. Ensure the backend uses parameterized queries / ORM APIs (no string interpolation into SQL) to prevent SQL injection, and escapes or validates values used in any context that could lead to injection.
  6. Add/verify authorization checks on the backend to confirm the requesting user has access to the requested organization's members before returning data.
  7. Review the implementation of api.get to confirm it encodes parameters correctly and does not introduce unsafe concatenation or header injection.

🟡 apps/app/src/lib/api-client.ts (MEDIUM Risk)

# Issue Risk Level
1 Unvalidated endpoint concatenation may allow attacker-controlled URLs MEDIUM
2 Unvalidated organizationId header (X-Organization-Id) from callers MEDIUM
3 credentials: 'include' will send cookies, enabling CSRF if server trusts cookies MEDIUM
4 Verbose error messages and console logs may leak internal info or tokens MEDIUM
5 No fetch timeout or response size limit (client can hang or OOM on large responses) MEDIUM

Recommendations:

  1. Validate/sanitize endpoint before concatenation: require a relative path (e.g., startsWith('/')), reject absolute URLs (http:// or https://) or control characters, and normalize/encode path segments. Prefer passing only known internal route identifiers rather than free-form strings.
  2. Validate and constrain organizationId values: enforce a whitelist, strict format/length (e.g., UUID regex), and reject or canonicalize unexpected characters before setting X-Organization-Id header.
  3. Reconsider credentials: 'include'. If not needed, remove it. If cookies are required, ensure the server enforces SameSite=strict/lax where appropriate and implement CSRF protections (anti-CSRF tokens, double-submit cookies, or use SameSite + secure session handling).
  4. Reduce console logging of auth/internal errors and never log tokens or sensitive payloads. Replace detailed error logs with sanitized messages and, if needed, send details to a secure diagnostics service with access controls.
  5. Add request timeouts and response-size protections: use AbortController to enforce timeouts, and if handling large responses, read the stream with a reader and enforce a maximum byte limit to avoid OOM. Also validate Content-Type and expected response shapes before parsing.
  6. When retrying after a 401, avoid logging tokens and ensure retry logic doesn't accidentally leak refreshed tokens. Consider scoping retry to same-origin requests and limit retries.
  7. Enforce stricter Content-Type handling: if sending JSON, ensure bodies are JSON serializable and callers cannot override content-type to something unsafe. Consider checking for FormData or binary types before setting application/json.

🔴 apps/app/src/utils/jwt-manager.ts (HIGH Risk)

# Issue Risk Level
1 JWT stored in localStorage (vulnerable to XSS token theft) HIGH
2 Refresh uses credentials:'include' (may enable CSRF-triggered actions) HIGH
3 JWT payload decoded without signature verification HIGH
4 Decoding JWT via atob without validation may throw DoS HIGH

Recommendations:

  1. Do not store long-lived access tokens in localStorage. Use httpOnly, Secure cookies with SameSite=strict/lax for auth tokens. If you must keep tokens client-side, keep only short-lived tokens and store refresh tokens securely on the server.
  2. Protect the /api/auth/token endpoint from CSRF. Prefer that the server issues tokens via httpOnly cookies or require a CSRF token/Double Submit Cookie for any endpoint that relies on browser cookies (avoid relying solely on credentials:'include' on GET endpoints). Consider using POST + CSRF token for stateful operations.
  3. Never trust client-side decoded JWT payloads for authorization decisions. Validate JWT signatures and claims server-side using the server's verification keys/algorithms before using any claim values.
  4. Harden client decoding: validate token structure before using atob (check parts.length === 3), use a base64url-safe decoder, and handle parsing errors gracefully. Prefer not to rely on client-side decoding for security-sensitive logic.
  5. Use short token lifetimes and rotate refresh tokens securely on the server. Consider rotating refresh tokens on use and binding refresh tokens to client/session context.
  6. Mitigate XSS: implement a strong Content Security Policy (CSP), sanitize/escape all user input, use frameworks' built-in templating protections, and run regular XSS testing.
  7. Log and monitor anomalous token refresh behavior (frequent refreshes, many different IPs) and implement rate-limiting or refresh cooldowns server-side if necessary.

💡 Recommendations

View 3 recommendation(s)
  1. Upgrade the vulnerable dependency: bump ai to >= 5.0.52 in package.json and reinstall so the GHSA-rwvc-j5jr-mgvh fix is applied.
  2. Remove the hardcoded token in apps/app/src/app/(app)/[orgId]/tasks/.../EmptyState.tsx. Do not embed secrets in frontend bundles — move token usage out of client code (e.g., fetch images via a server-side endpoint that injects credentials) and rotate the exposed token immediately.
  3. Validate and canonicalize all user-controlled IDs and endpoints before use: enforce strict formats (e.g., UUID regex) for orgId/taskId/automationId, use encodeURIComponent for path segments, and require relative paths (e.g., path.startsWith('/')) before concatenating in api-client or when building DB queries. Also validate X-Organization-Id headers server-side and never trust raw header/URL params in DB queries.

Powered by Comp AI - AI that handles compliance for you. Reviewed Nov 12, 2025

@comp-ai-code-review
Copy link

comp-ai-code-review bot commented Nov 12, 2025

🔒 Comp AI - Security Review

🔴 Risk Level: HIGH

OSV: ai@5.0.0 -> GHSA-rwvc-j5jr-mgvh (low). Hardcoded front-end API token found. Route/org/task IDs used without validation before DB/API calls.


📦 Dependency Vulnerabilities

🟢 NPM Packages (LOW)

Risk Score: 2/10 | Summary: 1 low CVE found

Package Version CVE Severity CVSS Summary Fixed In
ai 5.0.0 GHSA-rwvc-j5jr-mgvh LOW N/A Vercel’s AI SDK's filetype whitelists can be bypassed when uploading files 5.0.52

🛡️ Code Security Analysis

View 11 file(s) with issues

🔴 apps/api/src/auth/hybrid-auth.guard.ts (HIGH Risk)

# Issue Risk Level
1 Remote JWKS fetch uses BETTER_AUTH_URL allowing SSRF HIGH
2 Trusting env/config JWKS endpoint enables token forgery if compromised HIGH
3 Retry logic disables cache, enabling JWKS fetch storms (DoS/SSRF) HIGH
4 Excessive error logging may leak auth or infrastructure details HIGH
5 No rate limiting or brute-force protections for API key authentication HIGH
6 Headers cast to string without validation (malformed arrays may crash) HIGH

Recommendations:

  1. Whitelist/validate BETTER_AUTH_URL: only allow JWKS hostnames you control (compare parsed hostname against an allowlist). Reject or fail safe if BETTER_AUTH_URL points to private IP ranges or unexpected hosts to reduce SSRF risk.
  2. Harden JWKS usage: validate JWKS URL at startup, restrict to https, and enforce a strict set of accepted issuers/audiences/algorithms. Consider embedding known JWKS keys for critical services or pinning keys where appropriate.
  3. Improve JWKS caching/backoff: implement exponential backoff and a maximum retry limit instead of immediately creating a fresh JWKS with cache disabled. Add timeouts for remote fetches and circuit-breaker behavior to avoid fetch storms/DoS.
  4. Reduce logging verbosity and redact sensitive details: do not log raw error objects or tokens. Log only minimal actionable info (error codes, sanitized messages). Ensure logs do not reveal internal hostnames, stack traces, or authentication tokens in production.
  5. Require stronger organization binding: prefer deriving organization context from the JWT (or include an explicit org claim) instead of relying on client headers. If client header must be accepted, continue verifying membership (as this code does) and consider strict validation/normalization of the header value.
  6. Add rate limiting and brute-force protections on API key authentication paths: global and per-IP rate limits, failed attempt tracking, and exponential backoff. Monitor for repeated invalid API key attempts and throttle or temporarily block abusive clients.
  7. Normalize and validate headers before use: treat header values as string | string[] | undefined. Coerce arrays safely (e.g., use first value or reject), check types before calling string methods like startsWith, and validate length/format of API keys and tokens before processing.
  8. Avoid retrying verification blindly for every verification error: only retry on deterministic key-mismatch errors and cap retries. Consider logging retry events with rate-limiting to avoid log floods.
  9. Add request-level timeouts to JWKS fetches and ensure the HTTP client used by createRemoteJWKSet has reasonable network timeout settings to avoid resource exhaustion.

🔴 apps/api/src/main.ts (HIGH Risk)

# Issue Risk Level
1 Permissive CORS: origin reflected (origin: true) with credentials: true HIGH
2 Swagger UI exposed at /api/docs with persistAuthorization enabled (auth token risk) HIGH
3 Large body limits (15mb) allow large base64 uploads, risk memory DoS HIGH
4 No rate limiting/throttling configured (brute-force/DoS risk) HIGH
5 OpenAPI written to repo path in non-prod may leak internal API or sensitive schemas HIGH

Recommendations:

  1. CORS: Do not use origin: true together with credentials: true. Restrict origins to an allowlist (use a function that checks against a configured list) and only enable credentials for those trusted origins. Example: origin: (origin, cb) => { if (allowed.includes(origin)) cb(null, true); else cb(null, false); }.
  2. Swagger UI: Disable/limit Swagger UI in production. Only expose docs behind authentication (e.g., basic auth, IP allowlist, or require a token) or serve docs only in non-production environments. Also consider removing persistAuthorization or set swaggerOptions.persistAuthorization = false to avoid storing auth tokens in the browser UI.
  3. Request body limits & uploads: Lower JSON/urlencoded body limits or accept file uploads via streaming/multipart handlers (e.g., multer) instead of base64 in JSON. Validate content type, max file size, and enforce file-type checks. Consider per-route limits rather than global 15mb if only some endpoints need larger bodies.
  4. Rate limiting/throttling: Add request rate limiting (NestJS Throttler, express-rate-limit, or upstream reverse-proxy / WAF limits) to protect against brute-force and DoS. Apply stricter limits on authentication and file-upload endpoints.
  5. OpenAPI output: Avoid writing full OpenAPI to a repository or public path in development CI/agents. If you must export docs, ensure the target is a secure artifact store, the file is not committed to source control, and sensitive schemas/fields are redacted. Also ensure NODE_ENV is reliably set to 'production' in production to avoid accidental disclosure.

🔴 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/actions/generate-suggestions.ts (HIGH Risk)

# Issue Risk Level
1 No authorization check before DB queries by organizationId HIGH
2 Missing validation for organizationId and taskDescription used directly HIGH

Recommendations:

  1. Enforce authorization: do not trust a caller-supplied organizationId. Resolve organizationId from the authenticated session/token and verify the caller is a member of that organization before any DB queries.
  2. Validate and sanitize inputs: validate organizationId shape (e.g., UUID) and enforce length/character limits. Use a schema (zod) for the function input and reject or normalize unexpected values.
  3. Limit data exposure in DB queries: only select fields necessary for the operation, and avoid returning any sensitive fields to the LLM or client. Consider further filtering rows by both organizationId and an explicit membership/permission check.
  4. Protect LLM prompts: apply length limits and sanitize taskDescription before embedding in prompts. Redact or remove secrets/PII from context/vendor text before sending to the LLM to reduce data leak risk and prompt-injection surface.
  5. Use server-side authoritative org resolution: prefer fetching organizationId from server session/auth token rather than accepting it as a parameter to avoid horizontal privilege escalation.
  6. Add logging, rate limiting and anomaly detection around DB and LLM calls to detect and mitigate abuse or excessive data access.
  7. Add unit/integration tests and periodic audit to verify authorization enforcement on endpoints that accept organizationId.

🟡 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/chat/EmptyState.tsx (MEDIUM Risk)

# Issue Risk Level
1 Hardcoded API token in image URLs (pk_AZatYxV5QDSfWpRDaBxzRQ) MEDIUM
2 Unvalidated vendorWebsite/vendorName used to build img URLs MEDIUM

Recommendations:

  1. Remove the hardcoded token from front-end source. Treat the token as a secret: move it to a backend service or at minimum to a build-time environment variable that is not the secret/master token. If the token must be public (e.g., a public publishable key), clearly document it and rotate it if leaked.
  2. Proxy logo requests through your backend (e.g., /api/logo?domain=...) so the client never contains the token. The server can fetch from img.logo.dev using the secret token and return the image (or a cached copy) to the client.
  3. Whitelist/validate vendor domains or canonicalize them strictly before embedding into any outgoing URL path. Limit accepted characters to a safe domain regex (letters, digits, hyphen, dot) and explicitly reject anything that looks like a scheme, path traversal, or contains control characters.
  4. Enforce a content/security policy: add an appropriate CSP and a Referrer-Policy (for example 'no-referrer' or 'strict-origin') so tokens in querystrings are not leaked in Referer headers to third parties.
  5. Ensure any external/static example URLs (AUTOMATION_EXAMPLES) are vetted and cannot be overridden by untrusted inputs. If you accept suggestions from external sources, validate those sources and sanitize values at ingestion time.

🟡 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/chat/message-part/prompt-secret.tsx (MEDIUM Risk)

# Issue Risk Level
1 Client trusts caller-supplied orgId in payload MEDIUM
2 Unvalidated AI-provided input via input:any (description, category) MEDIUM
3 No anti-CSRF token or auth assertion on POST /api/secrets MEDIUM
4 Console.error may log sensitive data or backend details MEDIUM
5 Raw server error messages shown to users via toast.error MEDIUM

Recommendations:

  1. Enforce server-side authorization: ignore client-supplied organizationId and derive organization from the authenticated user/session token on the server. Validate that the authenticated principal is allowed to create secrets for the requested organization.
  2. Validate and sanitize all fields server-side (name, value, description, category). Do not rely on client-side sanitization or UI restrictions. Enforce secret-name format and length on the backend.
  3. Protect the /api/secrets endpoint from CSRF: require an anti-CSRF token or use authorization headers (e.g., Bearer token) and SameSite=strict cookies for session cookies. Confirm server checks authentication on every request.
  4. Avoid logging secret values or sensitive request/response payloads to the console. Redact or omit sensitive fields before logging. Log only non-sensitive metadata necessary for debugging.
  5. Return and display generic error messages to users. Do not surface raw server error objects or stack traces in client-facing toasts. Log detailed errors server-side (redacted) and return a generic message like 'Failed to create secret'.
  6. Implement server-side rate-limiting and input size limits for secret creation to mitigate abuse.
  7. Ensure the POST handler for /api/secrets uses strong server-side validation and stores the secret using proven encryption practices (e.g., KMS, envelope encryption).

🟡 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/evaluation/EvaluationCriteriaCard.tsx (MEDIUM Risk)

# Issue Risk Level
1 Unsanitized user input sent to updateEvaluationCriteria MEDIUM
2 No client-side input length or format validation MEDIUM
3 Potential stored XSS if server stores criteria and renders unsafely MEDIUM
4 No visible CSRF protection on state-changing request MEDIUM
5 Client can attempt updating arbitrary automationId without server auth check MEDIUM

Recommendations:

  1. Server-side: Always validate and sanitize the criteria payload in the updateEvaluationCriteria handler before persisting. Enforce length limits, allowed character sets, and reject/normalize unexpected input.
  2. Client-side: Add lightweight validation (max length, required patterns, and helpful error messages) to prevent accidental oversized or malformed submissions and improve UX.
  3. Output encoding: When rendering stored criteria anywhere, ensure the renderer escapes content (React does by default for text nodes). Avoid dangerouslySetInnerHTML; if HTML rendering is required, sanitize on the server or client with a vetted HTML sanitizer (e.g., DOMPurify) before inserting into the DOM.
  4. CSRF: Protect the update endpoint with CSRF mitigations (same-site cookies, anti-forgery tokens, or use of authorization headers with tokens). Ensure the client includes required tokens/headers when calling updateEvaluationCriteria.
  5. Authorization: Enforce server-side authorization checks that verify the authenticated user has permission to update the specific automationId. Do not rely on client-side checks.
  6. Audit logging: Log updates to evaluation criteria (who, when, what) and rate-limit update endpoints to detect and mitigate abuse.

🔴 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/page.tsx (HIGH Risk)

# Issue Risk Level
1 Route params used directly in DB query without validation HIGH
2 DB query uses unvalidated params (possible injection if raw queries used) HIGH
3 No authorization check before returning task (IDOR risk) HIGH
4 automationId passed to loadChatHistory without validation HIGH
5 task.title/description forwarded to client without sanitization (XSS risk) HIGH

Recommendations:

  1. Validate and type-check route params server-side as soon as they are read (e.g., ensure taskId/orgId/automationId are valid UUIDs or match expected patterns). Use a schema validator (Zod/Joi) or explicit checks before using in DB calls.
  2. Enforce authentication and explicit authorization: verify the current user/session is allowed to access the org and task (ownership or membership) before performing the DB lookup or returning any task data. Centralize this in middleware or server actions so every route is covered.
  3. Use ORM parameterized methods (as here) and avoid constructing raw SQL with user input. If any helper functions use raw queries, convert them to parameterized queries or validate/escape inputs tightly.
  4. Inspect loadChatHistory implementation and ensure automationId is validated and not directly used in raw queries, command execution, or eval. Apply input validation, limit returned history size, and add rate limiting/authorization on history fetches.
  5. Treat task.title and task.description as untrusted: either sanitize/encode them before sending to the client or ensure the client never renders them with dangerouslySetInnerHTML or other unsafe DOM APIs. Prefer rendering as plain text so React automatically escapes content; if HTML is needed, sanitize server-side with a vetted sanitizer (DOMPurify-like) and enforce a whitelist.
  6. Add logging and monitoring for unexpected param shapes and failed authorization attempts; add tests that exercise IDOR and parameter validation to prevent regressions.

🟡 apps/app/src/app/(app)/[orgId]/tasks/[taskId]/hooks/use-task.ts (MEDIUM Risk)

# Issue Risk Level
1 Unsanitized URL params passed to API (/v1/tasks/${taskId}) MEDIUM
2 Possible server-side injection via taskId/orgId from useParams MEDIUM
3 API error content thrown directly may leak sensitive info to UI MEDIUM
4 No client-side validation of orgId/taskId format/type before requests MEDIUM
5 SWR key includes raw taskId, may enable cache poisoning MEDIUM

Recommendations:

  1. Validate and canonicalize orgId and taskId on the client before use: enforce type, length and a strict whitelist/regex (e.g., UUID or alphanumeric with limited length). Reject or normalize unexpected values.
  2. Escape/encode path segments when building API URLs: use encodeURIComponent(taskId) (and orgId where used) when interpolating into /v1/tasks/${taskId} to avoid path injection/malformed URLs.
  3. Do not propagate raw backend error strings to thrown Errors shown to the UI. Map backend errors to safe, user-friendly messages and log full details server-side. Example: throw new Error('Failed to load task'); and preserve detailed error to telemetry only.
  4. Harden the server side to assume inputs are untrusted: use parameterized queries/ORM APIs, validate parameters server-side, and sanitize before using in any SQL/command/external call. Treat client validation as UX only.
  5. Normalize SWR keys to reduce risk of cache poisoning: derive keys from a canonical, validated id (or hash the id) instead of interpolating raw user input. Example key: ['task', hash(taskId), orgId] or use a prefixed, validated id string.
  6. Add client-side defensiveness: early-return or show error for missing/invalid orgId/taskId instead of attempting the request (currently there is a guard but also throw inside the fetch — ensure consistent handling).
  7. Add logging/monitoring for unexpected ID formats or frequent fetch errors to detect attempted abuse.

🟡 apps/app/src/hooks/use-organization-members.ts (MEDIUM Risk)

# Issue Risk Level
1 Unvalidated orgId passed to api.get and cache key MEDIUM
2 Console logs backend error messages (possible sensitive leak) MEDIUM
3 Response shape not validated before use MEDIUM

Recommendations:

  1. Validate and sanitize orgId (allowlist or UUID check)
  2. URL-encode orgId or send it in request body to avoid injection
  3. Avoid logging raw backend error strings in the browser
  4. Validate API response schema (e.g., zod/io-ts) before using data
  5. Return user-friendly errors, don't expose server messages to clients

🔴 apps/app/src/lib/api-client.ts (HIGH Risk)

# Issue Risk Level
1 Trusts client-sent X-Organization-Id header for org context HIGH
2 Sends credentials: 'include' which can enable CSRF across origins HIGH
3 No validation of organizationId before use HIGH
4 No endpoint path validation — callers can request arbitrary URLs HIGH
5 Returns raw server messages, risk of info disclosure HIGH
6 Console error logs may expose sensitive auth details HIGH
7 Authorization only attached in browser (typeof window) — server calls unauthenticated HIGH

Recommendations:

  1. Do not rely on client-provided X-Organization-Id for authorization decisions. Enforce organization membership and authorization server-side (derive org from the validated JWT or server session). Treat client-sent org headers as advisory only or drop them entirely.
  2. Avoid credentials: 'include' for cross-origin requests unless necessary. Prefer SameSite=strict/lax cookies, or use a CSRF token pattern (double-submit cookie or server-generated token) and ensure Access-Control-Allow-Credentials and CORS policy are correctly scoped if credentials are required.
  3. Validate and canonicalize organizationId before using it in headers or requests (e.g., ensure it matches expected format and that the current user is allowed to act on that org). Prefer using org id from the server-validated JWT claims.
  4. Whitelist allowed endpoint paths (or use explicit API wrapper methods) instead of concatenating arbitrary endpoint strings. Normalize/validate endpoint input and disallow full absolute URLs or path traversal patterns.
  5. Sanitize/truncate server error messages returned to clients. Do not return raw internal error strings or stack traces. Map internal errors to user-friendly messages and log the detailed messages server-side only.
  6. Remove or restrict console.error/console.log calls that may leak tokens or internal error details. Use structured server-side logging with appropriate redaction and severity levels instead of client-side console output for sensitive issues.
  7. If the client library will be used in server-side contexts, ensure token acquisition also works on the server (or explicitly document that this client is client-only). For server-side calls, attach Authorization using secure server-side credentials and never depend on typeof window checks for security.

🔴 apps/app/src/utils/jwt-manager.ts (HIGH Risk)

# Issue Risk Level
1 JWT stored in localStorage (accessible via XSS) HIGH
2 Token refresh uses credentials:'include' — may allow CSRF if endpoint lacks protection HIGH
3 Expiry timestamp stored client-side can be tampered HIGH
4 decodeJWTPayload uses atob without base64url handling HIGH
5 No JWT signature verification client-side (trusting tokens from client sources) HIGH

Recommendations:

  1. Move authentication tokens out of window-accessible storage. Prefer HttpOnly, Secure cookies (with SameSite=strict/lax as appropriate) for refresh/session cookies so JS cannot read them. If you must store short-lived tokens client-side, minimize lifetime and harden against XSS.
  2. Ensure /api/auth/token and any session endpoints enforce CSRF protections (CSRF tokens or SameSite cookie policy) and authenticate requests server-side. Do not rely on credentials:'include' alone as a CSRF defense.
  3. Do not trust client-side expiry as authoritative. Treat the expiry stored in localStorage as advisory only; always handle token expiry and invalid tokens server-side. Consider deriving expiry from the token payload on-the-fly rather than storing a separate timestamp, or store expiry in an integrity-protected place (server-controlled).
  4. Fix JWT payload decoding to handle base64url encoding safely: replace '-' with '+', '_' with '/', add proper padding before calling atob (or use a robust base64url decode library). Add defensive checks for token format and handle decode failures gracefully.
  5. Avoid relying on client-side signature verification for security decisions. The server must always validate JWT signatures and claims. On the client, treat tokens as opaque and implement robust error handling for rejected/expired tokens (e.g., force re-authentication).
  6. Reduce logging of sensitive authentication-related operations and never log full tokens. Remove or redact token contents from logs.
  7. Consider reducing attack surface: minimize token lifetime, rotate tokens frequently, implement refresh throttling carefully, and validate refresh concurrency and error paths to avoid leaking state.
  8. If keeping tokens client-side, harden against XSS: use CSP, sanitize/escape any dynamic HTML, and perform regular XSS testing.

💡 Recommendations

View 3 recommendation(s)
  1. Upgrade the vulnerable dependency: bump package.json to ai@>=5.0.52 (per GHSA-rwvc-j5jr-mgvh) and update the lockfile/build to ensure the fixed version is installed.
  2. Remove the hardcoded token (pk_AZatYxV5QDSfWpRDaBxzRQ) in apps/app/src/app/(app)/[orgId]/tasks/.../components/EmptyState.tsx. Do not embed credentials in client code — proxy image requests through a server endpoint that injects the token server-side or serve images without exposing the token.
  3. Validate and canonicalize route params and organization IDs before use in DB/API calls (e.g., apps/app/.../generate-suggestions.ts, page.tsx, use-task.ts): enforce UUID/regex checks, use encodeURIComponent for URL segments, and resolve organizationId from server-validated auth context rather than trusting client-supplied values.

Powered by Comp AI - AI that handles compliance for you. Reviewed Nov 12, 2025

- add flushSync for immediate UI updates after suggestions load
- change placeholder to generic text
- add vendor diversity requirement to AI prompts to avoid duplicate vendors
@Marfuen Marfuen merged commit ee8de8f into main Nov 12, 2025
8 of 9 checks passed
@Marfuen Marfuen deleted the mariano/smart-suggestions branch November 12, 2025 23:25
@claudfuen
Copy link
Contributor

🎉 This PR is included in version 1.57.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants