---
name: rt-js-analysis
description: "JavaScript bundle analysis skill. Use to extract secrets, API keys, hardcoded credentials, internal endpoints, and configuration from JavaScript files in SPAs (React, Angular, Vue, Next.js). Covers TruffleHog, Gitleaks, LinkFinder, and source map extraction. Essential for modern web applications."
---

# rt-js-analysis — JavaScript Bundle Analysis

## Overview

Modern Single Page Applications (React, Angular, Vue, Next.js, Nuxt) ship compiled JavaScript bundles that frequently contain hardcoded secrets, API keys, internal endpoint URLs, environment variables, and configuration objects that were never meant to be public. Unlike server-side code, these bundles are delivered directly to the browser and are trivially accessible to any operator.

This skill covers the full workflow for extracting intelligence from JavaScript bundles during a Red Team engagement: discovery, download, deobfuscation, secret scanning, endpoint extraction, and source map reconstruction. Every command below has been validated on Kali Linux.

**Primary objectives:**

- Extract API keys, tokens, and credentials from compiled JS bundles
- Discover undocumented internal API endpoints and admin routes
- Recover original source code via source maps
- Identify environment configuration leaked into client-side code
- Map third-party service integrations (Stripe, Twilio, SendGrid, Firebase, AWS, etc.)

---

## Skill Levels

### BEGINNER

Download JS files from a target and run a basic secret scan.

```bash
# 1. Crawl the target and pull all .js files
TARGET="https://target.example.com"
mkdir -p ~/rtexit/js-analysis && cd ~/rtexit/js-analysis

wget -r -l2 -nd -A "*.js" --no-check-certificate "$TARGET" -P ./bundles/

# 2. Run Gitleaks against the downloaded files
gitleaks detect --source ./bundles/ --report-format json --report-path gitleaks-report.json --no-git
cat gitleaks-report.json | python3 -m json.tool | less

# 3. Grep for common secret patterns manually
grep -rEi \
  "(api[_-]?key|apikey|secret|token|password|passwd|pwd|auth|bearer|access_key|private_key)" \
  ./bundles/ | grep -v "\.map" | head -80

# 4. Find hardcoded URLs and endpoints
grep -rEo "https?://[a-zA-Z0-9._/-]+" ./bundles/ | sort -u | grep -v "cdn\|jquery\|bootstrap\|google"
```

### INTERMEDIATE

Use LinkFinder and TruffleHog for deeper endpoint and secret extraction.

```bash
# 1. Install LinkFinder (if not present)
git clone https://github.com/GerbenJavado/LinkFinder.git ~/tools/LinkFinder
pip3 install jsbeautifier requests

# 2. Run LinkFinder against all local JS files
cd ~/tools/LinkFinder
for f in ~/rtexit/js-analysis/bundles/*.js; do
  echo "[*] Processing: $f"
  python3 linkfinder.py -i "$f" -o cli 2>/dev/null
done | sort -u | tee ~/rtexit/js-analysis/endpoints.txt

# 3. Run LinkFinder against live target (direct URL crawl)
python3 linkfinder.py -i "https://target.example.com" -d -o cli | tee ~/rtexit/js-analysis/endpoints-live.txt

# 4. Run TruffleHog against local directory
trufflehog filesystem ./bundles/ \
  --json \
  --only-verified \
  2>/dev/null | tee ~/rtexit/js-analysis/trufflehog-verified.json

# Run without --only-verified to get all candidates
trufflehog filesystem ./bundles/ \
  --json \
  2>/dev/null | tee ~/rtexit/js-analysis/trufflehog-all.json

# 5. Check for Firebase configuration leaks
grep -rEi "firebase|firebaseConfig|apiKey.*firebase|storageBucket|messagingSenderId" ./bundles/

# 6. Check for AWS credentials
grep -rEi "(AKIA[0-9A-Z]{16}|aws_access_key|aws_secret)" ./bundles/
```

### ADVANCED

Source map extraction, deobfuscation, and targeted secret enumeration.

```bash
# 1. Check if source maps are exposed
curl -s "https://target.example.com/static/js/main.chunk.js.map" | python3 -m json.tool | head -40
# If 200, source maps are exposed — extract original source
# If 404, they may still be referenced in the JS bundle headers

# 2. Find source map references in bundles
grep -rEo "sourceMappingURL=\S+" ./bundles/ | sort -u

# 3. Download and extract source maps with sourcemapper
# Install: go install github.com/denandz/sourcemapper@latest
sourcemapper -url "https://target.example.com/static/js/main.chunk.js.map" \
  -output ~/rtexit/js-analysis/sourcemap-output/

# Alternative: use source-map-cli
npm install -g source-map-cli
source-map decode -m main.chunk.js.map -o ./sourcemap-output/

# 4. Unminify / beautify bundles before scanning
pip3 install jsbeautifier
for f in ./bundles/*.js; do
  js-beautify "$f" > "./bundles/beautified/$(basename $f)"
done

# 5. Extract all string literals (catches obfuscated keys)
python3 - <<'PYEOF'
import re, glob, os

patterns = {
    "AWS Key":        r"AKIA[0-9A-Z]{16}",
    "AWS Secret":     r"(?i)aws.{0,20}secret.{0,20}['\"][0-9a-zA-Z/+]{40}['\"]",
    "Stripe Key":     r"(sk|pk)_(test|live)_[0-9a-zA-Z]{24,}",
    "Twilio":         r"SK[0-9a-fA-F]{32}",
    "Google API":     r"AIza[0-9A-Za-z\-_]{35}",
    "Firebase URL":   r"https://[a-z0-9-]+\.firebaseio\.com",
    "JWT":            r"eyJ[A-Za-z0-9_/+\-]{10,}\.eyJ[A-Za-z0-9_/+\-]{10,}\.[A-Za-z0-9_/+\-]{10,}",
    "Bearer Token":   r"(?i)bearer\s+[a-z0-9\-._~+/]+=*",
    "Basic Auth":     r"(?i)basic\s+[a-z0-9+/=]{10,}",
    "Slack Token":    r"xox[baprs]-[0-9a-zA-Z]{10,}",
    "GitHub PAT":     r"ghp_[0-9a-zA-Z]{36}",
    "SendGrid Key":   r"SG\.[0-9A-Za-z\-_]{22}\.[0-9A-Za-z\-_]{43}",
    "Mailgun Key":    r"key-[0-9a-zA-Z]{32}",
    "Generic Secret": r"(?i)(secret|password|passwd|api.?key)\s*[:=]\s*['\"][^'\"]{8,}['\"]",
}

results = {}
for fpath in glob.glob("./bundles/**/*.js", recursive=True):
    with open(fpath, "r", errors="ignore") as fh:
        content = fh.read()
    for name, pat in patterns.items():
        matches = re.findall(pat, content)
        if matches:
            results.setdefault(fpath, {})[name] = list(set(matches))

for fpath, findings in results.items():
    print(f"\n[FILE] {fpath}")
    for k, v in findings.items():
        print(f"  [{k}]")
        for m in v:
            print(f"    {m}")
PYEOF

# 6. Enumerate discovered endpoints against the target
while IFS= read -r endpoint; do
  code=$(curl -sk -o /dev/null -w "%{http_code}" "$endpoint")
  echo "$code $endpoint"
done < ~/rtexit/js-analysis/endpoints.txt | tee ~/rtexit/js-analysis/endpoint-probe.txt

# Filter interesting responses
grep -E "^(200|201|401|403|500)" ~/rtexit/js-analysis/endpoint-probe.txt
```

### EXPERT

Full pipeline automation, SPA crawling, token verification, and source reconstruction.

```bash
# 1. Use Katana (ProjectDiscovery) for deep SPA crawling
# Install: go install github.com/projectdiscovery/katana/cmd/katana@latest
katana -u "https://target.example.com" \
  -jc \
  -jsl \
  -d 5 \
  -o ~/rtexit/js-analysis/katana-crawl.txt

# Extract JS URLs from katana output
grep "\.js" ~/rtexit/js-analysis/katana-crawl.txt | sort -u > ~/rtexit/js-analysis/js-urls.txt

# 2. Download all discovered JS files in parallel
mkdir -p ~/rtexit/js-analysis/bundles
cat ~/rtexit/js-analysis/js-urls.txt | xargs -P 10 -I{} wget -q --no-check-certificate \
  -P ~/rtexit/js-analysis/bundles/ "{}"

# 3. Full TruffleHog scan with custom detectors
trufflehog filesystem ~/rtexit/js-analysis/bundles/ \
  --json \
  --concurrency 20 \
  2>/dev/null | jq -r 'select(.Verified==true) | "\(.DetectorName): \(.Raw)"' \
  | tee ~/rtexit/js-analysis/verified-secrets.txt

# 4. Attempt to verify leaked API keys
# Google Maps
GOOGLE_KEY="<extracted-key>"
curl -s "https://maps.googleapis.com/maps/api/geocode/json?address=test&key=$GOOGLE_KEY" | jq '.status'

# Stripe
STRIPE_KEY="<extracted-key>"
curl -s https://api.stripe.com/v1/charges -u "$STRIPE_KEY:" | jq '.error.code // "valid"'

# Twilio
TWILIO_SID="<extracted-sid>"
TWILIO_TOKEN="<extracted-token>"
curl -s "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_SID.json" \
  -u "$TWILIO_SID:$TWILIO_TOKEN" | jq '.status'

# Firebase — attempt unauthenticated database read
FB_URL="<extracted-firebase-url>"
curl -s "$FB_URL/.json?print=pretty" | head -40

# 5. Reconstruct full source tree from source maps
# Tool: https://github.com/nicolo-ribaudo/source-map-utils
python3 - <<'PYEOF'
import json, os, sys, urllib.request

map_url = "https://target.example.com/static/js/main.chunk.js.map"
out_dir = os.path.expanduser("~/rtexit/js-analysis/reconstructed/")
os.makedirs(out_dir, exist_ok=True)

with urllib.request.urlopen(map_url) as r:
    smap = json.loads(r.read())

sources = smap.get("sources", [])
contents = smap.get("sourcesContent", [])

for i, src in enumerate(sources):
    clean = src.replace("webpack:///", "").replace("../", "").lstrip("/")
    fpath = os.path.join(out_dir, clean)
    os.makedirs(os.path.dirname(fpath), exist_ok=True)
    if i < len(contents) and contents[i]:
        with open(fpath, "w", errors="replace") as fh:
            fh.write(contents[i])
        print(f"[+] {fpath}")

print(f"\n[*] Reconstructed {len(sources)} source files to {out_dir}")
PYEOF

# 6. Search reconstructed source for hardcoded credentials
grep -rEi \
  "(process\.env\.|REACT_APP_|VUE_APP_|NEXT_PUBLIC_|NG_APP_)" \
  ~/rtexit/js-analysis/reconstructed/ \
  | grep -v "undefined\|null\|example" \
  | tee ~/rtexit/js-analysis/env-vars.txt

# 7. Check Next.js publicRuntimeConfig exposure
curl -s "https://target.example.com/_next/static/chunks/pages/_app.js" \
  | grep -Eo "__NEXT_DATA__\s*=\s*\{[^<]+" | python3 -c "
import sys, json, re
data = sys.stdin.read()
m = re.search(r'\{.*\}', data, re.DOTALL)
if m:
    try: print(json.dumps(json.loads(m.group()), indent=2))
    except: print(m.group()[:2000])
"
```

---

## Step-by-Step Workflow

### Phase 1: Reconnaissance

```bash
# Step 1: Set target and create working directory
TARGET="https://target.example.com"
ENGAGEMENT="client-name-$(date +%Y%m%d)"
WORKDIR=~/rtexit/js-analysis/$ENGAGEMENT
mkdir -p $WORKDIR/{bundles,beautified,endpoints,secrets,sourcemaps,reconstructed,reports}
cd $WORKDIR

# Step 2: Identify the SPA framework
curl -s "$TARGET" | grep -Eo "(react|angular|vue|next|nuxt|ember|backbone)" | sort -u

# Step 3: Get the main HTML and extract JS script tags
curl -sk "$TARGET" | grep -Eo 'src="[^"]*\.js[^"]*"' | sed 's/src="//;s/"//' | sort -u

# Step 4: Check for webpack chunk manifest
curl -s "$TARGET/asset-manifest.json" 2>/dev/null | python3 -m json.tool
curl -s "$TARGET/webpack-manifest.json" 2>/dev/null | python3 -m json.tool
curl -s "$TARGET/_next/static/chunks/webpack.js" -I 2>/dev/null

# Step 5: Check robots.txt and sitemap for hidden routes
curl -s "$TARGET/robots.txt"
curl -s "$TARGET/sitemap.xml" | grep -Eo "<loc>[^<]+" | sed 's/<loc>//'
```

### Phase 2: Bundle Download

```bash
# Step 6: Use Katana for SPA-aware crawling (handles JS routing)
katana -u "$TARGET" -jc -jsl -d 4 -silent | tee $WORKDIR/katana-all.txt
grep -Eo "https?://[^ ]+\.js(\?[^ ]*)?" $WORKDIR/katana-all.txt | sort -u > $WORKDIR/js-urls.txt
wc -l $WORKDIR/js-urls.txt

# Step 7: Download all JS bundles
cat $WORKDIR/js-urls.txt | while read url; do
  fname=$(echo "$url" | md5sum | cut -d' ' -f1).js
  curl -sk "$url" -o "$WORKDIR/bundles/$fname" --create-dirs
  echo "$fname $url" >> $WORKDIR/url-map.txt
done

# Step 8: Alternative — wget recursive download
wget -r -l3 -nd -A "*.js,*.js.map" --no-check-certificate \
  --user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
  "$TARGET" -P $WORKDIR/bundles/
```

### Phase 3: Secret Extraction

```bash
# Step 9: Beautify bundles for better pattern matching
pip3 install jsbeautifier -q
for f in $WORKDIR/bundles/*.js; do
  js-beautify "$f" > "$WORKDIR/beautified/$(basename $f)" 2>/dev/null
done

# Step 10: TruffleHog scan
trufflehog filesystem $WORKDIR/bundles/ --json 2>/dev/null \
  | tee $WORKDIR/secrets/trufflehog-raw.json
cat $WORKDIR/secrets/trufflehog-raw.json \
  | jq -r '"[\(.DetectorName)] \(.Raw // .RawV2) [verified=\(.Verified)]"' \
  | tee $WORKDIR/secrets/trufflehog-summary.txt

# Step 11: Gitleaks scan
gitleaks detect \
  --source $WORKDIR/bundles/ \
  --report-format json \
  --report-path $WORKDIR/secrets/gitleaks.json \
  --no-git 2>/dev/null
jq -r '"\(.RuleID): \(.Secret) [\(.File)]"' $WORKDIR/secrets/gitleaks.json \
  | tee $WORKDIR/secrets/gitleaks-summary.txt

# Step 12: Manual pattern grep
grep -rEi --include="*.js" \
  "(AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z\-_]{35}|xox[baprs]-[0-9]{12}-[0-9a-zA-Z]{24,}|ghp_[0-9a-zA-Z]{36}|sk_(test|live)_[0-9a-zA-Z]{24,}|SG\.[0-9A-Za-z\-_]{22}\.[0-9A-Za-z\-_]{43})" \
  $WORKDIR/bundles/ | tee $WORKDIR/secrets/regex-matches.txt
```

### Phase 4: Endpoint Discovery

```bash
# Step 13: LinkFinder endpoint extraction
cd ~/tools/LinkFinder
for f in $WORKDIR/bundles/*.js; do
  python3 linkfinder.py -i "$f" -o cli 2>/dev/null
done | sort -u | tee $WORKDIR/endpoints/linkfinder-raw.txt

# Step 14: Custom endpoint extraction
grep -rEho "(?<=['\"])/[a-zA-Z0-9_/.-]{3,}(?=['\"])" $WORKDIR/bundles/ \
  | sort -u | grep -v "\.png\|\.svg\|\.css\|\.woff" \
  | tee $WORKDIR/endpoints/path-only.txt

# Step 15: Combine and deduplicate endpoints
cat $WORKDIR/endpoints/linkfinder-raw.txt $WORKDIR/endpoints/path-only.txt \
  | sort -u > $WORKDIR/endpoints/all-endpoints.txt
wc -l $WORKDIR/endpoints/all-endpoints.txt

# Step 16: Probe discovered endpoints
while IFS= read -r path; do
  [[ "$path" == http* ]] && url="$path" || url="$TARGET$path"
  code=$(curl -sk -o /dev/null -w "%{http_code}" -m 5 "$url")
  echo "$code $url"
done < $WORKDIR/endpoints/all-endpoints.txt \
  | tee $WORKDIR/endpoints/probe-results.txt

grep -E "^(200|201|204|301|302|400|401|403|500)" $WORKDIR/endpoints/probe-results.txt \
  | sort -k1,1 | tee $WORKDIR/endpoints/interesting-responses.txt
```

### Phase 5: Source Map Reconstruction

```bash
# Step 17: Find source map references
grep -rEo "sourceMappingURL=[^\s]+" $WORKDIR/bundles/ | sort -u

# Step 18: Download source maps
grep -rEo "https?://[^ ]+\.js\.map" $WORKDIR/bundles/ | sort -u | while read mapurl; do
  curl -sk "$mapurl" -o "$WORKDIR/sourcemaps/$(basename $mapurl)" 2>/dev/null \
    && echo "[+] Downloaded: $mapurl" \
    || echo "[-] Failed: $mapurl"
done

# Try appending .map to each JS URL
cat $WORKDIR/js-urls.txt | while read url; do
  mapurl="${url}.map"
  code=$(curl -sk -o "$WORKDIR/sourcemaps/$(basename $mapurl)" -w "%{http_code}" "$mapurl")
  [[ "$code" == "200" ]] && echo "[+] $mapurl" || rm -f "$WORKDIR/sourcemaps/$(basename $mapurl)"
done

# Step 19: Extract source files from maps
for mapfile in $WORKDIR/sourcemaps/*.map; do
  python3 - "$mapfile" "$WORKDIR/reconstructed/" <<'PYEOF'
import json, os, sys

map_path = sys.argv[1]
out_base = sys.argv[2]
os.makedirs(out_base, exist_ok=True)

with open(map_path, "r", errors="replace") as fh:
    smap = json.load(fh)

sources = smap.get("sources", [])
contents = smap.get("sourcesContent", [])
count = 0

for i, src in enumerate(sources):
    clean = src.replace("webpack:///", "").replace("webpack://", "")
    clean = clean.lstrip("./").replace("../", "").lstrip("/")
    if not clean or clean.startswith("?"):
        continue
    fpath = os.path.join(out_base, clean)
    os.makedirs(os.path.dirname(fpath), exist_ok=True)
    if i < len(contents) and contents[i]:
        with open(fpath, "w", errors="replace") as fh:
            fh.write(contents[i])
        count += 1

print(f"[+] {os.path.basename(map_path)}: extracted {count}/{len(sources)} files")
PYEOF
done
```

### Phase 6: Reporting

```bash
# Step 20: Generate RTExit-compatible finding file
python3 - <<PYEOF
import json, datetime, os, glob

workdir = os.path.expanduser("~/rtexit/js-analysis/$ENGAGEMENT")
finding = {
    "skill": "rt-js-analysis",
    "timestamp": datetime.datetime.utcnow().isoformat() + "Z",
    "target": "$TARGET",
    "engagement": "$ENGAGEMENT",
    "findings": {
        "secrets": [],
        "endpoints": [],
        "source_maps_found": False,
        "reconstructed_files": 0
    }
}

# Load TruffleHog results
th_path = os.path.join(workdir, "secrets/trufflehog-raw.json")
if os.path.exists(th_path):
    with open(th_path) as fh:
        for line in fh:
            try:
                item = json.loads(line)
                finding["findings"]["secrets"].append({
                    "tool": "trufflehog",
                    "type": item.get("DetectorName"),
                    "verified": item.get("Verified", False),
                    "raw": item.get("Raw", "")[:200]
                })
            except: pass

# Load endpoints
ep_path = os.path.join(workdir, "endpoints/interesting-responses.txt")
if os.path.exists(ep_path):
    with open(ep_path) as fh:
        for line in fh:
            parts = line.strip().split(" ", 1)
            if len(parts) == 2:
                finding["findings"]["endpoints"].append({"status": parts[0], "url": parts[1]})

# Count reconstructed files
recon = glob.glob(os.path.join(workdir, "reconstructed/**/*"), recursive=True)
finding["findings"]["reconstructed_files"] = len([f for f in recon if os.path.isfile(f)])
finding["findings"]["source_maps_found"] = finding["findings"]["reconstructed_files"] > 0

out = os.path.join(workdir, "reports/rtexit-finding.json")
with open(out, "w") as fh:
    json.dump(finding, fh, indent=2)
print(f"[+] RTExit finding written to: {out}")
print(f"    Secrets found:       {len(finding['findings']['secrets'])}")
print(f"    Endpoints found:     {len(finding['findings']['endpoints'])}")
print(f"    Reconstructed files: {finding['findings']['reconstructed_files']}")
PYEOF
```

---

## Tools Reference

| Tool | Purpose | URL |
|------|---------|-----|
| TruffleHog | Secret scanning with verification | https://github.com/trufflesecurity/trufflehog |
| Gitleaks | Secret pattern detection | https://github.com/gitleaks/gitleaks |
| LinkFinder | Endpoint extraction from JS | https://github.com/GerbenJavado/LinkFinder |
| Katana | SPA-aware web crawler | https://github.com/projectdiscovery/katana |
| sourcemapper | Source map downloader/extractor | https://github.com/denandz/sourcemapper |
| jsbeautifier | JS unminification | https://github.com/beautify-web/js-beautify |
| SecretFinder | Regex-based secret finder for JS | https://github.com/m4ll0k/SecretFinder |
| getJS | Collects JS files from a target | https://github.com/003random/getJS |
| subjs | Finds JS files from subdomains | https://github.com/lc/subjs |
| xnLinkFinder | Advanced endpoint extraction | https://github.com/xnl-h4ck3r/xnLinkFinder |

### Tool Installation (Kali Linux)

```bash
# TruffleHog
curl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh | sh -s -- -b /usr/local/bin

# Gitleaks
wget https://github.com/gitleaks/gitleaks/releases/latest/download/gitleaks_$(uname -s)_x64.tar.gz -O /tmp/gitleaks.tar.gz
tar -xzf /tmp/gitleaks.tar.gz -C /usr/local/bin gitleaks

# Katana
go install github.com/projectdiscovery/katana/cmd/katana@latest

# LinkFinder
git clone https://github.com/GerbenJavado/LinkFinder.git ~/tools/LinkFinder
cd ~/tools/LinkFinder && pip3 install -r requirements.txt

# getJS
go install github.com/003random/getJS@latest

# subjs
go install github.com/lc/subjs@latest

# jsbeautifier
pip3 install jsbeautifier

# xnLinkFinder
pip3 install xnLinkFinder
```

---

## Wordlists and SecLists Integration

When probing discovered API endpoints, augment with relevant SecLists wordlists:

```bash
# API endpoint fuzzing against discovered base paths
SECLISTS=/usr/share/seclists

# Fuzz for additional API routes
ffuf -u "$TARGET/api/FUZZ" \
  -w $SECLISTS/Discovery/Web-Content/api/api-endpoints.txt \
  -fc 404 -mc all -o $WORKDIR/endpoints/ffuf-api.json -of json

# Admin panel discovery
ffuf -u "$TARGET/FUZZ" \
  -w $SECLISTS/Discovery/Web-Content/directory-list-2.3-medium.txt \
  -fc 404 -mc 200,201,301,302,401,403 \
  -o $WORKDIR/endpoints/ffuf-dirs.json -of json

# JavaScript file discovery
ffuf -u "$TARGET/static/js/FUZZ.js" \
  -w $SECLISTS/Discovery/Web-Content/raft-medium-words.txt \
  -fc 404 -o $WORKDIR/endpoints/ffuf-js.json -of json

# Combine LinkFinder results with SecLists for endpoint brute-force
cat $WORKDIR/endpoints/path-only.txt $SECLISTS/Discovery/Web-Content/api/objects.txt \
  | sort -u | ffuf -u "$TARGET/FUZZ" -w - -fc 404
```

---

## Output Files

All output is written to `~/rtexit/js-analysis/<engagement>/`:

```
<engagement>/
├── bundles/                  # Raw downloaded JS files
├── beautified/               # Unminified JS for manual review
├── sourcemaps/               # Downloaded .map files
├── reconstructed/            # Extracted original source tree
├── endpoints/
│   ├── linkfinder-raw.txt    # All extracted endpoints
│   ├── path-only.txt         # Path-only endpoints
│   ├── all-endpoints.txt     # Deduplicated full list
│   ├── probe-results.txt     # HTTP status for each endpoint
│   └── interesting-responses.txt  # Non-404 responses
├── secrets/
│   ├── trufflehog-raw.json   # Full TruffleHog JSON output
│   ├── trufflehog-summary.txt
│   ├── gitleaks.json         # Gitleaks JSON output
│   ├── gitleaks-summary.txt
│   └── regex-matches.txt     # Manual regex grep results
└── reports/
    └── rtexit-finding.json   # RTExit autodoc engine input
```

### RTExit Autodoc Integration

The `reports/rtexit-finding.json` file produced in Phase 6 is consumed directly by the RTExit autodoc engine. Place completed findings in the engagement's `findings/` directory:

```bash
cp $WORKDIR/reports/rtexit-finding.json \
  ~/rtexit/engagements/$ENGAGEMENT/findings/rt-js-analysis-$(date +%H%M%S).json
```

The autodoc engine will pick up the file on next run and incorporate the findings into the engagement report. Verified secrets are automatically flagged as Critical; unverified patterns are flagged as High.

---

## Common Findings and Their Impact

| Finding Type | Typical Impact | Verification |
|---|---|---|
| Firebase API Key | Unauthenticated database read/write | `curl "$FB_URL/.json?print=pretty"` |
| Stripe Secret Key | Full payment data access, charge customers | `curl -u "$KEY:" https://api.stripe.com/v1/charges` |
| AWS Access Key | Cloud resource access, data exfiltration | `aws sts get-caller-identity --key-id $KEY` |
| Google Maps API Key | API quota abuse, billing fraud | Maps geocode endpoint |
| JWT Secret | Token forgery, authentication bypass | jwt.io signature test |
| Internal API base URL | Undocumented endpoint exposure | Probe with ffuf |
| Environment variables | Reveals infrastructure, credentials | Grep for process.env |
| GraphQL schema introspection | Full API schema exposure | `{"query":"{__schema{types{name}}}"}` |

---

## Operational Notes

- Always run in an authorized engagement scope. Verify credentials against live services only with written authorization.
- Source map extraction may recover proprietary source code — handle per rules of engagement.
- Some targets deploy honeypot credentials in JS bundles. Use infrastructure-side verification before escalating.
- React DevTools and Angular Augury browser extensions can expose component state containing live credentials in development builds.
- Next.js `getServerSideProps` results are serialized into `__NEXT_DATA__` on every page load — always check this endpoint.
- Check for `.env` files accidentally committed: `curl -s "$TARGET/.env"`.

---

## Resources

- PortSwigger Web Security Academy — JavaScript Analysis: https://portswigger.net/web-security
- OWASP Testing Guide — Testing for Sensitive Data in JS: https://owasp.org/www-project-web-security-testing-guide/
- TruffleHog Documentation: https://github.com/trufflesecurity/trufflehog/wiki
- Gitleaks Rules Reference: https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml
- HackTricks — JavaScript Deobfuscation: https://book.hacktricks.xyz/pentesting-web/javascript-deobfuscation
- SecLists API Wordlists: https://github.com/danielmiessler/SecLists/tree/master/Discovery/Web-Content/api
- LinkFinder Usage Guide: https://github.com/GerbenJavado/LinkFinder#usage
- Source Map Specification: https://tc39.es/source-map/
- Katana Documentation: https://github.com/projectdiscovery/katana#readme
- JS Nice (online deobfuscator): http://www.jsnice.org/
- Prettier (JS formatter): https://prettier.io/
