Skip to content

VNX-213: Exposure of Sensitive Information Due to Incompatible Policies

Detects health, status and debug endpoints that return the whole process environment or application configuration (process.env, os.environ, app.config, os.Environ(), System.getenv()), publishing every secret an operator put there.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-213
Severity Medium
SARIF level warning
Kind sast
Languages Go, Java, JavaScript / TypeScript, Python
CWE CWE-213
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C
Tags policy exposure environment configuration cwe-213
Source internal/sast/rules/vnx-213.rego

Overview

VNX-213 maps to CWE-213: Exposure of Sensitive Information Due to Incompatible Policies. The weakness is a conflict between two policies: the developer’s (“this endpoint shows runtime facts”) and the operator’s (“secrets go in environment variables and config”). No line of code shows a policy, so the rule reports the most concrete place the conflict appears: an endpoint that returns the whole environment or configuration, which is where operators put database passwords, API keys and signing secrets.

Language Reported
JavaScript, TypeScript process.env passed whole (alone, in an object, spread, or JSON.stringify(process.env)) to res.send/json/end/write/render, ctx.body or reply.send, directly or through a variable
Python dict(os.environ), os.environ.copy()/.items(), app.config (whole or .items()), settings.__dict__, vars(settings) inside jsonify, JsonResponse, HttpResponse, make_response, Response, render_template
Go os.Environ() encoded or written to the http.ResponseWriter or a gin context, including a range os.Environ() loop that writes each entry
Java System.getenv() / System.getProperties() (no argument) returned from a controller or servlet, or put in ResponseEntity, a body, a model attribute or the response writer

What Gets Flagged

app.get('/healthz', (req, res) => {
  res.json({ status: 'ok', env: process.env });   // FLAGGED
});
return jsonify(status="ok", environment=dict(os.environ))   # FLAGGED

@router.get("/debug/env")
def env_dump():
    return dict(os.environ)                                  # FLAGGED
json.NewEncoder(w).Encode(os.Environ())   // FLAGGED

What Is Not Flagged

  • Single variables: process.env.APP_VERSION, os.environ.get("X"), System.getenv("X").
  • Object.keys(process.env) (names only), and environments copied for a subprocess (env=os.environ.copy(), cmd.Env = os.Environ()).
  • Spring Actuator exposure (VNX-JAVA-002) and phpinfo() (VNX-PHP-008), which have their own rules.
  • An environment returned from a function no route exposes (a settings loader), or filtered before it is written (if strings.HasPrefix(kv, "PUBLIC_")).
  • Comments, string literals and test code.

Remediation

Return an explicit allow-list of fields.

res.json({ status: 'ok', version: process.env.APP_VERSION });

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-213
// nosec vnx-213

Or record an ignore rule: vulnetix ignore add --rule vnx-213 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-213.rego, cli/internal/sast/docs/vnx-213.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.