Question

Why Some JSON Responses Start with while(1); in JavaScript

javascriptjsonajaxsecurity

Question

Why do some Google private JSON responses begin with while (1);?

For example, when toggling a calendar setting in Google Calendar, the response may look like this:

while (1);
[
  ['u', [
    ['smsSentFlag', 'false'],
    ['hideInvitations', 'false'],
    ['remindOnRespondedEventsOnly', 'true'],
    ['hideInvitations_remindOnRespondedEventsOnly', 'false_true'],
    ['Calendar ID stripped for privacy', 'false'],
    ['smsVerifiedFlag', 'true']
  ]]
]

It seems like this might be done to stop developers from calling eval() directly on the response, since the response is no longer valid JavaScript data by itself. However, someone could still manually remove the prefix.

I have also seen similar prefixes such as &&&START&&&, and in some cases both while(1); and &&&START&&& together.

What is the purpose of these prefixes, and what problem are they trying to solve?

Short Answer

By the end of this page, you will understand why some web applications prepend strings like while(1); to JSON responses, what JSON hijacking is, why this was historically important in JavaScript applications, and what safer modern alternatives are commonly used today.

Concept

The core idea

Prefixes like while(1); are a defensive trick added before JSON responses so the response is not directly executable as JavaScript.

This was mainly used to reduce the risk of a class of attacks often called JSON hijacking or cross-site script inclusion attacks.

Why this mattered

In older web applications, some endpoints returned sensitive data as raw JSON, often arrays or objects. If that JSON could be loaded in a <script> tag from another site, the browser might execute it as JavaScript in a way that exposed private data.

For example, if an authenticated user visited a malicious site, that site might try to load a private JSON endpoint from another domain:

<script src="https://example.com/private-data"></script>

If the response was valid executable JavaScript, the attacker could sometimes abuse that behavior.

What while(1); does

This prefix makes the response invalid as plain JSON and also useless when treated as a script:

while (1);
[{"secret":"data"}]

If a browser tries to execute that as JavaScript, it gets stuck in an infinite loop before reaching the data. That means the payload cannot be meaningfully consumed through script inclusion.

A legitimate client that expects this format can strip the prefix first, then parse the remaining JSON safely.

Why not just trust developers not to use eval()?

The main goal was not only to discourage eval(). It was to protect against browser behavior and cross-origin attacks, especially in older browsers and older application architectures.

Even if someone can manually remove the prefix, an attacker loading the endpoint through a <script> tag cannot easily do that before execution.

Why other prefixes like &&&START&&& exist

Different applications used different non-JSON prefixes:

  • while(1);
  • for(;;);
  • )]}',
  • &&&START&&&

All of them serve a similar purpose:

  • make the response invalid as raw JSON
  • make it non-executable or inconvenient as JavaScript
  • require the intended client to explicitly strip the prefix before parsing

Modern context

Today, this is less common because APIs usually rely on stronger protections such as:

  • proper Content-Type: application/json
  • CORS rules
  • CSRF protections
  • authentication headers or tokens
  • SameSite cookies
  • avoiding sensitive GET JSON endpoints where possible

So the prefix was a practical historical defense, especially for private endpoints used by large JavaScript applications.

Mental Model

Think of the JSON response as a package being shipped.

  • A normal JSON response is like a package with the contents immediately visible.
  • A prefixed response adds a tamper seal on top.
  • The official client knows how to remove the seal first.
  • A browser blindly executing it as a script trips over the seal and cannot use the contents directly.

while(1); is an extreme kind of seal: if you try to "run" the package as code, you never get past the first line.

So the prefix is not meant to make the data impossible to read forever. It is meant to stop the browser from accidentally treating private data as executable script in the wrong context.

Take Quiz

Syntax and Examples

Basic pattern

A server may return something like this:

while (1);
{"name":"Alice","role":"admin"}

That is not valid JSON because of the extra prefix.

A trusted client can remove the prefix and then parse the rest.

Example in JavaScript

const responseText = 'while (1);{"name":"Alice","role":"admin"}';

const cleaned = responseText.replace(/^while \(1\);/, '');
const data = JSON.parse(cleaned);

console.log(data.name); // Alice

Another common prefix

const responseText = ")]}',\n{"ok":true}";
const cleaned = responseText.replace(/^\)\]\}',\n/, '');
const data = JSON.parse(cleaned);

Important point

Use JSON.parse() after removing the known prefix.

Do not do this:

const data = eval(responseText);

eval() executes code and is unsafe for parsing server responses.

Safer server idea

A modern API would usually just return:

{"name":"Alice","role":"admin"}

and protect the endpoint using proper headers, cookies, tokens, and origin rules rather than relying on a defensive prefix alone.

Step by Step Execution

Example response

while (1);
["red", "green", "blue"]

Client-side processing

const responseText = 'while (1);["red", "green", "blue"]';
const cleaned = responseText.replace(/^while \(1\);/, '');
const colors = JSON.parse(cleaned);

console.log(colors[1]);

Step by step

1. The server sends text

The client receives this exact string:

while (1);["red", "green", "blue"]

2. The prefix is removed

This line removes the anti-execution prefix:

const cleaned = responseText.replace(/^while \(1\);/, '');

Now cleaned becomes:

["red", "green", "blue"]

3. The JSON is parsed

const colors = JSON.parse(cleaned);

Now colors is a real JavaScript array:

["red", "green", "blue"]

4. Normal code can use the data

console.log(colors[1]);

Output:

green

What happens if a browser executes it as a script?

The browser starts with:

while (1);

That creates an infinite loop. The rest is never reached in a useful way. This is exactly why the prefix was used as a defense.

Real World Use Cases

1. Private web app endpoints

Large JavaScript applications such as mail, calendar, and admin dashboards often had internal endpoints returning structured data. Prefixes were used so those endpoints could not be safely included as scripts from another origin.

2. Protecting authenticated GET responses

If a browser automatically sent cookies with a request, a malicious site might try to load a user's private data through a <script> tag. Prefixing the response reduced that risk.

3. Legacy AJAX applications

Before modern browser security features became standard, many applications used custom response formats and defensive prefixes as an extra layer of protection.

4. Internal APIs with custom clients

Some apps controlled both server and client code. That made it practical to add a prefix server-side and remove it client-side before parsing.

5. Defensive parsing conventions

Even today, some systems add a non-JSON prefix like )]}', to ensure the client explicitly recognizes and parses the payload rather than accidentally executing it.

Take Quiz

Real Codebase Usage

Common patterns in real projects

Explicit response normalization

Developers often create a small utility that removes known prefixes before parsing:

function parseSafeJson(text) {
  const cleaned = text
    .replace(/^while \(1\);/, '')
    .replace(/^for \(;;\);/, '')
    .replace(/^\)\]\}',?\n/, '');

  return JSON.parse(cleaned);
}

This keeps the parsing logic in one place.

Guard clauses

A parser may first verify that the payload begins with an expected prefix or valid JSON token:

function parseGoogleStyleResponse(text) {
  if (text.startsWith('while (1);')) {
    text = text.slice('while (1);'.length);
  }

  return JSON.parse(text);
}

Validation before parsing

In production code, developers often validate that the cleaned result looks like JSON before parsing:

function looksLikeJson(text) {
  return text.trim().startsWith('{') || text.trim().startsWith('[');
}

Error handling

Real code should handle malformed responses gracefully:

function safeParseResponse(text) {
  try {
    const cleaned = text.replace(/^while \(1\);/, '');
    return { ok: true, data: JSON.parse(cleaned) };
  } catch (error) {
    return { ok: false, error: 'Invalid server response' };
  }
}

Why this matters in a real codebase

  • keeps parsing logic consistent
  • avoids eval()
  • makes migrations easier if the server format changes
  • centralizes legacy compatibility code

Common Mistakes

1. Treating prefixed JSON as normal JSON

This will fail because the response contains extra characters before the JSON.

Broken code:

const text = 'while (1);{"ok":true}';
JSON.parse(text); // Error

Fix:

const cleaned = text.replace(/^while \(1\);/, '');
JSON.parse(cleaned);

2. Using eval() to parse the response

Broken code:

const data = eval(text);

Why it is wrong:

  • executes code instead of parsing data
  • unsafe for untrusted input
  • unnecessary in modern JavaScript

Fix:

const data = JSON.parse(cleaned);

3. Removing the prefix too loosely

If you do a generic replace, you may accidentally modify valid content later in the string.

Less safe:

text = text.replace('while (1);', '');

Better:

text = text.replace(/^while \(1\);/, '');

The ^ means only remove it from the start.

4. Assuming the prefix is a complete security solution

The prefix is only one defense. It does not replace:

  • authentication
  • authorization
  • CSRF protection
  • CORS policy
  • secure cookie settings

5. Forgetting that many old endpoints returned arrays

Historically, top-level arrays were especially discussed in JSON hijacking scenarios. Developers sometimes miss the historical context and think the prefix was random formatting rather than a security measure.

Comparisons

Related approaches

ApproachWhat it doesMain purposeStill common?
Raw JSONReturns plain JSON directlySimple API responsesYes
while(1); prefixMakes response non-JSON and non-useful as scriptMitigate JSON hijackingMostly legacy
for(;;); prefixSame idea as while(1);Mitigate script inclusion abuseMostly legacy
)]}', prefixBreaks JavaScript parsing and signals custom parsingXSSI protectionStill seen sometimes
&&&START&&& prefixCustom marker before payloadFraming and defensive parsingRare, custom

JSON.parse() vs eval()

MethodPurposeSafe for JSON parsing?Notes
JSON.parse()Parses JSON textYesPreferred approach
eval()Executes JavaScript codeNoDangerous and unnecessary

Old defense vs modern defense

TechniqueBest useLimitation
Prefixing responsesExtra protection for legacy browser behaviorNot enough by itself
CORSControls which origins can read responsesDoes not replace auth
CSRF tokensProtects state-changing requestsNot directly about reading JSON
SameSite cookiesRestricts cross-site cookie sendingBrowser-dependent behavior
Auth headers/tokensProtects private endpointsMust be implemented correctly
Take Quiz

Cheat Sheet

Quick reference

What is while(1); before JSON?

A defensive prefix added before a JSON payload so the response is not directly executable as JavaScript.

Why was it used?

Mostly to reduce the risk of JSON hijacking or cross-site script inclusion attacks in older web apps.

What should a client do?

  1. Remove the known prefix
  2. Parse the remaining text with JSON.parse()

Example

const cleaned = text.replace(/^while \(1\);/, '');
const data = JSON.parse(cleaned);

Common prefixes

while (1);
for (;;);
)]}',
&&&START&&&

Do not do this

eval(text)

Important rule

A prefix is an extra defense, not a replacement for:

  • authentication
  • authorization
  • CORS
  • CSRF protection
  • secure cookies

Modern recommendation

Prefer plain JSON with proper web security controls unless you must support a legacy protocol or client.

FAQ

Why does while(1); stop the response from being used as a script?

Because it starts an infinite loop immediately, so the rest of the response is never usefully executed when treated as JavaScript.

Is while(1); valid JSON?

No. It makes the response invalid as raw JSON until the prefix is removed.

Was this mainly about stopping eval()?

Not primarily. It was mainly a defense against browsers loading private JSON endpoints as scripts from another site.

Why could a normal client still use the response?

Because the intended client knows to remove the prefix first and then parse the remaining JSON.

What is JSON hijacking?

It is a class of attacks where a malicious site tries to exploit how browsers handle script loading to access sensitive JSON from another origin.

Why do some services use )]}', instead?

It serves a similar purpose: making the response invalid or non-executable until the client explicitly strips the prefix.

Is this still needed in modern APIs?

Usually not as a primary defense. Modern APIs more commonly rely on CORS, CSRF protection, secure cookies, and token-based authentication.

Should I add while(1); to my own API?

Usually no, unless you are maintaining a legacy client/server contract. For new APIs, plain JSON plus proper security controls is typically better.

Take Quiz

Mini Project

Description

Build a small JavaScript parser that accepts server responses containing anti-execution prefixes such as while(1); or )]}', and safely converts them into usable JavaScript data. This mirrors the kind of compatibility code developers write when integrating with legacy or private endpoints.

Goal

Create a function that strips known prefixes and safely parses the remaining JSON using JSON.parse().

Requirements

  • Write a function that accepts a response string.
  • Remove at least two known protective prefixes if they appear at the start.
  • Parse the cleaned text as JSON.
  • Return the parsed result.
  • Handle invalid input without using eval().
Take Quiz

Keep learning

Related questions

View more