Skip to content

alexlux58/PageSourceAnalyzer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PageSourceAnalyzer

Authorized bug-bounty recon scanner. Fetches a target page + its linked JavaScript (and optionally .map files), runs deterministic detection rules for likely-sensitive artifacts (tokens, keys, JWTs, internal endpoints, suspicious comments), and can optionally hand a masked summary to an OpenAI model for triage.

Only use this on targets you are explicitly authorized to test (your own apps, in-scope bug bounty programs, lab environments, etc.). A scope allowlist is supported and recommended.

Install

cd ~/Desktop/PageSourceAnalyzer
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env   # only needed if you want --ai

Quick start

# Single page, deterministic scan only.
python scanner.py https://example.com

# With AI triage (masked findings only are sent to the model).
python scanner.py https://example.com --ai

# AI triage is also saved as Markdown under reports/ai/ by default.
python scanner.py https://example.com --ai --ai-report-dir reports/ai

# Crawl the target same-origin, up to 25 pages, depth 2, 0.5s between requests.
python scanner.py https://target.example \
  --crawl --max-pages 25 --max-depth 2 --delay 0.5

# Use a scope allowlist so you can't accidentally hit out-of-scope hosts.
python scanner.py https://target.example --scope scope/target.txt

# Persist findings to SQLite so re-runs print "new findings vs previous".
python scanner.py https://target.example --db reports/history.sqlite

Every run also writes a full JSON report to reports/<host>-<timestamp>.json. When --ai is enabled, the AI triage is saved separately as reports/ai/<host>-<timestamp>-ai-triage.md. Use --show-ai if you also want the full AI triage printed in the terminal. Use --quiet to hide the progress/loading output.

Scope files

--scope path/to/file.txt enables a strict allowlist. Format:

# one host per line, comments allowed
target.example
api.target.example
# subdomains of listed hosts are also allowed

If the target URL or any linked JS host is not in scope, the scanner refuses to fetch it.

What it detects

Deterministic rules (regex + entropy):

  • Cloud / SaaS keys: AWS (AKIA/ASIA), Google (AIza), Slack (xox*), GitHub (ghp_, etc), Stripe (sk_live_, pk_live_), SendGrid, Mailgun, Twilio account SIDs
  • JWTs, Authorization: Bearer …, Basic … headers
  • PEM -----BEGIN … PRIVATE KEY----- blocks
  • apiKey = "…" / password: "…" / client_secret = "…" assignments
  • Emails, RFC1918 internal IPs, full URLs
  • Interesting endpoint paths under /api/, /admin/, /internal/, /debug/, /dev/, /staging/, /graphql/, /v1/, …
  • sourceMappingURL=… references, and (with default settings) the actual .map files plus their listed original source paths
  • Firebase realtime DB URLs, S3 bucket URLs
  • Suspicious HTML comments: TODO, FIXME, password, secret, do not commit, remove before prod, etc.
  • High-entropy strings (>=4.2 bits/char) inside quoted literals, flagged as medium for manual validation

HTML injection / DOM-XSS

Static review of inline and external JavaScript for the classic OWASP WSTG-CLNT-03 pattern: an untrusted source flowing into a dangerous sink. No payloads are sent, no scripts are executed.

Sinks detected:

  • element.innerHTML / outerHTML assignments, insertAdjacentHTML
  • document.write / document.writeln
  • eval(...), new Function(...), setTimeout("...string...") / setInterval("...string...")
  • jQuery sinks: .html(), .append(), .prepend(), .after(), .before(), .replaceWith(), and selectors built by string concatenation ($("div[id=" + t + "]"))
  • React dangerouslySetInnerHTML
  • Vue v-html, Angular [innerHTML], Angular bypassSecurityTrust*
  • Direct location / location.href assignment

Sources detected:

  • location.hash, location.search, location.href, location.pathname
  • document.URL, document.documentURI, document.baseURI, document.referrer, document.cookie
  • window.name
  • localStorage.getItem / sessionStorage.getItem
  • URLSearchParams / .searchParams
  • window.addEventListener("message", ...) (postMessage receiver)

Severity:

  • high — a source appears within ~600 characters of a sink in the same file (likely tainted data flow worth manual review).
  • medium — a sink is fed something dynamic (string concatenation or template literal) but no source is nearby.
  • Standalone sinks/sources are intentionally not reported, because bundled framework code contains them everywhere and they drown the signal. Disable with --no-dom-xss if you want to skip the pass.

Response security headers

After fetching a page the scanner inspects the response headers for mitigations that matter for HTML injection / DOM-XSS:

  • missing_csp_header — no Content-Security-Policy header set
  • csp_unsafe_inline'unsafe-inline' in script-src / default-src
  • csp_unsafe_eval'unsafe-eval' anywhere in the policy

Disable with --no-header-checks.

What it does not do

  • It does not try to use any discovered credential.
  • It does not send raw secret values to the AI model — only masked previews (first 6 + last 4 chars) and short context snippets.
  • It does not fuzz or send active exploitation payloads.

Workflow

  1. Run the scanner against an in-scope target.
  2. Review reports/<host>-<timestamp>.json. Sort by severity_hint: high.
  3. Manually validate before reporting:
    • Is the value a placeholder (YOUR_API_KEY_HERE, xxx, changeme)?
    • Is it a public/publishable key (e.g. pk_live_… for Stripe) that is supposed to be client-side?
    • Is the endpoint actually reachable without auth?
    • Is the source map exposing readable original source?
  4. File a responsible-disclosure report using the skeleton in this README (or the one the AI triage step produces).

Report skeleton

# Exposed Sensitive Information in Client-Side Source

## Summary
Sensitive information appears to be exposed in client-side HTML/JavaScript.

## Affected Asset
https://target.example/static/app.js

## Evidence
Finding type: <jwt | api_key | source_map | internal_endpoint | …>
Location:     external JavaScript
Masked value: eyJhbG...abcd

## Steps to Reproduce
1. Visit https://target.example
2. Open the linked JavaScript asset above
3. Search for `token`, `secret`, `apiKey`, or the masked value shown

## Impact
An attacker may discover internal API endpoints, credentials, or tokens
that should not be exposed client-side, enabling further enumeration or
unauthorized access.

## Recommendation
Remove secrets from client-side code, rotate any exposed credentials,
restrict access to source maps, and move sensitive operations server-side.

SQLite history

When --db reports/history.sqlite is passed, each finding is keyed by (target, source_url, location, finding_type, match). Re-running on the same target prints how many findings are new since previous runs — useful for monitoring a target over time without re-reading every report.

Roadmap

  • Wayback Machine URL import
  • SARIF output (GitHub Security tab)
  • HTML report generator
  • Slack/Discord webhook notifications
  • GitHub dork export for related code disclosures

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages