Skip to content

feat: add normalized findings, jsonl/stdout output and workflow docs - #7

Closed
theoffsecgirl wants to merge 3 commits into
mainfrom
copilot/jsonl-workflow-v2
Closed

feat: add normalized findings, jsonl/stdout output and workflow docs#7
theoffsecgirl wants to merge 3 commits into
mainfrom
copilot/jsonl-workflow-v2

Conversation

@theoffsecgirl

Copy link
Copy Markdown
Owner

This PR upgrades webxray from a standalone scanner into a workflow-friendly producer.

Changes

  • add normalized findings schema
  • add --format json|jsonl
  • add --stdout mode
  • move logs/progress output to stderr so stdout can be piped safely
  • keep compatibility with --json-output
  • update README.md and README.es.md with workflow integration examples

Why

This makes webxray compatible with bbcopilot ingest and enables a real bug bounty pipeline:

webxray -u https://target.com --format jsonl --stdout > out.jsonl
bbcopilot ingest webxray out.jsonl
bbcopilot correlate
bbcopilot auto-triage
bbcopilot exploit-plan

Notes

Findings are signals/candidates, not confirmed vulnerabilities.

Copilot AI review requested due to automatic review settings April 19, 2026 09:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR evolves webxray into a workflow-friendly producer by emitting normalized findings in JSON/JSONL, supporting stdout-safe piping, and documenting pipeline integration.

Changes:

  • Add a normalized findings schema plus JSON/JSONL serialization and --stdout output mode.
  • Route logs/progress output to stderr to keep stdout clean for piping/ingestion.
  • Update READMEs with workflow/pipeline usage and new output parameters.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

File Description
webxray.py Adds finding normalization + JSON/JSONL output helpers, introduces --format/--stdout, and moves banner/logs/tqdm output to stderr.
README.md Reworks documentation to highlight pipeline workflow and new output modes.
README.es.md Updates Spanish documentation with normalized output examples and workflow integration guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread webxray.py
"""

__version__ = "1.1.0"
__version__ = "1.2.0"

Copilot AI Apr 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__version__ is bumped to 1.2.0 here, but pyproject.toml still declares project.version = "1.1.0". This will make the installed package version disagree with the CLI/banner version. Consider updating the packaging version (or deriving __version__ from package metadata) to keep them in sync.

Copilot uses AI. Check for mistakes.
Comment thread README.md
# Show version
webxray --version
```
Normalized findings ready for pipeline ingestion.

Copilot AI Apr 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the PR’s key behavior change is “logs/progress to stderr so stdout can be piped safely”, the English README’s Output section should mention that logs/progress go to stderr and only normalized findings are emitted on stdout when using --stdout (or --json-output -). Without this, users may think the tool is noisy on stdout.

Suggested change
Normalized findings ready for pipeline ingestion.
When using `--stdout` or `--json-output -`, logs and progress messages are sent to `stderr`, and only normalized findings are emitted on `stdout`.
This keeps `stdout` safe for piping into other tools.

Copilot uses AI. Check for mistakes.
Comment thread webxray.py
Comment on lines +191 to +195
elif finding_type == "waf_xss":
normalized["vector"] = "xss"
normalized["evidence"] = ["waf-oriented payload reflected in response"]
normalized["tags"] = ["waf-bypass", "get-param"]
normalized["raw"]["waf"] = finding.get("waf")

Copilot AI Apr 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalize_finding stores the original finding dict under raw and then mutates it (normalized["raw"]["waf"] = ...). Even though current WAF findings already include waf, keeping raw as the same object is a surprising side effect and can lead to accidental mutations later. Consider storing a shallow/deep copy in raw and removing the redundant assignment.

Copilot uses AI. Check for mistakes.
Comment thread webxray.py
Comment on lines +210 to +213
def serialize_findings(findings: List[dict], fmt: str) -> str:
if fmt == "jsonl":
return "\n".join(json.dumps(f, ensure_ascii=False) for f in findings)
return json.dumps(findings, indent=2, ensure_ascii=False)

Copilot AI Apr 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For JSONL output, it’s usually safer to end the payload with a trailing newline so concatenation and line-oriented tools behave consistently (and so the last record is newline-terminated when writing to a file). Consider appending "\n" when fmt == "jsonl" (including the empty-findings case).

Copilot uses AI. Check for mistakes.
Comment thread webxray.py
Comment on lines +572 to +574
normalized_findings = [normalize_finding(f) for f in all_findings]

if args.json_output or args.stdout:

Copilot AI Apr 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalized_findings is computed unconditionally, even when neither --json-output nor --stdout is requested. This adds unnecessary work (and retains extra references) on large scans. Consider computing/normalizing only inside the if args.json_output or args.stdout: block.

Suggested change
normalized_findings = [normalize_finding(f) for f in all_findings]
if args.json_output or args.stdout:
if args.json_output or args.stdout:
normalized_findings = [normalize_finding(f) for f in all_findings]

Copilot uses AI. Check for mistakes.
Comment thread README.md
Comment on lines 44 to 48
```text
[*] Starting scan → https://example.com
[*] Crawling depth: 2 | Timeout: 10s

[+] URLs found: 47
[+] Forms found: 8

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
XSS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[!] Reflected XSS → https://example.com/search?q=<script>alert(1)</script>
Parameter: q | Type: GET

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SQLi
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[!] Possible SQLi → https://example.com/product?id=1'
Parameter: id | Error: MySQL syntax

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Headers
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[!] Missing: Content-Security-Policy
[!] Missing: X-Frame-Options
[+] Present: Strict-Transport-Security
[+] Present: X-Content-Type-Options

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
WAF
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[*] WAF detected: Cloudflare
[*] Applying bypass payloads...
[!] Possible bypass → https://example.com/search?q=<img src=x onerror=alert(1)>

[+] Results saved → results.json
[*] Scan completed in 12.4s
--format json|jsonl
--stdout
--json-output
```

Copilot AI Apr 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README "Params" snippet only lists the new output flags, but omits the required -u/--url and other commonly used options (-d, -t, --no-*, --waf-xss). This makes it hard to run the tool from the README alone; consider expanding this list or pointing readers to webxray --help.

Copilot uses AI. Check for mistakes.
Comment thread README.es.md
Comment on lines +97 to +101
### Guardar a fichero e ingerir en `bb-copilot`

```bash
webxray -u https://target.com -d 2 --format jsonl --json-output out.jsonl
bbcopilot ingest webxray out.jsonl

Copilot AI Apr 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README.es.md refers to ingesting into bb-copilot, but the commands use bbcopilot (no hyphen). Consider making the tool name consistent to avoid confusion when users copy/paste.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants