September 6, 2026
True, “true”, 1 or [] — Does Your API Treat Them the Same?
A Pentester’s Guide to JSON Type Confusion and Server-Side Validation

By Yamini Yadav_369
8 min read
I was testing an API.
The request looked completely normal.
The application expected a simple boolean value:
{
"enabled": true
}{
"enabled": true
}Nothing unusual.
The frontend only allowed the user to select:
Enabled or Disabled.
So I started asking a different question:
What happens if the API receives something other than the type the developer expected?
What if true becomes "true"?
What if it becomes 1?
What if it becomes []?
Or even {}?
The application may visually restrict the input, but the API does not receive the frontend.
It receives the HTTP request.
And that difference can create interesting security problems.
The Problem With "Valid JSON"
One common assumption during API development is:
"If the request is valid JSON, it is valid input."
That is not true.
JSON allows different data types:
"admin""admin"is a string.
truetrueis a boolean.
11is a number.
[][]is an array.
{}{}is an object.
All of them can be perfectly valid JSON.
The security question is different:
Does the application expect that particular type?
OWASP recommends that APIs validate input for length, range, format and type, and reject unexpected content.
Imagine an API responsible for enabling a security feature.
The intended request is:
POST /api/settings/security
Content-Type: application/json
{
"enabled": true
}POST /api/settings/security
Content-Type: application/json
{
"enabled": true
}The backend expects:
enabled = Booleanenabled = BooleanThe developer might write logic similar to:
if enabled:
activate_feature()
else:
deactivate_feature()if enabled:
activate_feature()
else:
deactivate_feature()At first glance, everything looks fine.
But what happens when the JSON type changes?
For example:
{
"enabled": "true"
}{
"enabled": "true"
}Now enabled is a string.
Or:
{
"enabled": 1
}{
"enabled": 1
}Now it is a number.
Or:
{
"enabled": []
}{
"enabled": []
}Now it is an array.
The important question is no longer:
"Is this valid JSON?"
It becomes:
"How does every layer of the application interpret this value?"
The Frontend Can Hide the Problem
Modern applications usually have several layers:
Browser
↓
Frontend validation
↓
API Gateway
↓
Backend framework
↓
Business logic
↓
DatabaseBrowser
↓
Frontend validation
↓
API Gateway
↓
Backend framework
↓
Business logic
↓
DatabaseThe frontend might enforce:
enabled = true / falseenabled = true / falseBut a pentester can interact directly with the API.
For example, in an authorized test environment, the original request can be captured in Burp Suite:
POST /api/settings/security HTTP/1.1
Host: lab.example
Content-Type: application/json
{
"enabled": true
}POST /api/settings/security HTTP/1.1
Host: lab.example
Content-Type: application/json
{
"enabled": true
}The next step is not immediately trying an exploit.
It is understanding the application's type expectations.
Test 1: Boolean → String
Start with:
{
"enabled": true
}{
"enabled": true
}Then test:
{
"enabled": "true"
}{
"enabled": "true"
}The difference is small but important.
First value:
booleanbooleanSecond value:
stringstringA strongly typed API should normally reject the second request if the schema requires a boolean.
For example:
HTTP/1.1 400 Bad RequestHTTP/1.1 400 Bad Requestwith a response such as:
{
"error": "enabled must be a boolean"
}{
"error": "enabled must be a boolean"
}That is good behaviour.
But if the application accepts both values and processes them identically, you have discovered a type-validation inconsistency.
PortSwigger maintains a Type Confusion Scanner specifically for testing whether integer and boolean JSON values are being accepted as strings by the server.
Test 2: Boolean → Number
Next:
{
"enabled": 1
}{
"enabled": 1
}Again, the question is not whether the JSON is valid.
It is.
The question is whether:
11is being treated as:
truetruesomewhere in the application.
Different programming languages and frameworks have different type-conversion and truthiness behavior.
That is where inconsistencies become interesting.
For a security tester, the important observation is:
Expected type
↓
Actual type
↓
Application interpretation
↓
Security-sensitive decisionExpected type
↓
Actual type
↓
Application interpretation
↓
Security-sensitive decisionIf those four stages do not agree, the application may behave unexpectedly.
Test 3: Boolean → Array
Now things get more interesting.
Try a completely different JSON type:
{
"enabled": []
}{
"enabled": []
}or in a controlled lab:
{
"enabled": {}
}{
"enabled": {}
}A secure API should reject these values when the schema expects a boolean.
Something like:
HTTP/1.1 400 Bad RequestHTTP/1.1 400 Bad Requestis expected.
The important result is not necessarily a successful response.
A different response can itself be useful evidence.
For example:
true → 200
"true" → 200
1 → 200
[] → 500
{} → 500true → 200
"true" → 200
1 → 200
[] → 500
{} → 500Now we have something interesting.
The application is not handling equivalent or unexpected types consistently.
Why a 500 Error Matters
A 500 Internal Server Error does not automatically mean there is a vulnerability.
But it tells the pentester something important:
The application may not be handling unexpected input safely.
OWASP recommends rejecting unexpected input and handling validation failures safely rather than allowing malformed data to travel deeper into the application.
For example:
Expected:
enabled → boolean
Unexpected:
enabled → arrayExpected:
enabled → boolean
Unexpected:
enabled → arrayInstead of:
Request
↓
Parser
↓
Business logic
↓
Exception
↓
500Request
↓
Parser
↓
Business logic
↓
Exception
↓
500the safer flow is:
Request
↓
Strict schema validation
↓
Type mismatch
↓
400 Bad RequestRequest
↓
Strict schema validation
↓
Type mismatch
↓
400 Bad RequestThe difference is important.
But Is Type Confusion Actually a Vulnerability?
Not always.
This is one of the most important lessons.
A server accepting:
{
"id": "123"
}{
"id": "123"
}when it expects:
{
"id": 123
}{
"id": 123
}may simply be a robustness issue.
It becomes much more interesting when the type difference affects a security decision or business rule.
For example:
role
is_admin
enabled
verified
approved
discount
quantity
user_id
tenant_id
access_level
statusrole
is_admin
enabled
verified
approved
discount
quantity
user_id
tenant_id
access_level
statusThese fields can influence application behavior.
Imagine a fictional authorization API:
{
"approved": true
}{
"approved": true
}The intended rule is:
approved must be Booleanapproved must be BooleanBut somewhere in the backend, the value is converted or evaluated differently.
If an unexpected type changes the result of an authorization or business decision, the impact can become significantly more serious.
That is where a simple validation weakness can turn into a real security finding.
The Most Important Test: Compare Behavior
Do not stop after changing one value.
The goal is not simply to find a 200 OK.
The goal is to understand:
How does the application interpret each representation?
Burp Suite Methodology
This is where the testing becomes practical.
Step 1: Capture the normal request
Use the application normally.
Capture the API request in Burp Suite.
Example:
POST /api/profile/preferences
Content-Type: application/json
{
"notifications": true
}POST /api/profile/preferences
Content-Type: application/json
{
"notifications": true
}Step 2: Identify Security-Relevant Fields
Look for parameters related to:
role
permission
status
enabled
verified
approved
tenant
user
access
discount
limit
quantityrole
permission
status
enabled
verified
approved
tenant
user
access
discount
limit
quantityDo not blindly fuzz every parameter.
First understand what the parameter actually controls.
Step 3: Change One Variable
Keep everything else identical.
Original:
{
"notifications": true
}{
"notifications": true
}Test:
{
"notifications": "true"
}{
"notifications": "true"
}Then:
{
"notifications": 1
}{
"notifications": 1
}Then:
{
"notifications": []
}{
"notifications": []
}Then:
{
"notifications": null
}{
"notifications": null
}This makes your testing controlled and reproducible.
Look Beyond the HTTP Status Code
A common pentesting mistake is:
"Both returned 200, so nothing happened."
Not necessarily.
Compare:
HTTP status
Response body
Response length
Response headers
Database state
Application behavior
Authorization result
Object state
Audit logsHTTP status
Response body
Response length
Response headers
Database state
Application behavior
Authorization result
Object state
Audit logsFor example:
true
→ security feature enabled
"true"
→ security feature enabled
1
→ security feature enabled
[]
→ application errortrue
→ security feature enabled
"true"
→ security feature enabled
1
→ security feature enabled
[]
→ application errorThe first three responses reveal a potential type-validation weakness.
The last response reveals an error-handling weakness.
But the actual severity depends on what security-sensitive behavior can be influenced.
The Real Bug Is Often Somewhere Else
This is the part that makes type confusion interesting.
The vulnerability may not exist in the API endpoint itself.
It could appear because different components interpret the same value differently.
For example:
Frontend
"true" → invalid
↓
API Gateway
"true" → accepted
↓
Backend
"true" → converted to true
↓
Business Logic
true → privileged operationFrontend
"true" → invalid
↓
API Gateway
"true" → accepted
↓
Backend
"true" → converted to true
↓
Business Logic
true → privileged operationThe security problem is the trust boundary between components.
OWASP's guidance emphasizes that input should be validated at a trusted service layer and that client-side validation should not be relied upon as a security control.
Type Confusion vs Business Logic
These concepts can overlap, but they are not identical.
Type Confusion
The application receives a value with an unexpected type.
Example:
Boolean expected
String receivedBoolean expected
String receivedBusiness Logic Flaw
The application performs an action that violates the intended business rule.
Example:
User should not be able to approve their own request.User should not be able to approve their own request.The Interesting Case
The two combine:
Unexpected type
↓
Different interpretation
↓
Business rule changes
↓
Security impactUnexpected type
↓
Different interpretation
↓
Business rule changes
↓
Security impactThat is when the finding becomes much more valuable.
OWASP describes business-logic vulnerabilities as problems where the implementation does not match what the business actually requires, and specifically recommends validating inputs for business meaning rather than only format.
Another Interesting Example: Quantity
Imagine an API expects:
{
"quantity": 2
}{
"quantity": 2
}The frontend only permits positive integers.
A tester can check how the server handles:
{
"quantity": "2"
}{
"quantity": "2"
}and:
{
"quantity": 2.5
}{
"quantity": 2.5
}and:
{
"quantity": []
}{
"quantity": []
}and:
{
"quantity": null
}{
"quantity": null
}The interesting question becomes:
Does the application strictly enforce:
quantity = integer
quantity >= 1
quantity <= allowed limitDoes the application strictly enforce:
quantity = integer
quantity >= 1
quantity <= allowed limitor does it simply attempt to convert whatever it receives?
OWASP recommends both syntactic and semantic validation, meaning an application should validate not just the data format but whether the value actually makes sense in the business context.
Another Example: Status
Consider:
{
"status": "approved"
}{
"status": "approved"
}The application expects one of:
pending
approved
rejectedpending
approved
rejectedA proper allowlist would reject unexpected values.
A weak implementation might only check:
status existsstatus existsinstead of:
status is a string
AND
status belongs to an allowed set
AND
current user is authorized to make that transitionstatus is a string
AND
status belongs to an allowed set
AND
current user is authorized to make that transitionThis is the difference between input validation and security-aware business validation.
What Pentesters Should Look For
When testing JSON APIs, don't just ask:
Can I inject something?
Also ask:
What type does the application expect?
What happens when the type changes?
Does the API normalize the value?
Does the gateway validate it?
Does the backend validate it again?
Does the database driver convert it?
Does the business logic interpret it differently?
Does the value influence authorization?
Does it influence ownership or tenant selection?
Does it change a workflow state?
Does it produce a controlled 4xx error or an unhandled 5xx?
These questions can uncover bugs that automated scanners may not fully understand.
A Simple Pentester Checklist
When testing JSON APIs:
[ ] Identify expected data types
[ ] Test string vs number
[ ] Test string vs boolean
[ ] Test integer vs decimal
[ ] Test null
[ ] Test empty string
[ ] Test empty array
[ ] Test object
[ ] Test missing parameter
[ ] Test duplicate parameters where applicable
[ ] Compare HTTP responses
[ ] Compare application behavior
[ ] Check security-sensitive fields
[ ] Check authorization impact
[ ] Check business-logic impact
[ ] Check error handling
[ ] Confirm reproducibility
[ ] Avoid causing destructive changes[ ] Identify expected data types
[ ] Test string vs number
[ ] Test string vs boolean
[ ] Test integer vs decimal
[ ] Test null
[ ] Test empty string
[ ] Test empty array
[ ] Test object
[ ] Test missing parameter
[ ] Test duplicate parameters where applicable
[ ] Compare HTTP responses
[ ] Compare application behavior
[ ] Check security-sensitive fields
[ ] Check authorization impact
[ ] Check business-logic impact
[ ] Check error handling
[ ] Confirm reproducibility
[ ] Avoid causing destructive changesHow Developers Can Fix It
The solution is not simply:
"Add more validation."
The validation needs to be strict, consistent and meaningful.
A secure API should define an explicit schema.
For example:
enabled:
type: boolean
required: trueenabled:
type: boolean
required: trueAnd reject:
{
"enabled": "true"
}
{
"enabled": 1
}
{
"enabled": []
}{
"enabled": "true"
}
{
"enabled": 1
}
{
"enabled": []
}when those types are not part of the API contract.
OWASP recommends strong types, rejection of unexpected content, appropriate schemas/validation libraries, and validation of both syntax and business meaning.
A particularly useful design principle is to parse external input into a canonical internal type before business logic operates on it, rather than repeatedly interpreting loosely typed raw input. OWASP's FIASSE guidance describes this as treating external input as untrusted until it has been parsed into a canonical internal type.
The interesting part of API security isn't always the complicated payload.
Sometimes it is one tiny difference:
truetrueversus:
"true""true"or:
11or:
[][]All can be valid JSON.
But they are not the same type.
And if different layers of an application interpret them differently, that gap can become a security problem.
The lesson for pentesters is simple:
Don't test only what the UI allows you to send. Test what the API is actually willing to accept.
And the lesson for developers is even simpler:
Valid JSON does not mean valid application input.
Strict type validation, semantic validation and server-side enforcement are what turn an API contract into an actual security boundary.
The next time you capture a JSON request in Burp Suite, don't immediately reach for a famous payload.
Look at the data type first.
Ask yourself:
"What happens if I change the type, but keep the value almost the same?"
Sometimes the smallest change tells you the most interesting story.
All examples in this article are intended for authorized security testing and intentionally controlled environments.
API security API penetration testing API security testing JSON type confusion type confusion vulnerability API validation bypass server side validation input validation bypass API input validation JSON validation API vulnerabilities REST API security REST API penetration testing Burp Suite API testing Burp Suite penetration testing API pentesting web application penetration testing business logic vulnerability business logic flaws API parameter tampering
Cybersecurity API Security Penetration Testing Ethical Hacking Web Security
#CyberSecurity #APISecurity #APIPentesting #PenetrationTesting #EthicalHacking #WebSecurity #BurpSuite #BugBounty #AppSec #InformationSecurity #SecurityTesting #API #RESTAPI #CyberSecurityResearch #VAPT #WebApplicationSecurity #BugBountyHunter #Pentesting