Observer

php-demo

Production Health Report · generated 2026-10-31 04:23:56 · Scanned 8 source file(s) in 196 ms
examples/php-demo

Executive Summary

Analyzed php-demo (PHP, CodeIgniter 3, MySQL). Collected 20 finding(s): 1 critical, 12 high, 2 medium, 5 low, spanning static analysis, runtime errors, and logs. The most pressing items are listed below; explanations restate the detected findings without adding unverified conclusions.

Guidance mode: local (heuristic, no LLM) — explanations are grounded in the detected findings.

Security severity grade
E
Language
PHP
Findings
22
Est. fix effort
~8h 5m
Critical 1High 12Medium 2Low 7
10F
Security
57F
Code Health · All Engines
57F
Observer Built-in

How scoring works: severity, CWE and OWASP tags follow industry standards (CVSS-aligned). The Security rating (A–E) is standards-style — it reflects the single most severe security issue present (E = Critical … A = none), the same model tools like SonarQube use. The 0–100 scores use scoring model v2 over first-party files. Code Health includes all enabled engines; Observer Built-in isolates native rules. Optional engines contributed 0 health finding(s).

Observer severity grade: A = no security finding; B = Low; C = Medium; D = High; E = Critical. The grade reflects the worst detected security severity. Scores and standards mappings are heuristic summaries, not certification or proof of compliance.

Technology Stack

Frameworks

NameVersionConfidenceEvidence
CodeIgniter 3 3.1.11 High composer.json requires codeigniter/framework 3.1.11

Databases

NameVersionConfidenceEvidence
MySQL — High dbdriver mysqli in database.php

Infrastructure

None detected.

Fix These First

The highest-severity issues, grouped and ranked. Start here — the full list of locations and the fix for each is in All Findings, just below.

Critical Hardcoded Stripe live secret key Security · 1×
High SQL built with string concatenation Database · 3×
High Hardcoded credential Security · 2×
High display_errors enabled Configuration · 1×
High Empty catch block Error Handling · 1×
High Possible reflected XSS Security · 1×
Show all Critical & High ↓

Findings: 22 Occurrences, 13 Issue Types

22 finding occurrences across 8 scanned file(s). They are consolidated into 13 unique issue types below; the count on each row shows its occurrences. Expand a row to see every location (clickable — opens the public demo source on GitHub) and the possible remediation. Findings and guidance are rule-based — confirm before acting.

Critical Hardcoded Stripe live secret key Security 1×
A live credential is committed in source control. Anyone with repo access (or a leak) can use it.
Fix: Revoke and rotate the credential immediately; load secrets from environment variables or a secrets manager.
Suggested fix
Before: $apiKey = "sk_live_abc123";
After:  $apiKey = getenv("STRIPE_API_KEY"); // load from env/secret store, rotate the leaked key
Where — 1 occurrence(s)
application/models/BookingModel.php:7 [redacted secret-like content]
High SQL built with string concatenation Database 3×
Interpolating variables directly into a SQL string allows SQL injection if any value is attacker-controlled.
Fix: Use parameterized queries / query bindings (prepared statements) instead of concatenation.
Suggested fix
Before: $db->query("SELECT * FROM users WHERE id = " . $id);
After:  $db->query("SELECT * FROM users WHERE id = ?", [$id]); // parameterized
Where — 3 occurrence(s)
application/models/BookingModel.php:12 $sql = "INSERT INTO bookings (user_id, booking_date) VALUES ('" . $userId . "', '" . $date . "')";
application/models/BookingModel.php:20 $sql = "SELECT * FROM bookings WHERE booking_date = '" . $date . "'";
application/models/BookingModel.php:26 $sql = "DELETE FROM bookings WHERE id = " . $id;
High Hardcoded credential Security 2×
A password/secret/API key is hardcoded as a literal value, exposing it to anyone reading the code.
Fix: Move the value to an environment variable or secrets manager and reference it at runtime.
Suggested fix
Before: $apiKey = "sk_live_abc123";
After:  $apiKey = getenv("STRIPE_API_KEY"); // load from env/secret store, rotate the leaked key
Where — 2 occurrence(s)
application/config/config.php:13 [redacted secret-like content]
application/config/database.php:12 [redacted secret-like content]
High display_errors enabled Configuration 1×
Displaying errors in production leaks stack traces, file paths, and query details to end users and attackers.
Fix: Turn display_errors off in production; log errors to a file instead.
Suggested fix
Disable display_errors / debug in production; log errors to a file instead.
Where — 1 occurrence(s)
application/config/config.php:7 $config['display_errors'] = 1;
High Empty catch block Error Handling 1×
A catch block that does nothing swallows the exception, hiding production failures and making them impossible to diagnose.
Fix: Log the exception (with context) and handle or rethrow it; never silently discard errors.
Suggested fix
Log the exception (with context) and handle or rethrow it — never discard it silently.
Where — 1 occurrence(s)
High Possible reflected XSS Security 1×
Request input is echoed to the page without escaping, allowing reflected cross-site scripting.
Fix: Escape output with htmlspecialchars() (or template auto-escaping) before rendering user input.
Suggested fix
Before: echo $_GET['name'];
After:  echo htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');
Where — 1 occurrence(s)
High Unvalidated input in file/include operation (path traversal / LFI) Security 1×
A file or include operation uses unvalidated request input, letting attackers read or execute arbitrary files.
Fix: Validate against an allow-list of paths; never pass request input directly to file/include functions.
Suggested fix
Before: include $_GET['page'];
After:  $allowed = ['home'=>'home.php']; include $allowed[$_GET['page']] ?? '404.php';
Where — 1 occurrence(s)
High Insecure deserialization of request input Security 1×
unserialize() on attacker-controlled data enables object injection and can lead to remote code execution.
Fix: Avoid unserialize() on user input; use json_decode(), or pass ['allowed_classes' => false].
Suggested fix
Before: $o = unserialize($_POST['data']);
After:  $o = json_decode($_POST['data'], true); // or unserialize($x, ['allowed_classes' => false])
Where — 1 occurrence(s)
application/controllers/VulnController.php:15 $data = unserialize($_POST['payload']);
High Possible SSRF (server-side request forgery) Security 1×
A server-side HTTP request is built from unvalidated request input, letting attackers reach internal or arbitrary hosts.
Fix: Allow-list destinations and validate URLs; never build request targets directly from user input.
Suggested fix
Validate the URL against an allow-list of hosts/schemes before making the request; block private IP ranges.
Where — 1 occurrence(s)
application/controllers/VulnController.php:18 $ch = curl_init($_GET['url']);
High TLS/SSL certificate verification disabled Security 1×
Disabling certificate verification exposes outbound HTTPS connections to man-in-the-middle attacks.
Fix: Enable verification: CURLOPT_SSL_VERIFYPEER=true / Guzzle 'verify'=>true.
Suggested fix
Before: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
After:  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
Where — 1 occurrence(s)
application/controllers/VulnController.php:21 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
Medium Database debug mode enabled Configuration 1×
db_debug = TRUE prints raw SQL errors (including queries) to the response on failure.
Fix: Disable db_debug in production and rely on application logging.
Suggested fix
Disable display_errors / debug in production; log errors to a file instead.
Where — 1 occurrence(s)
Medium SELECT * query Performance 1×
CVSS ~5.0
Selecting all columns over-fetches data, increases I/O, and breaks when the schema changes.
Fix: Select only the columns you need.
Suggested fix
Select only needed columns / add appropriate indexes / avoid leading-wildcard LIKE.
Where — 1 occurrence(s)
application/models/BookingModel.php:20 $sql = "SELECT * FROM bookings WHERE booking_date = '" . $date . "'";
Low Unvalidated request input Security 7×
Reading $_GET/$_POST/$_REQUEST directly uses raw, unvalidated user input, which often flows into queries or output.
Fix: Validate and sanitize input (e.g. filter_input, the framework's input/validation layer) before use.
Suggested fix
Validate/sanitize input (filter_input, the framework's validation layer) before use.
Where — 7 occurrence(s)
application/controllers/VulnController.php:15 $data = unserialize($_POST['payload']);
application/controllers/VulnController.php:18 $ch = curl_init($_GET['url']);

Remediation Guidance

Critical Hardcoded Stripe live secret key Fix complexity: Low Effort: ~15 min
ProblemHardcoded Stripe live secret key (application/models/BookingModel.php:7)
Root causeA live credential is committed in source control. Anyone with repo access (or a leak) can use it.
ImpactCritical — can cause outages, data loss, or a security breach if unaddressed.
ExploitabilityAnyone with source/repo access (or via a leak) can use the credential to access the linked service or data.
Possible fixRevoke and rotate the credential immediately; load secrets from environment variables or a secrets manager.
Example
Before: $apiKey = "sk_live_abc123";
After:  $apiKey = getenv("STRIPE_API_KEY"); // load from env/secret store, rotate the leaked key
High display_errors enabled Fix complexity: Low Effort: ~10 min
Problemdisplay_errors enabled (application/config/config.php:7)
Root causeDisplaying errors in production leaks stack traces, file paths, and query details to end users and attackers.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityVerbose errors leak stack traces, queries, and paths that help an attacker map the system.
Possible fixTurn display_errors off in production; log errors to a file instead.
Example
Disable display_errors / debug in production; log errors to a file instead.
High Hardcoded credential Fix complexity: Low Effort: ~15 min
ProblemHardcoded credential (application/config/config.php:13)
Root causeA password/secret/API key is hardcoded as a literal value, exposing it to anyone reading the code.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityAnyone with source/repo access (or via a leak) can use the credential to access the linked service or data.
Possible fixMove the value to an environment variable or secrets manager and reference it at runtime.
Example
Before: $apiKey = "sk_live_abc123";
After:  $apiKey = getenv("STRIPE_API_KEY"); // load from env/secret store, rotate the leaked key
High Hardcoded credential Fix complexity: Low Effort: ~15 min
ProblemHardcoded credential (application/config/database.php:12)
Root causeA password/secret/API key is hardcoded as a literal value, exposing it to anyone reading the code.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityAnyone with source/repo access (or via a leak) can use the credential to access the linked service or data.
Possible fixMove the value to an environment variable or secrets manager and reference it at runtime.
Example
Before: $apiKey = "sk_live_abc123";
After:  $apiKey = getenv("STRIPE_API_KEY"); // load from env/secret store, rotate the leaked key
High Empty catch block Fix complexity: Low Effort: ~10 min
ProblemEmpty catch block (application/controllers/BookingController.php:23)
Root causeA catch block that does nothing swallows the exception, hiding production failures and making them impossible to diagnose.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityNot directly exploitable, but swallowed exceptions hide failures and security events from monitoring.
Possible fixLog the exception (with context) and handle or rethrow it; never silently discard errors.
Example
Log the exception (with context) and handle or rethrow it — never discard it silently.
High Possible reflected XSS Fix complexity: Low Effort: ~15 min
ProblemPossible reflected XSS (application/controllers/VulnController.php:9)
Root causeRequest input is echoed to the page without escaping, allowing reflected cross-site scripting.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityAn attacker supplies a value containing <script>…</script>; it executes in another user's browser (session theft, defacement).
Possible fixEscape output with htmlspecialchars() (or template auto-escaping) before rendering user input.
Example
Before: echo $_GET['name'];
After:  echo htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');
High Unvalidated input in file/include operation (path traversal / LFI) Fix complexity: Medium Effort: ~30 min
ProblemUnvalidated input in file/include operation (path traversal / LFI) (application/controllers/VulnController.php:12)
Root causeA file or include operation uses unvalidated request input, letting attackers read or execute arbitrary files.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityInput like ../../etc/passwd lets an attacker read or include files outside the intended directory.
Possible fixValidate against an allow-list of paths; never pass request input directly to file/include functions.
Example
Before: include $_GET['page'];
After:  $allowed = ['home'=>'home.php']; include $allowed[$_GET['page']] ?? '404.php';
High Insecure deserialization of request input Fix complexity: Medium Effort: ~1 hour
ProblemInsecure deserialization of request input (application/controllers/VulnController.php:15)
Root causeunserialize() on attacker-controlled data enables object injection and can lead to remote code execution.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityCrafted serialized input triggers object injection, which can escalate to remote code execution.
Possible fixAvoid unserialize() on user input; use json_decode(), or pass ['allowed_classes' => false].
Example
Before: $o = unserialize($_POST['data']);
After:  $o = json_decode($_POST['data'], true); // or unserialize($x, ['allowed_classes' => false])
High Possible SSRF (server-side request forgery) Fix complexity: Medium Effort: ~1 hour
ProblemPossible SSRF (server-side request forgery) (application/controllers/VulnController.php:18)
Root causeA server-side HTTP request is built from unvalidated request input, letting attackers reach internal or arbitrary hosts.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityAn attacker supplies an internal URL (e.g. http://169.254.169.254/) so the server fetches internal resources/metadata.
Possible fixAllow-list destinations and validate URLs; never build request targets directly from user input.
Example
Validate the URL against an allow-list of hosts/schemes before making the request; block private IP ranges.
High TLS/SSL certificate verification disabled Fix complexity: Low Effort: ~10 min
ProblemTLS/SSL certificate verification disabled (application/controllers/VulnController.php:21)
Root causeDisabling certificate verification exposes outbound HTTPS connections to man-in-the-middle attacks.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityWith verification off, a man-in-the-middle can present any certificate and intercept/modify the HTTPS traffic.
Possible fixEnable verification: CURLOPT_SSL_VERIFYPEER=true / Guzzle 'verify'=>true.
Example
Before: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
After:  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
High SQL built with string concatenation Fix complexity: Medium Effort: ~30 min per query
ProblemSQL built with string concatenation (application/models/BookingModel.php:12)
Root causeInterpolating variables directly into a SQL string allows SQL injection if any value is attacker-controlled.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityAn attacker submits crafted input (e.g. ' OR '1'='1) to read, modify, or delete database records.
Possible fixUse parameterized queries / query bindings (prepared statements) instead of concatenation.
Example
Before: $db->query("SELECT * FROM users WHERE id = " . $id);
After:  $db->query("SELECT * FROM users WHERE id = ?", [$id]); // parameterized
High SQL built with string concatenation Fix complexity: Medium Effort: ~30 min per query
ProblemSQL built with string concatenation (application/models/BookingModel.php:20)
Root causeInterpolating variables directly into a SQL string allows SQL injection if any value is attacker-controlled.
ImpactHigh — significant risk to stability, security, or correctness.
ExploitabilityAn attacker submits crafted input (e.g. ' OR '1'='1) to read, modify, or delete database records.
Possible fixUse parameterized queries / query bindings (prepared statements) instead of concatenation.
Example
Before: $db->query("SELECT * FROM users WHERE id = " . $id);
After:  $db->query("SELECT * FROM users WHERE id = ?", [$id]); // parameterized

Suggested Fix Priority

  1. [Critical] Hardcoded Stripe live secret key
  2. [High] display_errors enabled
  3. [High] Hardcoded credential
  4. [High] Hardcoded credential
  5. [High] Empty catch block

Compliance & Standards

Indicative mapping to support audits — not a certification. Findings are mapped from their CWE/OWASP tags.

OWASP Top 10 (2021) coverage

CategoryFindingsStatus
A01 Broken Access Control 1 Issues found
A02 Cryptographic Failures 0 No issues detected
A03 Injection 11 Issues found
A04 Insecure Design 0 Not assessed
A05 Security Misconfiguration 3 Issues found
A06 Vulnerable and Outdated Components 0 No issues detected
A07 Identification and Authentication Failures 3 Issues found
A08 Software and Data Integrity Failures 1 Issues found
A09 Security Logging and Monitoring Failures 1 Issues found
A10 Server-Side Request Forgery (SSRF) 1 Issues found

PCI-DSS & ISO/IEC 27001 mapping

AreaOWASPPCI-DSSISO 27001Status
Access control A01 Req 7 — Restrict access by need-to-know A.8.3 Information access restriction Action needed (1)
Cryptography A02 Req 3 & 4 — Protect stored & transmitted data A.8.24 Use of cryptography OK
Injection A03 Req 6.2.4 — Prevent injection flaws A.8.28 Secure coding Action needed (11)
Configuration A05 Req 2.2 — Secure system configuration A.8.9 Configuration management Action needed (3)
Dependencies A06 Req 6.3.3 — Patch known vulnerabilities A.8.8 Mgmt of technical vulnerabilities OK
Authentication A07 Req 8 — Identify & authenticate access A.5.17 Authentication information Action needed (3)
Data integrity A08 Req 6.5 — Change & integrity control A.8.28 Secure coding Action needed (1)
Logging A09 Req 10 — Log & monitor all access A.8.15 Logging Action needed (1)
SSRF A10 Req 6.2.4 — Secure coding practices A.8.28 Secure coding Action needed (1)

CWE breakdown

CWEFindings
CWE-207
CWE-7983
CWE-893
CWE-2092
CWE-221
CWE-2951
CWE-5021
CWE-7551
CWE-791
CWE-9181

Project Structure

CategoryCount
Config2
Controllers2
Services1
Models1
Observer Pro — deeper, framework-aware security

You're on the free edition. Pro's premium rule packs add framework-specific security rules — Laravel, CodeIgniter, WordPress, Symfony, Django, Rails, Spring & Express — layered on top of everything in this report.

Get Observer Pro → Launch offer: use code LAUNCH25 for 25% off (first 25 buyers).