Skip to content

Error Bodies That Repeat Your Input Back

Adityo Guni Waluyo

API error messages that echo requester input are a cheap reconnaissance channel. The fix: specific code, static detail, regression tests.

TL;DR

KotaPortal's admin API was reflecting user input back in error messages across five spots in two services, confirming injection viability per OWASP guidance. The fix keeps specific error codes but makes human-readable details fully static, never echoing request data. Each endpoint gets a regression test that sends a random probe and fails if the probe appears in the response.

During a routine security review of the KotaPortal admin API, a write request falling outside the authorized access scope was rejected with a standard `FORBIDDEN` status. However, the response body carried the exact `bidang` value the requester had typed. An automated probe script later confirmed this behavior, receiving its own randomized probe value quoted verbatim within the error detail.

What the Investigation Found

The investigation identified five distinct spots across two services where request data was reflected. Three separate `mapError` chains were interpolating user input directly into validation messages, such as `invalid bidang: `, and authorization failures, like `this data belongs to bidang `. According to the OWASP Error Handling Cheat Sheet, issues at the error handling level can reveal information about the target and identify injection points [3]. A quoted-back value confirms three specific conditions: the field successfully reaches internal validation, the internal vocabulary of valid values is exposed, and special characters survive intact into the response. This creates a cheap, reliable injection test channel.

The Fix Pattern and the Boundary

The resolution requires keeping the machine-readable error code specific while making the human-readable detail entirely static. Messages must read `invalid bidang` without appending the value, or `this data belongs to another bidang`. Standard codes like `FORBIDDEN`, `INVALID_INPUT`, and `CONFLICT` remain intact. Client-side field validation can still inform users that their input is incorrect before submission. The API must never repeat the input back, primarily because the API serves diverse clients that may not be the benign, controlled form in the official frontend.

Regression Tests as the Proof

To guarantee the fix holds, each corrected endpoint receives a dedicated regression test. The checkable artifact is straightforward: send a unique, randomized probe payload, expect the standard error code, and grep the response body for the probe string. The test passes only on zero hits. Enforcing a code-level convention where error details must be static strings or table-driven lookups, never format strings constructed over request data, is significantly cheaper than manually reviewing every error message before each release. The OWASP warning exists precisely to justify this strict convention.

Sources

Related articles