Skip to main content
Information disclosure vulnerabilities don’t directly compromise your application, but they give attackers the reconnaissance data they need to plan targeted attacks. An exposed .env file, a stack trace in a 500 page, or a Server: Apache/2.4.51 header can be the starting point for a critical exploit.

exposed-sensitive-file

Critical

What it is

Sensitive files — such as .env, config.json, backup.sql, .git/config, or phpinfo.php — are publicly accessible via direct URL, or directory listing is enabled on the server, exposing the full list of files.

Why it matters

.env files often contain database credentials, API keys, and encryption secrets. A single exposed .env file gives an attacker everything needed to compromise your infrastructure. Directory listings expose the full application structure, making further attacks trivial.

How QAOS detects it

The agent probes a set of common sensitive file paths on every target:
/.env
/backup.sql
/.git/config
/phpinfo.php
/config.json
/credentials.json
/wp-config.php
/.DS_Store
It also checks whether directory listing is enabled by requesting directory URLs directly.

How to fix

Configure your web server to deny access to sensitive files:
# Nginx — deny access to dot files and sensitive paths
location ~ /\. {
    deny all;
}
location ~* \.(env|sql|bak|config)$ {
    deny all;
}
Disable directory listing:
autoindex off;
Use .gitignore and .dockerignore to ensure .env and other secrets are never placed in public directories.

sensitive-data-logged

High

What it is

The browser console contains log entries with sensitive information: passwords, authentication tokens, JWT tokens, API keys, or personally identifiable information (PII).

Why it matters

Browser console logs are visible to any user with DevTools open. In shared environments or when a user shares a screenshot, this data is exposed. Console logs also often flow into log aggregation systems, creating a persistent record of sensitive data.

How QAOS detects it

The agent captures console log entries during normal page interaction and scans them for patterns indicating sensitive data: password strings, token patterns, credit card numbers, SSN patterns, or full user objects containing PII.

Examples

console.log('User logged in:', { email: 'user@example.com', password: 'hunter2' })
console.log('Auth token:', authToken)
console.log('Response:', { creditCard: '4111-1111-1111-1111' })

How to fix

Audit all console.log calls before production deployment. Use a logging library that supports log levels and automatically strips or redacts sensitive fields. Never log password values, full tokens, or complete user objects containing PII.
// Use structured logging with field redaction
logger.info('User logged in', { userId: user.id, email: user.email })
// NOT: logger.info('User logged in', user) — may include password hash, tokens, etc.

server-info-leakage

Medium

What it is

HTTP response headers disclose the server software name and exact version number, giving attackers a targeted list of known CVEs to exploit.

Why it matters

An attacker who knows you’re running Apache/2.4.51 (Ubuntu) can immediately look up all known vulnerabilities for that version and attempt targeted exploits. Version information is free reconnaissance.

How QAOS detects it

The agent checks HTTP response headers for Server and X-Powered-By values that include version numbers or framework names.

Examples

Server: Apache/2.4.51 (Ubuntu)     ← exact version disclosed
X-Powered-By: PHP/7.4.3            ← PHP version
X-Powered-By: Express              ← backend framework
X-Powered-By: ASP.NET              ← technology stack

How to fix

Remove or genericize server identification headers:
# Nginx
server_tokens off;
more_clear_headers Server;
# Apache
ServerTokens Prod
ServerSignature Off
// Express.js
app.disable('x-powered-by')

detailed-error-message

Medium

What it is

The browser console contains stack traces, file system paths, database error messages, or internal IP addresses that reveal the application’s internal structure.

Why it matters

Stack traces reveal file paths and line numbers, letting attackers map the codebase. Database errors like SQLSTATE[42S02]: Table 'users' not found expose schema details. Internal IP addresses reveal network topology.

How QAOS detects it

The agent captures all console log entries and scans them for stack trace patterns, database error strings, file system paths, and internal network addresses.

Examples

at /var/www/app/routes/user.js:42:15
SQLSTATE[42S02]: Table 'users.sessions' doesn't exist
Traceback (most recent call last): File "/app/api/views.py", line 128
Connection refused: 192.168.1.5:5432

How to fix

Set up a proper error handling middleware that logs detailed errors server-side only, while sending generic error messages to the client. Configure your logging framework to write to files, not to browser-visible outputs:
// Express.js error handler
app.use((err, req, res, next) => {
  logger.error(err)  // detailed log server-side
  res.status(500).json({ error: 'An unexpected error occurred' })  // generic client response
})

detailed-error-page

Medium

What it is

Error pages (404, 500, etc.) display stack traces, file paths, database error messages, or internal IP addresses instead of a generic error message.

Why it matters

Error pages are often the highest-information-density pages in an application. A verbose 500 error page can reveal the entire application stack, database schema, and internal network layout in a single response.

How QAOS detects it

The agent deliberately requests non-existent pages and triggers server errors to probe error page verbosity, checking the response for stack traces and internal details.

How to fix

Configure custom error pages that display only a user-friendly message with no internal details. In development, verbose errors are useful — but ensure DEBUG=False (or equivalent) in production:
# Django
DEBUG = False  # Never True in production

# FastAPI — use exception handlers
@app.exception_handler(Exception)
async def generic_exception_handler(request, exc):
    logger.exception(exc)
    return JSONResponse(status_code=500, content={"detail": "Internal server error"})

local-log-storage

Medium

What it is

Client-side JavaScript writes log entries to localStorage or sessionStorage, persisting debug data in the browser across sessions.

Why it matters

localStorage is accessible to any JavaScript running on the same origin (including injected scripts from XSS) and persists indefinitely. Sensitive debug data stored there can be read by attackers long after the original session.

How QAOS detects it

The agent scans JavaScript source for calls to localStorage.setItem or sessionStorage.setItem with log-related patterns.

How to fix

Remove localStorage-based logging from production builds. If you need client-side error reporting, use a proper service (Sentry, Datadog) that transmits logs over HTTPS rather than storing them locally.

log-event-exposure

Low

What it is

The application emits log events to the browser console in production, exposing implementation details to any user who opens DevTools.

Why it matters

While less critical than stack traces, debug console output reveals API call patterns, internal state, feature flags, and application behavior that aids attackers in understanding your system.

How QAOS detects it

The agent captures all console output during normal page interaction and checks for non-error console statements that appear to be debug-level logging.

How to fix

Use a logging library that respects log levels and disables debug output in production:
// Use a conditional based on environment
if (process.env.NODE_ENV === 'development') {
  console.log('[Debug]', data)
}

// Or use a logger with level filtering
const logger = createLogger({ level: process.env.LOG_LEVEL || 'warn' })