Skip to content

Fix: prevent crash when parsing invalid JSON in analytics handler#5906

Open
TeamInfinixdevcom wants to merge 1 commit intoFlowiseAI:mainfrom
TeamInfinixdevcom:fix-safe-json-model-loader
Open

Fix: prevent crash when parsing invalid JSON in analytics handler#5906
TeamInfinixdevcom wants to merge 1 commit intoFlowiseAI:mainfrom
TeamInfinixdevcom:fix-safe-json-model-loader

Conversation

@TeamInfinixdevcom
Copy link

This PR introduces defensive JSON parsing for analytics configuration
to prevent runtime crashes when JSON.parse receives empty or malformed input.

Changes:

  • Added safeJsonParse helper in utils.ts
  • Replaced JSON.parse with safeJsonParse in handler.ts
  • Added validation to ensure analytic config is a valid object

This preserves existing behavior for valid JSON while preventing crashes.

Copilot AI review requested due to automatic review settings March 4, 2026 21:43
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the application's resilience by implementing defensive JSON parsing. By introducing a safeJsonParse utility and integrating it into critical areas like analytics configuration and Google credential handling, the changes prevent crashes that would otherwise occur when encountering malformed or empty JSON data. This ensures the application continues to function reliably even with unexpected input, maintaining existing behavior for valid JSON while bolstering error handling.

Highlights

  • Defensive JSON Parsing: Introduced a new safeJsonParse utility function to handle potentially invalid or empty JSON inputs gracefully, preventing runtime crashes.
  • Analytics Configuration Robustness: Replaced direct JSON.parse calls with safeJsonParse in the analytics handler and added validation to ensure the parsed analytic configuration is a valid object.
  • Google Credentials Parsing: Applied safeJsonParse to the parsing of Google application credentials, enhancing the stability of credential handling.
Changelog
  • packages/components/src/google-utils.ts
    • Imported the new safeJsonParse utility.
    • Modified the logic for parsing googleApplicationCredential to use safeJsonParse, falling back to the original credential if parsing fails.
  • packages/components/src/handler.ts
    • Imported the new safeJsonParse utility.
    • Replaced JSON.parse with safeJsonParse when processing options.analytic in additionalCallbacks.
    • Added validation to ensure the analytic object is not null, an object, and not an array after parsing in additionalCallbacks.
    • Replaced JSON.parse with safeJsonParse when processing this.options.analytic in AnalyticHandler.
    • Added validation to ensure the analytic object is not null, an object, and not an array after parsing in AnalyticHandler.
  • packages/components/src/utils.ts
    • Added a new safeJsonParse function that attempts to parse a string as JSON and returns null if the input is empty, whitespace-only, or causes a parsing error.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a safeJsonParse utility. The safeJsonParse utility has been modified to prevent a Denial of Service vulnerability by adding robust type validation and ensuring consistent handling of nullish and non-string inputs, aligning with repository idioms for nullish checks. Additionally, the implementation in google-utils.ts has been reviewed to prevent deferred runtime errors by ensuring that only valid, parsed objects are assigned to authOptions.credentials.

Comment on lines +22 to +25
else if (!googleApplicationCredentialFilePath && googleApplicationCredential) {
const parsedCredential = safeJsonParse(googleApplicationCredential)
authOptions.credentials = parsedCredential ?? googleApplicationCredential
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The current implementation parsedCredential ?? googleApplicationCredential can lead to runtime errors. If safeJsonParse fails and returns null, the original (and likely malformed) googleApplicationCredential string is assigned to authOptions.credentials. The credentials property expects an object, not a string. This would replace an immediate crash with a deferred one. To fix this, we should only assign the parsed value if it's a valid object, similar to the validation added in handler.ts.

Suggested change
else if (!googleApplicationCredentialFilePath && googleApplicationCredential) {
const parsedCredential = safeJsonParse(googleApplicationCredential)
authOptions.credentials = parsedCredential ?? googleApplicationCredential
}
else if (!googleApplicationCredentialFilePath && googleApplicationCredential) {
const parsedCredential = safeJsonParse(googleApplicationCredential);
if (parsedCredential && typeof parsedCredential === 'object' && !Array.isArray(parsedCredential)) {
authOptions.credentials = parsedCredential;
}
}

Comment on lines +127 to +128
export function safeJsonParse(input: string) {
if (!input || input.trim() === '') return null
Copy link
Contributor

Choose a reason for hiding this comment

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

security-medium medium

The safeJsonParse function is vulnerable to a Denial of Service (DoS) attack because it does not validate the type of the input parameter before calling the .trim() method. If the function is called with a non-string value (such as an object, array, number, or boolean), it will throw a TypeError. This can lead to a server crash if the input is derived from untrusted or malformed configuration data, such as the options.analytic or googleApplicationCredential parameters used in this pull request.

To ensure consistent handling of nullish and non-string inputs, and to align with the repository's idiom for nullish checks, the function should return null for null, undefined, empty strings, and any other non-string inputs that cannot be parsed as JSON. This also prevents the TypeError.

if (input == null || (typeof input === 'string' && input.trim() === '')) return null;
if (typeof input !== 'string') return null;
References
  1. In JavaScript/TypeScript, use loose equality (== null) as a standard idiom for a 'nullish' check that covers both null and undefined.

Copy link
Contributor

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

This PR adds defensive JSON parsing to prevent runtime crashes when analytics (and related credential) configuration contains empty or malformed JSON, by introducing a safe JSON parsing helper and replacing direct JSON.parse usage in analytics handling.

Changes:

  • Added safeJsonParse helper to return null instead of throwing on invalid/empty JSON input.
  • Updated analytics handler paths (additionalCallbacks, AnalyticHandler.init) to use safeJsonParse and validate the parsed config is an object.
  • Updated Google credentials builder to use safeJsonParse instead of direct JSON.parse.

Reviewed changes

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

File Description
packages/components/src/utils.ts Introduces safeJsonParse helper used to prevent JSON parsing crashes.
packages/components/src/handler.ts Switches analytics config parsing to safeJsonParse and adds object-shape validation before iterating providers.
packages/components/src/google-utils.ts Uses safeJsonParse for Google credential JSON to avoid throwing on malformed input.

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

Comment on lines +520 to 522
const analytic = safeJsonParse(options.analytic ?? '')
if (!analytic || typeof analytic !== 'object' || Array.isArray(analytic)) return []
const callbacks: any = []
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

There are existing Jest tests for handler.ts, but the new defensive analytics parsing/validation path isn’t covered. Please add tests that verify malformed/empty options.analytic (and this.options.analytic) no longer throw and instead return [] / short-circuit initialization, to prevent regressions of the crash this PR is fixing.

Copilot uses AI. Check for mistakes.
Comment on lines +780 to 782
const analytic = safeJsonParse(this.options.analytic ?? '')
if (!analytic || typeof analytic !== 'object' || Array.isArray(analytic)) return
for (const provider in analytic) {
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

Same as above: please add coverage for invalid JSON in this.options.analytic to ensure AnalyticHandler.init() doesn’t throw and correctly exits early when the config is malformed (and that valid JSON still initializes providers).

Copilot uses AI. Check for mistakes.
Comment on lines +127 to +130
export function safeJsonParse(input: string) {
if (!input || input.trim() === '') return null
try {
return JSON.parse(input)
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

safeJsonParse can still throw when input is not a string (e.g., an object from getCredentialParam), because input.trim() is executed before the try/catch. That undermines the goal of preventing crashes. Consider changing the signature to accept unknown and guarding with typeof input === 'string' (and/or moving the trim check inside the try) so non-string values safely return null (or pass through if you want to support already-parsed objects).

Suggested change
export function safeJsonParse(input: string) {
if (!input || input.trim() === '') return null
try {
return JSON.parse(input)
export function safeJsonParse(input: unknown) {
if (typeof input !== 'string') return null
const trimmed = input.trim()
if (!trimmed) return null
try {
return JSON.parse(trimmed)

Copilot uses AI. Check for mistakes.
authOptions.credentials = JSON.parse(googleApplicationCredential)
else if (!googleApplicationCredentialFilePath && googleApplicationCredential) {
const parsedCredential = safeJsonParse(googleApplicationCredential)
authOptions.credentials = parsedCredential ?? googleApplicationCredential
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

On parse failure, this now assigns authOptions.credentials to the raw googleApplicationCredential value (likely a string). Downstream libraries typically expect an object for credentials, so this can turn a clear JSON parse error into a later, harder-to-debug runtime/config error. Consider validating that the parsed value is a non-null object (and not an array) and either throw a user-friendly error when invalid, or avoid setting credentials unless it parsed to the expected shape.

Suggested change
authOptions.credentials = parsedCredential ?? googleApplicationCredential
if (parsedCredential && typeof parsedCredential === 'object' && !Array.isArray(parsedCredential)) {
authOptions.credentials = parsedCredential
} else {
throw new Error('Invalid Google Application Credential JSON; expected a JSON object.')
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants