Skip to content

[BUGFIX] Missing await on async fetch calls#4

Open
GAURAV-1313 wants to merge 2 commits into
masterfrom
bugfix/missing-await
Open

[BUGFIX] Missing await on async fetch calls#4
GAURAV-1313 wants to merge 2 commits into
masterfrom
bugfix/missing-await

Conversation

@GAURAV-1313

Copy link
Copy Markdown
Owner

Async fetch calls missing await, returns Promise instead of data.

@netlify

netlify Bot commented Jun 24, 2026

Copy link
Copy Markdown

Deploy Preview for nofriction canceled.

Name Link
🔨 Latest commit 8171964
🔍 Latest deploy log https://app.netlify.com/projects/nofriction/deploys/6a3c346fef6ea600085deebc

@GAURAV-1313

GAURAV-1313 commented Jun 24, 2026

Copy link
Copy Markdown
Owner Author

AI Code Review

Summary

The introduced async function has multiple async/await issues and lacks input validation, which leads to probable runtime errors and unstable behavior under erroneous conditions.

Key Findings

Bugs

  • [CRITICAL] fetchAndProcess function — missing await before fetch call and before response.json() call leads to response and data being unresolved promises — causes runtime errors and failure to retrieve expected data.
  • [HIGH] fetchAndProcess function — no validation of input parameter 'url' (e.g., null, non-string, or invalid URL) — potential unhandled rejection or unexpected behavior.
  • [HIGH] fetchAndProcess function — direct access to data.items without checking if data is non-null or has items property — possible runtime exception if API response is malformed.

Security

  • HIGH In function fetchAndProcess, the input 'url' is used directly in the fetch call without any validation or sanitization. This can lead to Server-Side Request Forgery (SSRF) attacks, where an attacker can cause the server to make unauthorized requests to internal or external systems.
  • MEDIUM Missing await keyword before fetch and response.json calls in fetchAndProcess function leads to 'response' being a Promise object instead of the resolved response, causing possible runtime errors and unhandled Promise situations.

Performance

  • Missing await on asynchronous fetch and json parsing calls in fetchAndProcess function causes promise creation without resolution, leading to unintended concurrent behavior and potential unhandled promise usage

Recommended Fixes

General

  • Add 'await' to the fetch and response.json() calls to properly handle promises.
  • Implement validation for the 'url' parameter to ensure it is a non-empty valid string before using it.
  • Add checks to verify that the parsed JSON data is an object and contains the 'items' property before accessing it to avoid runtime exceptions.

Security Fixes

  • In function fetchAndProcess, the input 'url' is used directly in the fetch call without any validation or sanitization. This can lead to Server-Side Request Forgery (SSRF) attacks, where an attacker can cause the server to make unauthorized requests to internal or external systems. — Implement strict validation and allow-listing of URLs before making fetch calls. Use a URL parsing library to ensure the scheme is HTTPS and restrict the hostname to trusted domains only.
  • Missing await keyword before fetch and response.json calls in fetchAndProcess function leads to 'response' being a Promise object instead of the resolved response, causing possible runtime errors and unhandled Promise situations. — Add 'await' before the fetch and response.json calls: 'const response = await fetch(url); const data = await response.json();' to ensure correct asynchronous behavior.

Performance Fixes

  • Missing await on asynchronous fetch and json parsing calls in fetchAndProcess function causes promise creation without resolution, leading to unintended concurrent behavior and potential unhandled promise usage — Add await keyword before fetch(url) and response.json() calls to properly serialize asynchronous operations and ensure data consistency

Suggested Tests

fetchAndProcess

import { fetchAndProcess } from "./api";

describe("fetchAndProcess", () => {
  beforeEach(() => {
    global.fetch = jest.fn();
  });

  afterEach(() => {
    jest.restoreAllMocks();
  });

  it("should return items array when fetch and json resolve correctly", async () => {
    const mockItems = [{ id: 1 }, { id: 2 }];
    const mockJson = jest.fn().mockResolvedValue({ items: mockItems });
    const mockResponse = { json: mockJson };
    global.fetch.mockResolvedValue(mockResponse);

    const url = "https://example.com/api";
    const result = await fetchAndProcess(url);

    expect(global.fetch).toHaveBeenCalledWith(url);
    expect(mockJson).toHaveBeenCalled();
    expect(Array.isArray(result)).toBe(true);
    expect(result).toEqual(mockItems);
  });

  it("should handle empty items array from response", async () => {
    const mockJson = jest.fn().mockResolvedValue({ items: [] });
    const mockResponse = { json: mockJson };
    global.fetch.mockResolvedValue(mockResponse);

    const result = await fetchAndProcess("https://example.com/api");

    expect(Array.isArray(result)).toBe(true);
    expect(result.length).toBe(0);
  });

  it("should throw if fetch rejects", async () => {
    global.fetch.mockRejectedValue(new Error("Network error"));

    await expect(fetchAndProcess("https://example.com/api")).rejects.toThrow("Network error");
  });

  it("should throw if json parsing fails", async () => {
    const mockJson = jest.fn().mockRejectedValue(new Error("Invalid JSON"));
    const mockResponse = { json: mockJson };
    global.fetch.mockResolvedValue(mockResponse);

    await expect(fetchAndProcess("https://example.com/api")).rejects.toThrow("Invalid JSON");
  });

  it("should throw if data.items is undefined", async () => {
    const mockJson = jest.fn().mockResolvedValue({ noItems: true });
    const mockResponse = { json: mockJson };
    global.fetch.mockResolvedValue(mockResponse);

    await expect(fetchAndProcess("https://example.com/api")).rejects.toThrow(TypeError);
  });

  it("should throw if called with undefined url", async () => {
    await expect(fetchAndProcess(undefined)).rejects.toThrow();
  });

  it("should not mutate input url", async () => {
    const url = "https://example.com/api";
    const urlCopy = url;

    const mockJson = jest.fn().mockResolvedValue({ items: [1, 2] });
    const mockResponse = { json: mockJson };
    global.fetch.mockResolvedValue(mockResponse);

    await fetchAndProcess(url);

    expect(url).toBe(urlCopy);
  });
});

Auto-Fix Available

Add the apply-ai-fixes label to this pull request to have RepoSpace
automatically generate and commit code fixes for the issues listed above.


6 issues found. Reviewed by RepoSpace AI.

- src/api.js: Added 'await' to fetch and response.json() to handle asynchronous operations correctly.
@GAURAV-1313

Copy link
Copy Markdown
Owner Author

Auto-Fix Results

Applied (1)

  • src/api.js — Added 'await' to fetch and response.json() to handle asynchronous operations correctly.

Generated by RepoSpace AI. Review AI commits before merging.

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.

1 participant