371 Templates. 8 Seconds. AWS Credentials Sitting Wide Open.

Date: March 3, 2026
Tool: Nuclei v3.3.9 (ProjectDiscovery)
Category: Web Misconfiguration
Result: ✅ Pass — 5/6 classes
Scan time: 8 seconds
Methodology note: We built a deliberately misconfigured Flask web application on a controlled local server (never internet-accessible). Six vulnerability classes were embedded. SecurityClaw ran Nuclei v3.3.9 against it. The AWS keys and credentials in the output are canary values — structurally correct but intentionally fake. The one miss (phpinfo) is documented with the exact technical reason.

What We Tested

The target was a Flask application we built specifically for this demo — a realistic simulation of the kind of misconfigurations that accumulate in development environments and occasionally ship to production. Six vulnerability classes, deliberately embedded, running on localhost.

We ran SecurityClaw's nuclei-scan skill: 371 templates checked in sequence, covering the most common classes of web misconfiguration, credential exposure, and security header absence.

The six planted vulnerability classes:

  1. AWS credentials at /.aws/credentials — The access key and secret sitting at the default path, served over HTTP
  2. Laravel/CodeIgniter .env disclosure — Environment files at /.env, /.env.bak, /.env.backup, /.env.old
  3. Backup ZIP files — Archive files at common paths (/backup.zip, /www.zip, etc.)
  4. Git config exposed/.git/config accessible over HTTP
  5. Missing security headers — All 11 standard security headers absent
  6. PHPInfo exposure/phpinfo.php serving the full PHP configuration page

Scan time: 8 seconds. False positives: 0.

What It Found — The Full Output

Finding 1: AWS Credentials Exposed (CVSS 9.4 — HIGH)

The /.aws/credentials template extracted two AWS access key IDs directly from the response. This is the finding that ends conversations in security reviews.

GET /.aws/credentials HTTP/1.1 Host: localhost HTTP/1.1 200 OK Content-Type: text/plain [default] aws_access_key_id = AKIAIOSFODNN7EXAMPLE aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY region = eu-west-1

In a real system, this is game over. AWS credentials at full access provide account takeover, access to all attached S3 buckets, ability to spin up EC2 instances for cryptomining or lateral movement, and — depending on the IAM configuration — potential access to every other AWS service in the account. CVSS 9.4.

How does this happen in production? The most common path: a developer has ~/.aws/credentials configured locally for AWS CLI access. They deploy from a checkout without excluding the .aws/ directory. The credentials file ships with the application code.

Nuclei found this in 8 seconds by checking the most predictable location first. So would any attacker.

Finding 2 & 3: .env Disclosure (HIGH) — Two Templates, One File

The same /.env file triggered two different Nuclei templates: laravel-env (looking for APP_KEY=) and codeigniter-env (looking for DB_ variable patterns). This is worth explaining.

Nuclei templates use regex matchers. Different frameworks use different patterns in their environment files. By running both templates, Nuclei catches .env disclosures regardless of which PHP framework generated the file. The same endpoint appearing twice in the output isn't a bug — it's overlapping coverage catching the same misconfiguration via two different detection paths.

The four .env paths checked: /.env, /.env.bak, /.env.backup, /.env.old. All four were accessible. Each contained database connection strings and application secrets.

Finding 4: Backup ZIP Files (MEDIUM)

Nuclei's zip-backup-files template is a clusterbomb: it tries 1,305 payload combinations — common backup filenames combined with common archive extensions. It matched four paths:

backup.zip → 200 OK → contains config/database.yml (DB credentials) www.zip → 200 OK → contains config/database.yml html.zip → 200 OK → contains config/database.yml web.zip → 200 OK → contains config/database.yml

Each ZIP contained a database configuration file with credentials. This is the misconfiguration that happens when developers take a backup before a deployment, leave the archive in the web root "temporarily," and then forget it exists. The backup lives there for months. Sometimes years.

Finding 5: Git Config Exposed (MEDIUM)

/.git/config was accessible. The git config file contains remote URLs (including potentially credential-embedded HTTPS remote URLs), branch tracking configuration, and sometimes stored git credentials if the developer used the git credential helper. It's a lower-severity version of full .git/HEAD exposure — less useful for reconstructing the repository, more useful for identifying the remote repository URL and any embedded auth tokens.

Finding 6: 11 Missing Security Headers (INFO)

Every HTTP response from the Flask app was missing all 11 standard security headers. Nuclei documents each one individually:

missing-hsts: HSTS not set missing-csp: Content-Security-Policy not set missing-x-frame-options: X-Frame-Options not set missing-x-content-type: X-Content-Type-Options not set missing-permissions-policy: Permissions-Policy not set [...6 more]

These are classified INFO because they're enablers, not standalone vulnerabilities. Absent X-Frame-Options doesn't cause a breach directly — it makes clickjacking attacks viable. Absent CSP doesn't enable XSS — it removes a mitigation layer that would contain XSS impact. They matter in combination, especially on authenticated applications where the missing headers amplify the impact of other findings.

The Honest Miss: phpinfo Exposure

Nuclei did not detect the planted PHPInfo page at /phpinfo.php. Here's exactly why — and why it's actually instructive.

The phpinfo-files template uses a composite matcher: it looks for both the string "PHP Extension" AND "PHP Version" in the HTTP response. A real PHPInfo page contains both — they're the two most distinctive elements of a PHP configuration disclosure page.

Our mock PHPInfo page only returned "PHP Version". We didn't include the extension table that real PHPInfo pages generate. The template saw one match condition pass and the other fail, so it didn't trigger.

This is a demo environment quality issue, not a Nuclei failure. A real running PHPInfo page — the kind you encounter in production — would contain both strings and would trigger immediately. If we rerun this demo against a PHP server with real PHPInfo output, the detection rate is 6/6.

We're documenting this because it illustrates something real: false negatives in automated scanning can come from the scan target, not just the scan tool. An incomplete mock isn't the same as a real misconfiguration. Security testing against realistic targets gives realistic results.

Scorecard Impact — Demo Series Update

This campaign updates the SecurityClaw capability scorecard:

  • Total campaigns: 6 (was 5 before this demo)
  • Web Misconfiguration category: Nikto + Nuclei both pass — 5/5 and 5/6 respectively
  • Tools demonstrated: TruffleHog, Nikto, npm-audit, WPScan, Nuclei

The cumulative picture: across 6 campaigns, SecurityClaw has demonstrated detection across secrets (git history), web misconfigurations (active server), supply chain (dependencies), WordPress fingerprinting, and misconfiguration scanning. The partial results (TruffleHog's Stripe gap, WPScan vs WP Engine hardening) are documented alongside the passes.

Why These Misconfigurations Keep Appearing

The findings in this demo aren't exotic. AWS credentials at /.aws/credentials, .env files, backup archives in the web root — these appear in real-world bug bounty submissions at high rates. They're common because they share a root cause: the gap between how software is developed and how it's deployed.

Developers work locally with real credentials, real environment files, real git repos. Deployment processes that don't explicitly strip development artefacts ship everything. The developer never sees the deployed state — they assume CI/CD handles it. CI/CD assumes the developer cleaned up. The /.aws/credentials file ends up on a production web server.

Nuclei catches the resulting state in 8 seconds. The organisations that get caught by this class of finding aren't universally negligent — they're often well-resourced teams with mature CI/CD pipelines who had a gap between what they assumed was stripped during deployment and what was actually stripped.

The answer is automated scanning in the pipeline, not just on-demand security reviews. For practitioners building that pipeline: The Web Application Hacker's Handbook covers credential exposure and misconfiguration exploitation in depth — the attack techniques that tools like Nuclei are designed to detect. Black Hat Python (2nd Edition) covers building custom detection tooling when template coverage isn't enough.

Run Nuclei Against Your Own Infrastructure

# Install nuclei go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest # Basic scan nuclei -u https://yourdomain.com # With specific template categories nuclei -u https://yourdomain.com -t exposures/ -t misconfiguration/ # Exclude noisy info templates for CI/CD runs nuclei -u https://yourdomain.com -severity medium,high,critical

The misconfigurations Nuclei catches in 8 seconds are the ones that show up in breach reports. Run it before every deployment.

See the Full SecurityClaw Pipeline

Nuclei is one layer. SecurityClaw combines it with secrets detection, dependency scanning, web scanning, and manual analysis into a single campaign view:

Learn about SecurityClaw →

SecurityClaw is in active development. The demos section documents real campaign results as the platform matures.

Advertisement