Skip to content

R3DRUN3/waptly

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

waptly

Release Latest Release
License: Unlicense Red Team Badge

A lightweight, fast and extensible CLI tool to automate security posture checks during Web Application Penetration Testing (WAPT) activities.
Waptly scans one or more targets concurrently and outputs a structured JSON report, helping pentesters map the webapp risk surface.


Caution

Waptly is intended for authorized security testing only.
Do not use against systems you do not own or have explicit permission to test.

Checks

Checks include (but are not limited to):

Module Description
http_security_headers Detects missing security headers (CSP, HSTS, X-Frame-Options, etc.)
waf_detection Fingerprints WAF presence via response headers (Cloudflare, Akamai, AWS, etc.)
tls Checks TLS version, certificate expiry, self-signed certs and weak ciphers
robots_txt Parses robots.txt and flags sensitive paths exposed to crawlers
http_methods Probes dangerous HTTP methods (TRACE, PUT, DELETE, CONNECT)

Use case

waptly is primarily designed as a component to be integrated into red team automation workflows, with the purpose of assisting in mapping the attack surface of a web application.
It helps generate actionable insights to be further investigated during penetration testing activities.
The output already includes findings that can be directly incorporated into the final report, such as missing HTTP security headers.
waptly is not intended to replace established WAPT tools such as Nuclei, Gobuster or Burp Suite.
On the contrary, it is designed to complement them.
waptly is also highly effective as a tool for AI agents operating via CLI environments, such as Claude Code or Codex.
It is possible either to create a customized skill file for the agent or to have the agent invoke the tool directly,
for example, when using Codex:

codex --full-auto "run the command `./waptly https://pentest-ground.com:4280/` and write a summary of the output to FINDINGS.md"

Usage

You can directly download the latest binary release for your target architecture, however, the recommended way to run waptly is via Docker:

docker run ghcr.io/r3drun3/waptly:v0.1.4 <target_1> <target_2> <target_n>
video-demo.mp4

Tip

By default, the JSON output only includes failed checks, keeping the report focused and noise-free.
Pass the --verbose (or -v) flag to include all checks regardless of their result.
Example: waptly --verbose https://example.com

Output

Waptly outputs a single JSON report to stdout, here is an example:

{
  "version": "v0.1.4",
  "generated_at": "2026-04-27T15:54:15Z",
  "targets": [
    {
      "target": "https://pentest-ground.com:4280/",
      "checks": [
        {
          "check": "cookie_security",
          "passed": false,
          "details": {
            "findings": [
              {
                "name": "security",
                "missing_secure": true,
                "missing_http_only": true,
                "missing_same_site": true,
                "severity": "high"
              },
              {
                "name": "PHPSESSID",
                "missing_secure": true,
                "missing_http_only": true,
                "missing_same_site": true,
                "severity": "high"
              }
            ],
            "total_cookies_checked": 2
          }
        },
        {
          "check": "error_handling",
          "passed": true,
          "details": {
            "results": [
              {
                "payload_type": "large_payload",
                "path": "/",
                "triggered_500": false
              },
              {
                "payload_type": "malformed_json",
                "path": "/",
                "triggered_500": false
              },
              {
                "payload_type": "unicode_fuzz",
                "path": "/",
                "triggered_500": false
              },
              {
                "payload_type": "sql_injection",
                "path": "/?id=' OR 1=1--",
                "triggered_500": false
              },
              {
                "payload_type": "cmd_injection",
                "path": "/?q=;cat /etc/passwd",
                "triggered_500": false
              }
            ]
          }
        },
        {
          "check": "exposed_files",
          "passed": false,
          "details": {
            "base_url": "https://pentest-ground.com:4280",
            "found": [
              {
                "path": "/phpinfo.php",
                "status_code": 200,
                "content_type": "text/html; charset=UTF-8",
                "body_preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>\n<style type=\"text/css\">\nbody {background-color: #fff; co...",
                "severity": "high"
              }
            ],
            "found_count": 1,
            "probed": 30
          }
        },
        {
          "check": "http_security_headers",
          "passed": false,
          "details": {
            "missing": {
              "Content-Security-Policy": "Mitigates XSS and data injection attacks",
              "Cross-Origin-Opener-Policy": "Isolates browsing context against XS-Leaks",
              "Cross-Origin-Resource-Policy": "Controls cross-origin resource sharing",
              "Permissions-Policy": "Restricts browser feature access",
              "Referrer-Policy": "Controls referrer information leakage",
              "Strict-Transport-Security": "Enforces HTTPS (HSTS)",
              "X-Content-Type-Options": "Prevents MIME-type sniffing",
              "X-Frame-Options": "Protects against clickjacking"
            },
            "present": {}
          }
        },
        {
          "check": "http_methods",
          "passed": false,
          "details": {
            "dangerous_methods": [
              {
                "method": "TRACK",
                "status_code": 200,
                "risk": "Variant of TRACE, used by older IIS servers",
                "severity": "high",
                "advertised_by_options": false
              },
              {
                "method": "PUT",
                "status_code": 200,
                "risk": "Arbitrary file upload may be possible",
                "severity": "critical",
                "advertised_by_options": false
              },
              {
                "method": "DELETE",
                "status_code": 200,
                "risk": "Destructive operations may be possible",
                "severity": "critical",
                "advertised_by_options": false
              },
              {
                "method": "CONNECT",
                "status_code": 400,
                "risk": "Server may be usable as an HTTP proxy",
                "severity": "high",
                "advertised_by_options": false
              },
              {
                "method": "PATCH",
                "status_code": 200,
                "risk": "Partial resource modification may be possible",
                "severity": "medium",
                "advertised_by_options": false
              }
            ],
            "issues": [
              "TRACK enabled (HTTP 200) — Variant of TRACE, used by older IIS servers",
              "PUT enabled (HTTP 200) — Arbitrary file upload may be possible",
              "DELETE enabled (HTTP 200) — Destructive operations may be possible",
              "CONNECT enabled (HTTP 400) — Server may be usable as an HTTP proxy",
              "PATCH enabled (HTTP 200) — Partial resource modification may be possible"
            ],
            "options_advertised": null
          }
        },
        {
          "check": "https_redirect",
          "passed": false,
          "details": {
            "http_status": 400,
            "location": "",
            "message": "No valid HTTP to HTTPS redirect."
          }
        },
        {
          "check": "open_redirect",
          "passed": true,
          "details": {
            "findings": []
          }
        },
        {
          "check": "robots_txt",
          "passed": true,
          "details": {
            "entries": [
              {
                "user_agent": "*",
                "disallowed": [
                  "/"
                ]
              }
            ],
            "found": true,
            "raw_lines": [
              "User-agent: *",
              "Disallow: /"
            ],
            "robots_url": "https://pentest-ground.com:4280/robots.txt",
            "sensitive_paths": null,
            "status_code": 200
          }
        },
        {
          "check": "server_banner",
          "passed": false,
          "details": {
            "findings": [
              {
                "header": "Server",
                "value": "nginx/1.29.8",
                "technology": "nginx",
                "versions": [
                  "1.29.8"
                ]
              },
              {
                "header": "X-Powered-By",
                "value": "PHP/8.5.5",
                "technology": "PHP",
                "versions": [
                  "8.5.5"
                ]
              }
            ],
            "leaking": true,
            "technologies": [
              "nginx",
              "PHP"
            ],
            "versions": [
              "1.29.8",
              "8.5.5"
            ]
          }
        },
        {
          "check": "tls",
          "passed": true,
          "details": {
            "certificates": [
              {
                "days_until_expiry": 56,
                "dns_names": [
                  "pentest-ground.com"
                ],
                "expired": false,
                "is_ca": false,
                "issuer": "E7",
                "not_after": "2026-06-23T03:10:40Z",
                "not_before": "2026-03-25T03:10:41Z",
                "self_signed": false,
                "signature_algorithm": "ECDSA-SHA384",
                "subject": "pentest-ground.com"
              },
              {
                "dns_names": null,
                "is_ca": true,
                "issuer": "ISRG Root X1",
                "not_after": "2027-03-12T23:59:59Z",
                "not_before": "2024-03-13T00:00:00Z",
                "signature_algorithm": "SHA256-RSA",
                "subject": "E7"
              }
            ],
            "cipher_suite": "TLS_AES_128_GCM_SHA256",
            "issues": [],
            "tls_version": "TLS 1.3",
            "weak_cipher": false
          }
        },
        {
          "check": "waf_detection",
          "passed": false,
          "details": {
            "detected": [],
            "evidence": {},
            "waf_detected": false
          }
        }
      ]
    }
  ]
}

Adding a new check

  1. Create checks/your_check.go in the checks/ package
  2. Implement the Check interface
  3. Register it via init() (no changes to main.go needed)

About

Automate the tedious web security poking.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors