Bolt.new ships AI-generated apps to bolt.host subdomains in seconds, but the default templates often ship exposed API keys in client bundles and permissive CORS. This tutorial shows an ethical scan workflow that finds misconfigs in your own Bolt apps using Scavio SERP discovery.
Prerequisites
- Python 3.10+
- A Scavio API key
- Written permission for any target domain
- requests library
Walkthrough
Step 1: Enumerate Bolt-hosted apps
SERP dorks find apps indexed under bolt.host.
DORKS = [
'site:bolt.host',
'site:bolt.host api_key',
'site:bolt.host \"supabase\" OR \"firebase\"'
]Step 2: Collect candidate URLs
Run each dork through Scavio.
import requests, os
API_KEY = os.environ['SCAVIO_API_KEY']
def enumerate():
urls = set()
for d in DORKS:
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY}, json={'query': d, 'num_results': 50})
for h in r.json().get('organic_results', []):
urls.add(h['link'])
return urlsStep 3: Fetch client JS bundles
Look for leaked secrets in the bundled JS.
import re
SECRET_PATTERNS = [r'sk_live_[A-Za-z0-9]{20,}', r'AIza[A-Za-z0-9_-]{30,}', r'eyJ[A-Za-z0-9_-]{20,}']
def scan_bundle(url):
html = requests.get(url, timeout=10).text
js_urls = re.findall(r'src=\"([^\"]+\.js)\"', html)
hits = []
for j in js_urls:
full = j if j.startswith('http') else url.rstrip('/') + j
body = requests.get(full, timeout=10).text
for p in SECRET_PATTERNS:
hits += re.findall(p, body)
return hitsStep 4: Test CORS policy
Check for Access-Control-Allow-Origin: *.
def cors_check(url):
r = requests.options(url, headers={'Origin': 'https://evil.example'})
return r.headers.get('Access-Control-Allow-Origin') == '*'Step 5: Report
Write a per-app finding with severity.
def report(url, secrets, cors_wide):
if secrets or cors_wide:
print(f'[{url}] secrets={len(secrets)} cors_wide={cors_wide}')Python Example
import os, requests, re
API_KEY = os.environ['SCAVIO_API_KEY']
PATTERNS = [r'sk_live_[A-Za-z0-9]{20,}', r'AIza[A-Za-z0-9_-]{30,}']
def scan():
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'query': 'site:bolt.host my-app', 'num_results': 20})
for h in r.json().get('organic_results', []):
html = requests.get(h['link'], timeout=10).text
secrets = []
for p in PATTERNS: secrets += re.findall(p, html)
if secrets: print(f'[{h["link"]}] leaked secrets: {len(secrets)}')
scan()JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY;
const PATTERNS = [/sk_live_[A-Za-z0-9]{20,}/g, /AIza[A-Za-z0-9_-]{30,}/g];
export async function scan() {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'site:bolt.host my-app', num_results: 20 })
});
const data = await r.json();
for (const h of data.organic_results || []) {
const html = await (await fetch(h.link)).text();
const secrets = PATTERNS.flatMap(p => html.match(p) || []);
if (secrets.length) console.log(`[${h.link}] ${secrets.length} secrets`);
}
}Expected Output
Per-URL list of leaked secrets and CORS posture. Typical finding rate: 5-15% of Bolt apps have at least one exposed key.