-
Notifications
You must be signed in to change notification settings - Fork 0
feat: continue improving pulse ux #55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
⏳ I'm reviewing this pull request for security vulnerabilities and code quality issues. I'll provide an update when I'm done |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Reviewer's GuideThis pull request enhances the user experience of the weekly pulse feature. Implementation involved integrating File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Caution Review failedThe pull request is closed. """ WalkthroughA new asynchronous function for fetching the previous week's manager was added. The Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ManagerScreen
participant Actions as actions.ts (getPreviousWeekManager)
participant Supabase
User->>ManagerScreen: Mounts or changes user/week/year
ManagerScreen->>Actions: getPreviousWeekManager(userId, week, year)
Actions->>Supabase: Query submissions for previous week/year
Supabase-->>Actions: Return manager field
Actions-->>ManagerScreen: Return previous manager email or null
ManagerScreen->>ManagerScreen: Update state, suggest manager
User->>ManagerScreen: Inputs manager email or presses Shift+Enter
ManagerScreen->>ManagerScreen: Validate and trigger onNext if valid
Possibly related PRs
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
src/components/screens/ProjectSelectionScreen.tsxOops! Something went wrong! :( ESLint: 9.25.1 ESLint couldn't find the plugin "@next/eslint-plugin-next". (The package "@next/eslint-plugin-next" was not found when loaded as a Node module from the directory "".) It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:
The plugin "@next/eslint-plugin-next" was referenced from the config file in " » eslint-config-next/core-web-vitals » /node_modules/.pnpm/eslint-config-next@15.3.1_eslint@9.25.1_jiti@2.4.2__typescript@5.8.3/node_modules/eslint-config-next/index.js". If you still can't figure out the problem, please see https://eslint.org/docs/latest/use/troubleshooting. Tip ⚡️ Faster reviews with caching
Enjoy the performance boost—your workflow just got faster. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
✅ I finished the code review, and left comments with the issues I found. I will now generate code fix suggestions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @harley - I've reviewed your changes - here's some feedback:
- The
Shift + Enter
keyboard navigation logic is repeated in multiple screen components; consider creating a custom hook for this functionality. - The bottom navigation bar is implemented differently across screens (fixed positioning in
AdditionalProjectsScreen
vs. flexboxmt-auto
in others); consider standardizing this approach for consistency.
Here's what I looked at during the review
- 🟢 General issues: all looks good
- 🟢 Security: all looks good
- 🟢 Testing: all looks good
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this 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
🔭 Outside diff range comments (1)
src/components/screens/AdditionalProjectsScreen.tsx (1)
44-48
:⚠️ Potential issueValidate hours > 0 before adding “other” projects
handleOtherProjectSubmit
only checks thathoursInput
is truthy. A user could enter0
, negative numbers (via copy-paste) or non-numeric text and still bypass UI validation by calling the function programmatically.- if (otherProject.trim() && hoursInput) { - addAdditionalProject(otherProject.trim(), parseInt(hoursInput, 10)); - } +const hours = parseInt(hoursInput, 10); +if (otherProject.trim() && Number.isFinite(hours) && hours > 0) { + addAdditionalProject(otherProject.trim(), hours); +}
🧹 Nitpick comments (9)
src/app/actions.ts (1)
61-101
: Consider deduplicating “previous-week” logic and tighten parameter checks
getPreviousWeekManager
is almost a copy-paste ofgetPreviousWeekPrimaryProject
, differing only in the selected column. Two quick wins:
Extract the week/year rollover calculation and the Supabase fetch into a small helper that receives the column name to select; this keeps
actions.ts
maintainable and eliminates the risk that one function gets patched while the twin is forgotten.The guard
if (!userId || !currentWeekNumber || !currentYear)
treats0
as “missing”. It would be clearer (and safer for possible future callers) to test forundefined
/null
explicitly:- if (!userId || !currentWeekNumber || !currentYear) { + if (!userId || currentWeekNumber === undefined || currentYear === undefined) {Sample refactor skeleton (truncated for brevity):
async function getPreviousWeekValue( userId: string, week: number, year: number, field: 'primary_project_name' | 'manager' ): Promise<string | null> { /* shared logic … */ } export const getPreviousWeekManager = ( id: string, w: number, y: number ) => getPreviousWeekValue(id, w, y, 'manager');This keeps one source of truth for week arithmetic and error handling.
src/components/screens/HoursWorkedScreen.tsx (2)
19-33
: Avoid re-registering the global key listener on every slider tickBecause
formData.primaryProject.hours
is a dependency, moving the slider from 0 → 80 re-creates thekeydown
handler up to 80 times. The removal inreturn
avoids leaks, but the churn is unnecessary and may hurt performance on low-powered devices.A common pattern is to register once on mount and consult a
ref
to get the latest value:+import { useEffect, useRef } from 'react'; const hoursRef = useRef(formData.primaryProject.hours); useEffect(() => { hoursRef.current = formData.primaryProject.hours }, [formData.primaryProject.hours]); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { - if (e.shiftKey && e.key === 'Enter' && hoursRef.current) { + if (e.shiftKey && e.key === 'Enter' && hoursRef.current) { e.preventDefault(); onNext(); } }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); -}, [onNext, formData.primaryProject.hours]); +}, [onNext]);This keeps the listener stable while still reacting to updated hours.
130-137
: Minor a11y nit – “Shift + Enter” hint is invisible to screen readersVisually the shortcut hint is great, but assistive tech won’t pick it up.
Consider addingaria-describedby
linking to a visually-hidden element, or include the shortcut in the button’saria-label
itself, e.g.:-aria-label="Next step, or press Shift + Enter" +aria-label="Next step (Shortcut: Shift + Enter)"src/components/screens/ManagerScreen.tsx (3)
7-7
: Redundant prop intersection –ScreenProps
already contains these fields
ScreenProps
(seetypes/weekly-pulse.ts
) declaresuserId
,currentWeekNumber
, andcurrentYear
as optional. The extra& { … }
intersection duplicates them:-export default function ManagerScreen({ … }: ScreenProps & { userId?: string; currentWeekNumber?: number; currentYear?: number }) { +export default function ManagerScreen({ … }: ScreenProps) {This keeps the signature concise and avoids drift if the base type changes.
32-40
: Trim effect dependencies to avoid unnecessary re-runsIncluding the whole
formData
object causes this effect to fire on unrelated form changes, producing needless renders. Depend only on what you read:-}, [isLoadingPreviousManager, fetchedPreviousManager, formData.manager, setFormData, formData]); +}, [isLoadingPreviousManager, fetchedPreviousManager, formData.manager, setFormData]);
96-111
: Case-insensitive comparison will make badges more reliableEmails are not case-sensitive, yet the equality checks use
===
, soAlice@corp.com
versusalice@corp.com
will incorrectly show “Overridden suggestion”. Normalise both sides:- formData.manager === fetchedPreviousManager + formData.manager?.toLowerCase() === fetchedPreviousManager?.toLowerCase()Do the same for the “overridden” case.
src/components/screens/AdditionalProjectsScreen.tsx (3)
194-202
: Always provide a radix toparseInt
& avoid implicit NaN handling in the disabled check
parseInt(projectHours)
is invoked without a radix, which causes implementation-defined behaviour in non-decimal strings and throws an eslint warning (radix = 10
rule).In addition, the disabled check
parseInt(projectHours) <= 0
silently treatsNaN
asfalse
, so the “Add” button may become enabled for invalid input like"abc"
.- disabled={!projectHours || parseInt(projectHours) <=0} + disabled={ + !projectHours || + Number.isNaN(Number(projectHours)) || + parseInt(projectHours, 10) <= 0 + }Apply the same fix to the
hoursInput
check a few lines below (≈257–258).
91-96
: Addtype="button"
to actionable buttonsBy default, a
<button>
inside a form (or nested future form) submits the form when pressed. Although the current layout doesn’t use a<form>
element, addingtype="button"
is a low-cost safeguard that prevents accidental submissions if the markup changes later, and helps accessibility tools infer intent.- <button onClick={onNext} …> + <button type="button" onClick={onNext} …>Please update all interactive buttons in this component (Skip, grid items, Add, Other, Back, Next).
Also applies to: 164-176, 195-202, 208-220, 256-261, 276-288
185-194
: Set an explicitstep
attribute on numeric inputs for better UXThe hours inputs currently use
type="number"
but nostep
. Addingstep="0.5"
(or1
) communicates the expected granularity to native pickers and assistive technologies.- <Input type="number" … min="1" max="80" … /> + <Input type="number" step="0.5" min="0.5" max="80" … />Align the same step on both “select from existing” and “other project” paths.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/app/actions.ts
(1 hunks)src/components/screens/AdditionalProjectsScreen.tsx
(2 hunks)src/components/screens/HoursWorkedScreen.tsx
(3 hunks)src/components/screens/ManagerScreen.tsx
(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/components/screens/AdditionalProjectsScreen.tsx (2)
src/components/ui/card.tsx (1)
Card
(85-85)src/components/ui/input.tsx (1)
Input
(21-21)
src/components/screens/ManagerScreen.tsx (2)
src/types/weekly-pulse.ts (1)
ScreenProps
(49-59)src/app/actions.ts (1)
getPreviousWeekManager
(61-101)
useEffect(() => { | ||
if (shouldNavigate) { | ||
onNext(); | ||
setShouldNavigate(false); | ||
if (userId && currentWeekNumber && currentYear) { | ||
setIsLoadingPreviousManager(true); | ||
getPreviousWeekManager(userId, currentWeekNumber, currentYear) | ||
.then(manager => { | ||
setFetchedPreviousManager(manager); | ||
}) | ||
.catch(error => { | ||
console.error("Failed to fetch previous week's manager:", error); | ||
setFetchedPreviousManager(null); | ||
}) | ||
.finally(() => { | ||
setIsLoadingPreviousManager(false); | ||
}); | ||
} else { | ||
setIsLoadingPreviousManager(false); | ||
} | ||
}, [shouldNavigate, onNext]); | ||
}, [userId, currentWeekNumber, currentYear]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prevent state updates after unmount / race conditions when fetching
If the component unmounts (or props change) before the Supabase promise resolves, calling setFetchedPreviousManager
or setIsLoadingPreviousManager
will warn in React 18. Guard with an “isMounted” flag or abort controller:
useEffect(() => {
- if (userId && currentWeekNumber && currentYear) {
+ let cancelled = false;
+ if (userId && currentWeekNumber && currentYear) {
setIsLoadingPreviousManager(true);
getPreviousWeekManager(userId, currentWeekNumber, currentYear)
.then(manager => {
- setFetchedPreviousManager(manager);
+ if (!cancelled) setFetchedPreviousManager(manager);
})
.catch(err => {
- console.error(…);
- setFetchedPreviousManager(null);
+ if (!cancelled) {
+ console.error(…);
+ setFetchedPreviousManager(null);
+ }
})
.finally(() => {
- setIsLoadingPreviousManager(false);
+ if (!cancelled) setIsLoadingPreviousManager(false);
});
} else {
setIsLoadingPreviousManager(false);
}
-}, [userId, currentWeekNumber, currentYear]);
+ return () => { cancelled = true; };
+}, [userId, currentWeekNumber, currentYear]);
📝 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.
useEffect(() => { | |
if (shouldNavigate) { | |
onNext(); | |
setShouldNavigate(false); | |
if (userId && currentWeekNumber && currentYear) { | |
setIsLoadingPreviousManager(true); | |
getPreviousWeekManager(userId, currentWeekNumber, currentYear) | |
.then(manager => { | |
setFetchedPreviousManager(manager); | |
}) | |
.catch(error => { | |
console.error("Failed to fetch previous week's manager:", error); | |
setFetchedPreviousManager(null); | |
}) | |
.finally(() => { | |
setIsLoadingPreviousManager(false); | |
}); | |
} else { | |
setIsLoadingPreviousManager(false); | |
} | |
}, [shouldNavigate, onNext]); | |
}, [userId, currentWeekNumber, currentYear]); | |
useEffect(() => { | |
let cancelled = false; | |
if (userId && currentWeekNumber && currentYear) { | |
setIsLoadingPreviousManager(true); | |
getPreviousWeekManager(userId, currentWeekNumber, currentYear) | |
.then(manager => { | |
if (!cancelled) { | |
setFetchedPreviousManager(manager); | |
} | |
}) | |
.catch(error => { | |
if (!cancelled) { | |
console.error("Failed to fetch previous week's manager:", error); | |
setFetchedPreviousManager(null); | |
} | |
}) | |
.finally(() => { | |
if (!cancelled) { | |
setIsLoadingPreviousManager(false); | |
} | |
}); | |
} else { | |
setIsLoadingPreviousManager(false); | |
} | |
return () => { cancelled = true; }; | |
}, [userId, currentWeekNumber, currentYear]); |
⏳ I'm reviewing this pull request for security vulnerabilities and code quality issues. I'll provide an update when I'm done |
✅ I finished the code review, and left comments with the issues I found. I will now generate code fix suggestions. |
⏳ I'm reviewing this pull request for security vulnerabilities and code quality issues. I'll provide an update when I'm done |
.maybeSingle(); | ||
|
||
if (error) { | ||
console.error('Error fetching previous week manager:', error.message); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warning
Description: Log Injection occurs when untrusted user input is directly written to log files without proper sanitization. This can allow attackers to manipulate log entries, potentially leading to security issues like log forging or cross-site scripting. To prevent this, always sanitize user input before logging by removing or encoding newline characters, using string encoding functions, and leveraging built-in sanitization features of logging libraries when available. Learn more - https://cwe.mitre.org/data/definitions/117.html
Severity: High
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vulnerability in the original code is Log Injection, which occurs when untrusted user input is directly written to log files without proper sanitization. This can allow attackers to manipulate log entries, potentially leading to security issues like log forging or cross-site scripting.
To address this vulnerability, the following changes were made:
-
For the error logging from the Supabase query:
- We assume the existence of a
sanitizeLogMessage
utility function that sanitizes log messages. - The error message is passed through this sanitization function before being logged.
- We assume the existence of a
-
For the catch block:
- Instead of directly logging the error object, we check if it's an instance of Error and log the message property if so.
- If it's not an Error instance, we convert it to a string before logging.
These changes help prevent log injection by ensuring that potentially malicious input is sanitized before being written to the logs. The sanitizeLogMessage
function (which would need to be implemented separately) should remove or encode newline characters and other potentially dangerous characters.
It's important to note that the actual implementation of sanitizeLogMessage
would depend on the specific requirements and the logging system being used. A typical implementation might include:
- Removing or encoding newline characters
- Escaping special characters
- Truncating overly long messages
- Using string encoding functions
References:
- CWE-117: Improper Output Neutralization for Logs
https://cwe.mitre.org/data/definitions/117.html - OWASP: Logging Cheat Sheet
https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html
Other examples of log sanitization:
function sanitizeLogMessage(message: string): string {
return message.replace(/[\r\n]+/g, ' ').slice(0, 1000);
}
// Or using a library like validator.js
import validator from 'validator';
function sanitizeLogMessage(message: string): string {
return validator.escape(message).slice(0, 1000);
}
console.error('Error fetching previous week manager:', error.message); | |
.maybeSingle(); | |
if (error) { | |
// import { sanitizeLogMessage } from './logUtils'; // Utility function to sanitize log messages | |
console.error('Error fetching previous week manager:', sanitizeLogMessage(error.message)); | |
return null; | |
} | |
return data ? data.manager : null; | |
} catch (err) { | |
console.error('Unexpected error in getPreviousWeekManager:', err instanceof Error ? err.message : String(err)); | |
return null; | |
} |
✅ I finished the code review, and left comments with the issues I found. I will now generate code fix suggestions. |
setFetchedPreviousManager(manager); | ||
}) | ||
.catch(error => { | ||
console.error("Failed to fetch previous week's manager:", error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warning
Description: Log Injection occurs when untrusted user input is directly written to log files without proper sanitization. This can allow attackers to manipulate log entries, potentially leading to security issues like log forging or cross-site scripting. To prevent this, always sanitize user input before logging by removing or encoding newline characters, using string encoding functions, and leveraging built-in sanitization features of logging libraries when available. Learn more - https://cwe.mitre.org/data/definitions/117.html
Severity: High
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vulnerability in the original code is Log Injection, which occurs when untrusted user input is directly written to log files without proper sanitization. This can allow attackers to manipulate log entries, potentially leading to security issues like log forging or cross-site scripting.
To address this vulnerability, the fix involves sanitizing the error message before logging it. The remediation is made by introducing a utility function sanitizeLogMessage
that sanitizes the log message before it's passed to console.error
.
The fix is implemented as follows:
- We assume the existence of a utility function
sanitizeLogMessage
in the@/utils/logSanitizer
module. This function would be responsible for sanitizing the log message. - The error object is converted to a string using
error.toString()
to ensure we're working with a string value. - The resulting string is then passed through the
sanitizeLogMessage
function before being logged.
This approach ensures that any potentially malicious content in the error message is sanitized before being written to the log, preventing log injection attacks. The sanitization function would typically remove or encode special characters, newlines, and other potentially harmful elements from the log message.
It's important to note that the actual implementation of sanitizeLogMessage
would depend on the specific requirements and potential threats in your application. Common sanitization techniques include:
- Removing newline characters
- Encoding special characters
- Truncating overly long messages
- Using built-in sanitization features of logging libraries
References:
- OWASP Log Injection: https://owasp.org/www-community/attacks/Log_Injection
- CWE-117: Improper Output Neutralization for Logs: https://cwe.mitre.org/data/definitions/117.html
- NIST: Security and Privacy Controls for Information Systems and Organizations: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf
Other examples of log sanitization:
// Using a regular expression to remove newlines and limit length
function sanitizeLog(message) {
return message.replace(/[\r\n]+/g, ' ').substring(0, 1000);
}
// Using a library like DOMPurify for more comprehensive sanitization
import DOMPurify from 'dompurify';
function sanitizeLog(message) {
return DOMPurify.sanitize(message, { ALLOWED_TAGS: [] });
}
console.error("Failed to fetch previous week's manager:", error); | |
setFetchedPreviousManager(manager); | |
}) | |
.catch(error => { | |
// import { sanitizeLogMessage } from '@/utils/logSanitizer'; // Utility function to sanitize log messages | |
console.error("Failed to fetch previous week's manager:", sanitizeLogMessage(error.toString())); | |
}) | |
.finally(() => { | |
setIsLoadingPreviousManager(false); |
⏳ I'm reviewing this pull request for security vulnerabilities and code quality issues. I'll provide an update when I'm done |
setFetchedPreviousManager(manager); | ||
}) | ||
.catch(error => { | ||
console.error("Failed to fetch previous week's manager:", error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warning
Description: Log Injection occurs when untrusted user input is directly written to log files without proper sanitization. This can allow attackers to manipulate log entries, potentially leading to security issues like log forging or cross-site scripting. To prevent this, always sanitize user input before logging by removing or encoding newline characters, using string encoding functions, and leveraging built-in sanitization features of logging libraries when available. Learn more - https://cwe.mitre.org/data/definitions/117.html
Severity: High
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vulnerability in the original code is Log Injection, which occurs when untrusted user input is directly written to log files without proper sanitization. In this case, the error object is being logged directly, which could potentially contain malicious content if manipulated by an attacker.
To fix this vulnerability, we've introduced a sanitization step before logging the error message. The fix involves using a hypothetical utility function called sanitizeLogMessage
to clean the error message before it's logged. This function would typically:
- Convert the error object to a string
- Remove or encode any potentially harmful characters (e.g., newlines, control characters)
- Limit the length of the message to prevent log flooding
The remediation is made by replacing:
console.error("Failed to fetch previous week's manager:", error);
with:
console.error("Failed to fetch previous week's manager:", sanitizeLogMessage(error.toString()));
This approach ensures that even if an attacker manages to inject malicious content into the error object, it will be sanitized before being logged, preventing log injection attacks.
It's important to note that the actual implementation of sanitizeLogMessage
would depend on the specific requirements and potential threats in your application. In a real-world scenario, you might use a well-tested library for log sanitization or implement a custom function that adheres to your organization's security policies.
References:
- OWASP Log Injection: https://owasp.org/www-community/attacks/Log_Injection
- CWE-117: Improper Output Neutralization for Logs: https://cwe.mitre.org/data/definitions/117.html
Other examples of log sanitization:
- Using a regular expression to remove newlines:
const sanitizeLog = (message) => message.replace(/[\r\n]+/g, ' ');
- Using a library like DOMPurify to sanitize HTML content in logs:
import DOMPurify from 'dompurify'; const sanitizeLog = (message) => DOMPurify.sanitize(message);
console.error("Failed to fetch previous week's manager:", error); | |
setFetchedPreviousManager(manager); | |
}) | |
.catch(error => { | |
// import { sanitizeLogMessage } from '@/utils/logSanitizer'; // Utility function to sanitize log messages | |
console.error("Failed to fetch previous week's manager:", sanitizeLogMessage(error.toString())); | |
}) | |
.finally(() => { | |
setIsLoadingPreviousManager(false); |
.maybeSingle(); | ||
|
||
if (error) { | ||
console.error('Error fetching previous week manager:', error.message); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warning
Description: Log Injection occurs when untrusted user input is directly written to log files without proper sanitization. This can allow attackers to manipulate log entries, potentially leading to security issues like log forging or cross-site scripting. To prevent this, always sanitize user input before logging by removing or encoding newline characters, using string encoding functions, and leveraging built-in sanitization features of logging libraries when available. Learn more - https://cwe.mitre.org/data/definitions/117.html
Severity: High
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vulnerability in the original code is Log Injection, which occurs when untrusted user input is directly written to log files without proper sanitization. This can allow attackers to manipulate log entries, potentially leading to security issues like log forging or cross-site scripting.
To address this vulnerability, the following changes were made:
-
For the error logging from the Supabase query:
- A sanitization function
sanitizeLogMessage
is used to clean the error message before logging. - This function should be implemented to remove or encode any potentially harmful characters or sequences.
- A sanitization function
-
For the catch block:
- Instead of directly logging the error object, we check if it's an instance of Error and log only the message.
- If it's not an Error instance, we convert it to a string before logging.
These changes help prevent log injection by ensuring that the logged content is properly sanitized and doesn't contain any malicious data that could be interpreted as log commands or script content.
The sanitizeLogMessage
function (which should be implemented separately) could use techniques such as:
- Removing or encoding newline characters
- Escaping special characters
- Truncating overly long messages
- Using string encoding functions
It's important to note that the specific implementation of sanitizeLogMessage
would depend on the logging system being used and the potential attack vectors relevant to your application.
References:
- CWE-117: Improper Output Neutralization for Logs
https://cwe.mitre.org/data/definitions/117.html - OWASP: Logging Cheat Sheet
https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html
Other examples of log sanitization:
// Using a regular expression to remove newlines and limit length
function sanitizeLog(message: string): string {
return message.replace(/[\r\n]+/g, ' ').substring(0, 1000);
}
// Using a library like validator.js
import validator from 'validator';
function sanitizeLog(message: string): string {
return validator.escape(message).substring(0, 1000);
}
Always ensure that your logging practices are secure and that you're not inadvertently exposing sensitive information through your logs.
console.error('Error fetching previous week manager:', error.message); | |
.maybeSingle(); | |
if (error) { | |
// import { sanitizeLogMessage } from './logUtils'; // Utility function to sanitize log messages | |
console.error('Error fetching previous week manager:', sanitizeLogMessage(error.message)); | |
return null; | |
} | |
return data ? data.manager : null; | |
} catch (err) { | |
console.error('Unexpected error in getPreviousWeekManager:', err instanceof Error ? err.message : String(err)); | |
return null; | |
} |
✅ I finished the code review, and left comments with the issues I found. I will now generate code fix suggestions. |
Summary by Sourcery
Improve the user experience of the Pulse application by enhancing the UI/UX of multiple screens with more interactive and responsive design elements
New Features:
Enhancements:
Chores:
Summary by CodeRabbit
New Features
Bug Fixes
Style