Dear json-server Maintainers,
We are a team of security researchers from Beijing University of Posts and Telecommunications (BUPT). We would like to responsibly disclose a host binding issue affecting typicode/json-server.
The CLI accepts and parses the --host option, but the parsed host value is not passed to the underlying HTTP listener. In our verification through the project's official CLI startup path, specifying --host 127.0.0.1 resulted in the runtime attempting to listen on 0.0.0.0 instead of the requested loopback address.
If the resulting listener is reachable from an untrusted network, the normal unauthenticated REST API may allow unauthorized clients to read or modify the configured JSON resources.
1. Affected Deployments
We verified the issue in json-server version 1.0.0-beta.15 at commit 89a34a4. Other versions containing the same CLI listening logic should be reviewed separately.
Deployments may be affected when users specify a loopback host such as --host 127.0.0.1, or rely on the default localhost, but the runtime is permitted to listen on and be reached through a non-loopback interface.
If the service becomes reachable from another host, its normal unauthenticated CRUD functionality may allow that client to read or modify resources backed by the configured JSON file. The practical impact therefore depends on network reachability and the sensitivity of the stored data.
2. Vulnerability Details
The json-server CLI defines a host option, defaults it to the HOST environment variable or localhost, and correctly stores the parsed value in the CLI configuration.
However, when starting the application, the CLI invokes the listener using the following form:
app.listen(port, () => {
...
});
The installed @tinyhttp/app listening interface expects the host as an additional argument. Because the parsed host is omitted from the call, the underlying listener receives no explicit host value.
In our verified reproduction, starting the official CLI with --host 127.0.0.1 caused the runtime to attempt to listen on 0.0.0.0:3137.
The validation environment prohibited listening on all network interfaces. Importantly, however, the attempted address shown by the runtime was 0.0.0.0:3137, even though the CLI had explicitly been given 127.0.0.1.
This demonstrates that the parsed host value is not controlling the actual listener address.
We separately verified the impact using the real json-server route stack. A POST /posts request returned HTTP 201, and the submitted data was persisted into the backing audit-db.json file.
The root cause is therefore a discrepancy between the security-relevant host configuration accepted by the CLI and the arguments actually supplied to the underlying network listener. A user may believe that the service is restricted to the local machine while the runtime attempts to bind more broadly.
Proof of Concept
Start the official CLI while explicitly requesting the loopback address:
node --experimental-strip-types src/bin.ts audit-db.json --port 3137 --host 127.0.0.1
In our restricted validation environment, the observed runtime result was:
Error: listen EPERM: operation not permitted 0.0.0.0:3137
On a normal host where listening is permitted, the actual socket address can additionally be checked using:
Once the service is reachable, its normal REST route can accept a write request such as:
curl -i \
-X POST http://127.0.0.1:3137/posts \
-H 'Content-Type: application/json' \
--data '{"title":"jsv-001-poc"}'
The verified application route stack returned HTTP 201, and the new object was written to the backing JSON database.
Reproduction Steps
① Obtain json-server version 1.0.0-beta.15 at commit 89a34a4, install its dependencies, and prepare a JSON database file.
② Start the official CLI with --host 127.0.0.1 and a test port such as 3137.
③ Inspect the runtime listener address using the startup error, ss, lsof, or an equivalent socket inspection mechanism.
④ Compare the configured host with the actual listener address.
⑤ If the service can start and is reachable in the test environment, access a REST resource and perform a normal write request.
⑥ Verify that the write operation is persisted to the backing JSON file.
Observed Result: the CLI accepts --host 127.0.0.1, but the runtime attempts to bind 0.0.0.0. Separately, the real REST application path accepts unauthenticated writes and persists them to the backing JSON file.
This confirms the host-binding defect. The security impact arises when the resulting listener is reachable from an untrusted network.
3. Suggested Patch
The parsed host value should be explicitly passed to the underlying listener so that the configured network binding is actually enforced.
For the currently verified listener signature, the startup call should follow the equivalent of:
app.listen(port, () => {
...
}, host);
Regression tests should verify at least --host 127.0.0.1, HOST=127.0.0.1, the default localhost behavior, and an explicit public binding such as --host 0.0.0.0.
4. Disclosure Timetable
BUPT follows a process of responsible disclosure. Following disclosure of vulnerabilities, we adhere to a non-disclosure period. During this time, we do not publicly disclose the vulnerability, although we may continue to research it and assist with verification.
Initial report sent: Aug. 11, 2026.
We would appreciate an email acknowledging receipt of this disclosure. We are also available to provide additional reproduction details, validation logs, or assistance in testing a proposed patch.
Best regards,
Shuya Li
Graduate Student
School of Cyberspace Security
Beijing University of Posts and Telecommunications
Email: lishuyasusu@bupt.edu.cn
Zifeng Kang
Associate Researcher
School of Cyberspace Security
Beijing University of Posts and Telecommunications
Email: zifengkang@bupt.edu.cn
Yanwei Sun
Lecturer
School of Cyberspace Security
Beijing University of Posts and Telecommunications
Email: sunyw@bupt.edu.cn
Xinran Liu
Researcher
Key Laboratory of Trustworthy Distributed Computing and Service (BUPT), Ministry of Education.
Dear json-server Maintainers,
We are a team of security researchers from Beijing University of Posts and Telecommunications (BUPT). We would like to responsibly disclose a host binding issue affecting
typicode/json-server.The CLI accepts and parses the
--hostoption, but the parsed host value is not passed to the underlying HTTP listener. In our verification through the project's official CLI startup path, specifying--host 127.0.0.1resulted in the runtime attempting to listen on0.0.0.0instead of the requested loopback address.If the resulting listener is reachable from an untrusted network, the normal unauthenticated REST API may allow unauthorized clients to read or modify the configured JSON resources.
1. Affected Deployments
We verified the issue in
json-serverversion1.0.0-beta.15at commit89a34a4. Other versions containing the same CLI listening logic should be reviewed separately.Deployments may be affected when users specify a loopback host such as
--host 127.0.0.1, or rely on the defaultlocalhost, but the runtime is permitted to listen on and be reached through a non-loopback interface.If the service becomes reachable from another host, its normal unauthenticated CRUD functionality may allow that client to read or modify resources backed by the configured JSON file. The practical impact therefore depends on network reachability and the sensitivity of the stored data.
2. Vulnerability Details
The
json-serverCLI defines ahostoption, defaults it to theHOSTenvironment variable orlocalhost, and correctly stores the parsed value in the CLI configuration.However, when starting the application, the CLI invokes the listener using the following form:
The installed
@tinyhttp/applistening interface expects the host as an additional argument. Because the parsed host is omitted from the call, the underlying listener receives no explicit host value.In our verified reproduction, starting the official CLI with
--host 127.0.0.1caused the runtime to attempt to listen on0.0.0.0:3137.The validation environment prohibited listening on all network interfaces. Importantly, however, the attempted address shown by the runtime was
0.0.0.0:3137, even though the CLI had explicitly been given127.0.0.1.This demonstrates that the parsed
hostvalue is not controlling the actual listener address.We separately verified the impact using the real
json-serverroute stack. APOST /postsrequest returned HTTP201, and the submitted data was persisted into the backingaudit-db.jsonfile.The root cause is therefore a discrepancy between the security-relevant host configuration accepted by the CLI and the arguments actually supplied to the underlying network listener. A user may believe that the service is restricted to the local machine while the runtime attempts to bind more broadly.
Proof of Concept
Start the official CLI while explicitly requesting the loopback address:
In our restricted validation environment, the observed runtime result was:
On a normal host where listening is permitted, the actual socket address can additionally be checked using:
Once the service is reachable, its normal REST route can accept a write request such as:
The verified application route stack returned HTTP
201, and the new object was written to the backing JSON database.Reproduction Steps
① Obtain
json-serverversion1.0.0-beta.15at commit89a34a4, install its dependencies, and prepare a JSON database file.② Start the official CLI with
--host 127.0.0.1and a test port such as3137.③ Inspect the runtime listener address using the startup error,
ss,lsof, or an equivalent socket inspection mechanism.④ Compare the configured host with the actual listener address.
⑤ If the service can start and is reachable in the test environment, access a REST resource and perform a normal write request.
⑥ Verify that the write operation is persisted to the backing JSON file.
Observed Result: the CLI accepts
--host 127.0.0.1, but the runtime attempts to bind0.0.0.0. Separately, the real REST application path accepts unauthenticated writes and persists them to the backing JSON file.This confirms the host-binding defect. The security impact arises when the resulting listener is reachable from an untrusted network.
3. Suggested Patch
The parsed host value should be explicitly passed to the underlying listener so that the configured network binding is actually enforced.
For the currently verified listener signature, the startup call should follow the equivalent of:
Regression tests should verify at least
--host 127.0.0.1,HOST=127.0.0.1, the defaultlocalhostbehavior, and an explicit public binding such as--host 0.0.0.0.4. Disclosure Timetable
BUPT follows a process of responsible disclosure. Following disclosure of vulnerabilities, we adhere to a non-disclosure period. During this time, we do not publicly disclose the vulnerability, although we may continue to research it and assist with verification.
Initial report sent: Aug. 11, 2026.
We would appreciate an email acknowledging receipt of this disclosure. We are also available to provide additional reproduction details, validation logs, or assistance in testing a proposed patch.
Best regards,
Shuya Li
Graduate Student
School of Cyberspace Security
Beijing University of Posts and Telecommunications
Email: lishuyasusu@bupt.edu.cn
Zifeng Kang
Associate Researcher
School of Cyberspace Security
Beijing University of Posts and Telecommunications
Email: zifengkang@bupt.edu.cn
Yanwei Sun
Lecturer
School of Cyberspace Security
Beijing University of Posts and Telecommunications
Email: sunyw@bupt.edu.cn
Xinran Liu
Researcher
Key Laboratory of Trustworthy Distributed Computing and Service (BUPT), Ministry of Education.