Back to Blog
critical SEVERITY5 min read

How Remote Configuration Injection happens in JavaScript fetch() and how to fix it

A critical vulnerability in `js/config.js` allowed attackers to inject malicious configuration data through DNS spoofing or man-in-the-middle attacks. The application fetched remote JSON configuration from GitHub without validating the response structure, enabling arbitrary code execution through crafted payloads. A single validation check now ensures only properly-formed configuration objects are accepted.

O
By Orbis AppSec
Published July 24, 2026Reviewed July 24, 2026

Answer Summary

Remote Configuration Injection (CWE-20) occurs in JavaScript when fetch() retrieves external JSON configuration without validating the response structure. In this case, `js/config.js` fetched remote `info.json` files and only checked HTTP status codes, not data integrity. The fix adds type validation (`typeof remoteInfo !== 'object' || remoteInfo === null || Array.isArray(remoteInfo)`) to reject malformed or malicious payloads before processing.

Vulnerability at a Glance

cweCWE-20 (Improper Input Validation)
fixAdded type checking to ensure remoteInfo is a valid non-null, non-array object
riskAttackers can inject malicious configuration through MITM or DNS spoofing attacks
languageJavaScript
root causeMissing validation of fetched JSON structure before processing
vulnerabilityRemote Configuration Injection via Unvalidated JSON Response

Introduction

The js/config.js file in this application handles dynamic configuration loading, fetching remote info.json files from GitHub raw content URLs to check for updates. However, a critical flaw at line 49 created a dangerous security gap: the code only verified that the HTTP response returned successfully (res.ok), but never validated that the returned data was actually a legitimate configuration object.

This oversight meant that an attacker who could intercept network traffic—through DNS hijacking, ARP spoofing, or compromising an upstream server—could inject arbitrary JSON payloads that the application would blindly trust and process. The remoteInfo variable would accept any valid JSON, including arrays, primitives, or objects with malicious properties that could corrupt application state or trigger unintended behavior.

The Vulnerability Explained

Let's examine the vulnerable code path:

const remoteInfo = await fetch(
    'https://raw.githubusercontent.com/...'
).then(res => {
    if (!res.ok) throw new Error('获取远程info.json失败');
    return res.json();
});
const remoteTime = String(remoteInfo.lastEditTime || '');
const localTime = String(lib.extensionPack['活动武将'].lastEditTime || '');

The code fetches a remote JSON file and immediately accesses properties like lastEditTime without verifying that remoteInfo is actually a valid configuration object. Here's what's missing:

  1. No type validation: The response could be an array [], a string "malicious", a number 42, or null
  2. No schema validation: Even if it's an object, it might contain unexpected properties
  3. No integrity verification: There's no cryptographic signature or hash to verify the content hasn't been tampered with

Attack Scenario

Imagine an attacker performing DNS spoofing on a corporate network:

  1. The attacker intercepts DNS queries for raw.githubusercontent.com
  2. Requests are redirected to an attacker-controlled server
  3. The malicious server responds with HTTP 200 and a crafted payload:
["__proto__", {"polluted": "true"}]

Or even more dangerously:

{
    "lastEditTime": "2099-12-31",
    "constructor": {"prototype": {"admin": true}}
}

Since the application only checks res.ok, this malicious payload passes through. Depending on how the configuration is processed downstream, this could lead to:

  • Prototype pollution attacks if object properties are merged unsafely
  • Application state corruption causing crashes or undefined behavior
  • Logic bypass if configuration values control security-sensitive features
  • Denial of service if the application expects specific data types

The Fix

The fix adds a single but crucial validation line at js/config.js:53:

Before (Vulnerable)

const remoteInfo = await fetch(
    'https://raw.githubusercontent.com/...'
).then(res => {
    if (!res.ok) throw new Error('获取远程info.json失败');
    return res.json();
});
const remoteTime = String(remoteInfo.lastEditTime || '');

After (Secure)

const remoteInfo = await fetch(
    'https://raw.githubusercontent.com/...'
).then(res => {
    if (!res.ok) throw new Error('获取远程info.json失败');
    return res.json();
});
if (typeof remoteInfo !== 'object' || remoteInfo === null || Array.isArray(remoteInfo)) 
    throw new Error('远程info.json数据无效');
const remoteTime = String(remoteInfo.lastEditTime || '');

This validation ensures:

Check Purpose
typeof remoteInfo !== 'object' Rejects primitives (strings, numbers, booleans)
remoteInfo === null Rejects null (which has typeof "object" in JavaScript)
Array.isArray(remoteInfo) Rejects arrays (which are also objects in JavaScript)

If any of these conditions are true, the application throws an error with the message "远程info.json数据无效" (Remote info.json data invalid), preventing malicious payloads from being processed.

Prevention & Best Practices

1. Always Validate External Data Structure

// Good: Validate before use
const data = await response.json();
if (!isValidConfigObject(data)) {
    throw new Error('Invalid configuration format');
}

function isValidConfigObject(obj) {
    return (
        typeof obj === 'object' &&
        obj !== null &&
        !Array.isArray(obj) &&
        typeof obj.lastEditTime === 'string'
    );
}

2. Consider Schema Validation Libraries

For complex configurations, use libraries like Zod, Yup, or JSON Schema:

import { z } from 'zod';

const ConfigSchema = z.object({
    lastEditTime: z.string(),
    version: z.string().optional(),
});

const remoteInfo = ConfigSchema.parse(await response.json());

3. Implement Integrity Verification

For sensitive configurations, consider:

  • Subresource Integrity (SRI): Hash-based verification
  • Digital signatures: Sign configuration files and verify signatures
  • Certificate pinning: Prevent MITM attacks at the TLS level

4. Use Content Security Policy

Restrict which domains can be fetched:

// In your CSP headers
connect-src 'self' https://raw.githubusercontent.com;

Key Takeaways

  • Never trust res.ok alone: HTTP status codes don't guarantee content integrity
  • The typeof operator returns "object" for both null and arrays: Always check explicitly with === null and Array.isArray()
  • Remote configuration endpoints are high-value targets: They can affect application behavior without modifying code
  • The remoteInfo.lastEditTime access assumed valid object structure: Defensive programming requires validating assumptions
  • One line of validation prevented a critical attack vector: Simple input validation is often the most effective defense

How Orbis AppSec Detected This

  • Source: Remote JSON data fetched from https://raw.githubusercontent.com/... via fetch() API
  • Sink: Direct property access on remoteInfo.lastEditTime at js/config.js:53 without type validation
  • Missing control: No validation that the parsed JSON response was a valid configuration object (non-null, non-array object type)
  • CWE: CWE-20 (Improper Input Validation)
  • Fix: Added type checking (typeof remoteInfo !== 'object' || remoteInfo === null || Array.isArray(remoteInfo)) to reject malformed responses before processing

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

This vulnerability demonstrates a common but dangerous pattern: trusting that external data will conform to expected formats. The fix—a single validation line—shows that effective security doesn't always require complex solutions. By validating that remoteInfo is a proper object before accessing its properties, the application now rejects malicious payloads that could have been injected through network-level attacks.

When working with remote data sources, always validate the structure and type of received data before processing. This is especially critical for configuration data that can influence application behavior. Remember: in JavaScript, typeof null === 'object' and arrays are objects too—explicit checks are essential.

References

Frequently Asked Questions

What is Remote Configuration Injection?

Remote Configuration Injection occurs when an application fetches configuration data from external sources without validating its structure or authenticity, allowing attackers to inject malicious settings that alter application behavior.

How do you prevent Remote Configuration Injection in JavaScript?

Validate all fetched JSON responses by checking data types, required fields, and value ranges. Use integrity checks like Subresource Integrity (SRI) hashes, implement certificate pinning, and consider signing configuration files cryptographically.

What CWE is Remote Configuration Injection?

Remote Configuration Injection typically falls under CWE-20 (Improper Input Validation), though it may also relate to CWE-494 (Download of Code Without Integrity Check) when the configuration can influence code execution.

Is checking HTTP status codes enough to prevent configuration injection?

No. HTTP status codes only indicate whether the server responded successfully, not whether the response content is legitimate. Attackers performing MITM attacks can return valid 200 responses with malicious payloads.

Can static analysis detect Remote Configuration Injection?

Yes. Static analyzers can identify patterns where fetch() or similar APIs retrieve external data that flows into sensitive operations without validation. Tools like Semgrep can flag missing input validation on network responses.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #230

Related Articles

high

How Sensitive Data Exposure happens in Zotero plugins and how to fix it

A high-severity data exposure vulnerability in `Zotero.ts` automatically transmitted complete document metadata—including private notes, attachment paths, and tags—to external LLM services without user consent. The fix replaces broad `item.toJSON()` serialization with explicit field selection, sending only essential bibliographic data.

high

How missing dependency update cooldowns happen in GitHub Dependabot configurations and how to fix it

A semgrep scan flagged `.github/dependabot.yml` for lacking a cooldown period, meaning Dependabot would immediately propose updates to brand-new package versions across npm, Bundler, and Docker ecosystems. The fix adds a `cooldown: default-days: 7` block to every `package-ecosystem` entry, forcing a one-week waiting period before newly published releases are considered — reducing exposure to malicious or unstable package drops.

high

How dependabot-missing-cooldown happens in GitHub Actions/Node.js and how to fix it

The repository's `.github/dependabot.yml` had no cooldown period configured, meaning Dependabot could immediately propose updates to newly published package versions with zero time for the community to flag malware or instability. The fix adds a `cooldown` block with `default-days: 7` to both the `npm` and `github-actions` ecosystems, forcing a 7-day waiting period before new releases are surfaced as update PRs.

high

How Path Traversal Happens in TensorFlow's Data Service and How to Fix It

TensorFlow's data service dispatcher validated dataset IDs against forward-slash traversal attacks but overlooked backslash characters on non-Windows platforms, allowing attackers to escape the root directory. A targeted fix adds explicit backslash validation across all platforms, closing a high-severity path traversal vulnerability in the snapshot management system.

critical

How Unbounded WebSocket Message Handling Causes Resource Exhaustion in Node.js and How to Fix It

The WebSocketCrossServerAdapter class in a popular Node.js WebSocket library lacked any rate limiting on inbound messages, allowing attackers to flood Redis nodes and WebSocket servers with high-volume traffic. The fix introduces a configurable `rateLimit` option that caps messages per connection per second, preventing resource exhaustion while preserving legitimate functionality.

critical

How Remote Code Execution Happens in Handlebars Template Compilation and How to Fix It

CVE-2026-33937 is a critical remote code execution vulnerability in Handlebars.js that allows attackers to execute arbitrary code by passing maliciously crafted Abstract Syntax Tree (AST) objects to the compile() function. The vulnerability was patched in version 4.7.9, and we've upgraded to protect against this threat vector.