[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-aws-labs-url-analysis":3,"mdc--y7pr06-key":39,"related-org-aws-labs-url-analysis":2196,"related-repo-aws-labs-url-analysis":2376},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":29,"repoUrl":30,"updatedAt":31,"license":32,"forks":33,"topics":34,"repo":35,"sourceUrl":37,"mdContent":38},"url-analysis","analyze suspicious URLs in isolated browser sessions","Analyze a suspicious URL by visiting it in an isolated AgentCore Browser\nsession. Captures screenshots, DOM, network requests, redirects, and\nextracted IOCs. Use for phishing triage, suspicious-link investigation,\nand malicious-site fingerprinting.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"aws-labs","AWS Labs","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Faws-labs.png","awslabs",[13,17,20,23,26],{"name":14,"slug":15,"type":16},"Security","security","tag",{"name":18,"slug":19,"type":16},"Triage","triage",{"name":21,"slug":22,"type":16},"Code Analysis","code-analysis",{"name":24,"slug":25,"type":16},"Debugging","debugging",{"name":27,"slug":28,"type":16},"Browser Automation","browser-automation",1,"https:\u002F\u002Fgithub.com\u002Fawslabs\u002Fagentic-developer-platform","2026-08-04T05:58:51.393402",null,0,[],{"repoUrl":30,"stars":29,"forks":33,"topics":36,"description":32},[],"https:\u002F\u002Fgithub.com\u002Fawslabs\u002Fagentic-developer-platform\u002Ftree\u002FHEAD\u002Fmodules\u002Fdomain-apps\u002Fcyber\u002Fagent\u002Fskills\u002Furl-analysis","---\nname: url-analysis\ndescription: |\n  Analyze a suspicious URL by visiting it in an isolated AgentCore Browser\n  session. Captures screenshots, DOM, network requests, redirects, and\n  extracted IOCs. Use for phishing triage, suspicious-link investigation,\n  and malicious-site fingerprinting.\ncompatibility: requires agentcore-browser, requires url-allowlist-config\nallowed-tools: Bash Read Write WebFetch\nmetadata:\n  stage: url-triage\n  typical_duration_seconds: 120\n  session_timeout_seconds: 300\n---\n\n# url-analysis skill\n\n## What this skill does\n\nAnalyze a suspicious URL using an isolated AgentCore Browser session, produce a\nstructured forensic report with verdict + confidence + IOCs + recommended actions.\n\nThe browser session runs in AWS-managed infrastructure, never in our VPC. Evidence\nis captured and synthesized into a deterministic verdict via `verdict.py`.\n\n## Your job as the executing agent\n\nGiven a URL to analyze:\n\n### 1. Pre-flight validation\n\n```python\nfrom denylist import DenylistConfig, check_url, scrub_url_credentials\n\nsafe_url = scrub_url_credentials(url)\nresult = check_url(url)\nif not result.allowed:\n    # Return immediately with status \"refused\" and result.reason\n    # Do NOT create a browser session\n    pass\n```\n\n### 2. Write and execute an orchestration script\n\nWrite a Python script that:\n- Opens an AgentCore Browser session (see `agentcore-browser-contract.md`)\n- Navigates to the URL\n- Captures a screenshot\n- Extracts visible text (via screenshot + your interpretation, or via CDP)\n- Detects any auto-downloads or forms\n- Populates an `Evidence` object (see `evidence_schema.py`)\n- Stops the browser session in a `finally` block\n\n**Key rules for the orchestration script:**\n- Language: Python 3.11+\n- Use `boto3.client('bedrock-agentcore', region_name='us-east-1')`\n- Follow `agentcore-browser-contract.md` for exact API shapes\n- The API provides OS-level actions (mouseClick, keyType, screenshot) NOT\n  high-level browser automation (no `navigate`, no `evaluate`, no `getHar`)\n- To navigate: type the URL into the browser address bar or use Playwright via CDP\n- Screenshots return base64-encoded PNG data\n- Always call `stop_browser_session` in a finally block\n- Save the script to `\u002Ftmp\u002Frun-artifacts\u002F{run_id}\u002Forchestration.py`\n\n**Two approaches to browser interaction. Default to CDP. Only fall back to InvokeBrowser if CDP fails at runtime.**\n\n1. **Playwright via CDP WebSocket — DEFAULT. USE THIS FIRST.**\n\n   Do NOT reject this path because \"CDP requires SigV4.\" The\n   `bedrock-agentcore` SDK handles SigV4 for you. The one-line idiom is:\n\n   ```python\n   from bedrock_agentcore.tools.browser_client import BrowserClient\n   from playwright.sync_api import sync_playwright\n\n   bc = BrowserClient(region=\"us-east-1\")\n   session_id = bc.start()                     # start_browser_session\n   ws_url, headers = bc.generate_ws_headers()  # SigV4-signed, ready to use\n\n   with sync_playwright() as p:\n       browser = p.chromium.connect_over_cdp(ws_url, headers=headers)\n       page = browser.contexts[0].pages[0] if browser.contexts else browser.new_context().new_page()\n       page.goto(url, wait_until=\"networkidle\", timeout=30000)\n       screenshot_bytes = page.screenshot(full_page=True)\n       text = page.inner_text(\"body\")\n       # ... extract forms, redirects, etc.\n\n   bc.stop()\n   ```\n\n   This gives full DOM access, network interception, form detection, and\n   download events. See `examples\u002F001-basic-clean.py` for the complete\n   template and `examples\u002F004`\u002F`005`\u002F`006` for scenario variants.\n\n2. **InvokeBrowser OS actions — FALLBACK ONLY.**\n\n   Use only when CDP raises a runtime error you can't work around (e.g., a\n   specific site breaks Playwright, or you need OS-level keyboard input\n   for a native dialog). Lower-level, no DOM access, no form detection,\n   no network interception. Screenshots from InvokeBrowser are full-OS\n   desktop PNGs — resize them before passing to Claude (see Section 9).\n\n### 3. Enrichment (parallel with browser work if possible)\n\n```python\nfrom enrichment import run_enrichment\n\nenrichment_result = run_enrichment(url, region=\"us-east-1\")\n```\n\nThis calls WHOIS, passive DNS, cert transparency, VT, URLhaus, MISP. Each source\ndegrades gracefully if unavailable.\n\n### 4. Populate Evidence\n\n```python\nfrom evidence_schema import Evidence, ScreenshotCapture, RedirectHop, DetectedForm\n\nevidence = Evidence(\n    target_url=url,\n    final_url=final_url_after_redirects,\n    http_status=200,\n    page_title=title,\n    screenshots=[ScreenshotCapture(...)],\n    visible_text=extracted_text,\n    forms=[DetectedForm(...)],\n    auto_downloads=[...],\n    enrichment={\n        \"whois\": enrichment_result.whois,\n        \"passive_dns\": enrichment_result.passive_dns,\n        \"cert_transparency\": enrichment_result.cert_transparency,\n        \"virustotal\": enrichment_result.virustotal,\n        \"urlhaus\": enrichment_result.urlhaus,\n        \"misp\": enrichment_result.misp,\n    },\n    run_started_at=start_iso,\n    run_completed_at=end_iso,\n)\n```\n\n### 5. Verdict (deterministic - do NOT modify)\n\n```python\nfrom verdict import synthesize_verdict\n\nbrowser_evidence_dict = evidence.to_browser_evidence_dict()\nverdict = synthesize_verdict(\n    url=url,\n    domain=domain,\n    browser_evidence=browser_evidence_dict,\n    enrichment=evidence.enrichment,\n)\n```\n\n### 6. Report\n\n```python\nfrom report import render_markdown_report, render_json_report\n\nfindings = {\n    \"url\": safe_url,\n    \"final_url\": evidence.final_url,\n    \"redirect_chain\": [r.to_url for r in evidence.redirects],\n    \"http_status\": evidence.http_status,\n    \"page_title\": evidence.page_title,\n    \"screenshots\": [],  # S3 URIs after upload\n    \"forms_detected\": browser_evidence_dict[\"forms_detected\"],\n    \"auto_downloads\": browser_evidence_dict[\"auto_downloads\"],\n    \"enrichment\": evidence.enrichment,\n    \"iocs\": extracted_iocs,\n}\n\nmd_report = render_markdown_report(safe_url, findings, verdict.to_dict(), duration)\n```\n\n### 7. Cleanup\n\nAlways call `stop_browser_session` in a finally block. If the session is already\nterminated, the API returns without error (ResourceNotFoundException is safe to ignore).\n\n### 8. Screenshot handling (MANDATORY — do not skip)\n\nBrowser screenshots at the default viewport (1456×819, full_page=True) can be\nseveral MB. Bedrock rejects over-size images with\n`API Error: 400 Could not process image` and the whole run dies. Resize before\nshowing to Claude OR keep the screenshot on disk and reason from text evidence.\n\n**Before opening a screenshot for visual reasoning, always resize it:**\n\n```python\nfrom url_analysis.evidence_store import shrink_for_claude\n\nresized_bytes = shrink_for_claude(screenshot_bytes, max_side=1024)\nwith open(\"\u002Ftmp\u002Furl1_screenshot.png\", \"wb\") as f:\n    f.write(resized_bytes)\n```\n\n`shrink_for_claude` downscales the longest side to `max_side` pixels and\nre-encodes as PNG. It's a no-op if the image is already small. Full-resolution\nbytes stay in the Evidence envelope (uploaded to S3 when the bucket is\nconfigured); the on-disk copy is only for Claude's visual input.\n\n**If Pillow\u002FPIL is unavailable in the runtime**, skip the screenshot read\nentirely — `page.title()` + `page.inner_text(\"body\")` + detected forms give\nClaude enough to reason from without the image. A missing image must NEVER\ncrash the run.\n\n## Example orchestration scripts\n\nSee `examples\u002F` for reference scripts covering the common scenarios:\n\n| # | File | Scenario | Evidence surface exercised |\n|---|------|----------|----------------------------|\n| 001 | `001-basic-clean.py` | Clean URL baseline | navigation, screenshot, forms, text |\n| 002 | `002-broken-tls.py` | TLS errors (expired, mismatch) | graceful degradation, partial evidence |\n| 003 | `003-malware-delivery.py` | Direct-file delivery (`.sh`, `.dll`) | `page.on(\"download\", ...)`, SHA-256 without persisting payload |\n| 004 | `004-phishing-form.py` | Credential harvest \u002F brand-impersonation forms | `page.evaluate()` form enumeration, detached-input detection, brand-host mismatch signals |\n| 005 | `005-redirect-chain.py` | Link shorteners, cloaking, exploit-kit hops | `page.on(\"response\")` + `page.on(\"framenavigated\")` → `RedirectHop[]`, TLD-drift + registered-domain-fanout signals |\n| 006 | `006-cloudflare-interstitial.py` | Vendor block pages (Cloudflare \u002F Google SB \u002F SmartScreen) | interstitial signature detection, Ray ID extraction, `status=partial`, **do not bypass** |\n\nPick the closest match to the URL's signal profile. You can combine\npatterns — a phishing URL that also uses redirects wants forms from\n004 + hop tracking from 005 + the `status=partial` pattern from 006\nif it gets intercepted.\n\nUse these as starting points, not as gospel. The API may drift; if the contract\nseems wrong, try small experiments and document the real shape in a comment.\n\n## Outputs\n\nStage envelope (JSON):\n\n```json\n{\n  \"artifact_id\": \"\u003CARTIFACT_ID>\",\n  \"stage\": \"url-analysis\",\n  \"stage_name\": \"url-analysis\",\n  \"timestamp\": \"\u003CISO8601 UTC>\",\n  \"status\": \"ok | partial | failed | refused\",\n  \"duration_seconds\": 42,\n  \"findings\": { ... },\n  \"verdict\": {\n    \"severity\": \"clean | suspicious | malicious\",\n    \"confidence\": 85,\n    \"category\": \"phishing | malware-delivery | c2 | scam | unclassified-risk | false-positive\",\n    \"reasoning\": \"...\",\n    \"mitre_attack\": [\"T1566.002\"],\n    \"recommended_actions\": [\"block domain at proxy\"]\n  },\n  \"tool_calls\": 8,\n  \"notes\": \"\"\n}\n```\n\n## Guardrails\n\n- **Never visit internal URLs.** Denylist is enforced before any session creation.\n- **Never submit forms.** Read-only observation of page content.\n- **Never click downloads.** Detect auto-downloads but don't interact.\n- **Session timeout enforced.** Default 300s, configurable per-tenant.\n- **Credentials scrubbed.** Any URL containing auth tokens is masked before persistence.\n- **Explicit session termination.** Always call StopBrowserSession in a finally block.\n\n## Failure handling\n\n- URL denylist match: refuse immediately, no session created\n- Session creation fails: retry 3x with backoff, then fail with \"browser unavailable\"\n- Navigation timeout: terminate session, produce partial report with evidence so far\n- Enrichment source unavailable: degrade gracefully, note missing sources\n- Session cleanup fails: log warning, AWS will auto-clean after timeout\n",{"data":40,"body":47},{"name":4,"description":6,"compatibility":41,"allowed-tools":42,"metadata":43},"requires agentcore-browser, requires url-allowlist-config","Bash Read Write WebFetch",{"stage":44,"typical_duration_seconds":45,"session_timeout_seconds":46},"url-triage",120,300,{"type":48,"children":49},"root",[50,59,66,72,86,92,97,104,189,195,200,271,280,372,380,595,601,631,636,642,830,836,913,919,1052,1058,1069,1075,1088,1096,1142,1161,1187,1193,1206,1464,1476,1481,1487,1492,2087,2093,2156,2162,2190],{"type":51,"tag":52,"props":53,"children":55},"element","h1",{"id":54},"url-analysis-skill",[56],{"type":57,"value":58},"text","url-analysis skill",{"type":51,"tag":60,"props":61,"children":63},"h2",{"id":62},"what-this-skill-does",[64],{"type":57,"value":65},"What this skill does",{"type":51,"tag":67,"props":68,"children":69},"p",{},[70],{"type":57,"value":71},"Analyze a suspicious URL using an isolated AgentCore Browser session, produce a\nstructured forensic report with verdict + confidence + IOCs + recommended actions.",{"type":51,"tag":67,"props":73,"children":74},{},[75,77,84],{"type":57,"value":76},"The browser session runs in AWS-managed infrastructure, never in our VPC. Evidence\nis captured and synthesized into a deterministic verdict via ",{"type":51,"tag":78,"props":79,"children":81},"code",{"className":80},[],[82],{"type":57,"value":83},"verdict.py",{"type":57,"value":85},".",{"type":51,"tag":60,"props":87,"children":89},{"id":88},"your-job-as-the-executing-agent",[90],{"type":57,"value":91},"Your job as the executing agent",{"type":51,"tag":67,"props":93,"children":94},{},[95],{"type":57,"value":96},"Given a URL to analyze:",{"type":51,"tag":98,"props":99,"children":101},"h3",{"id":100},"_1-pre-flight-validation",[102],{"type":57,"value":103},"1. Pre-flight validation",{"type":51,"tag":105,"props":106,"children":111},"pre",{"className":107,"code":108,"language":109,"meta":110,"style":110},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","from denylist import DenylistConfig, check_url, scrub_url_credentials\n\nsafe_url = scrub_url_credentials(url)\nresult = check_url(url)\nif not result.allowed:\n    # Return immediately with status \"refused\" and result.reason\n    # Do NOT create a browser session\n    pass\n","python","",[112],{"type":51,"tag":78,"props":113,"children":114},{"__ignoreMap":110},[115,125,135,144,153,162,171,180],{"type":51,"tag":116,"props":117,"children":119},"span",{"class":118,"line":29},"line",[120],{"type":51,"tag":116,"props":121,"children":122},{},[123],{"type":57,"value":124},"from denylist import DenylistConfig, check_url, scrub_url_credentials\n",{"type":51,"tag":116,"props":126,"children":128},{"class":118,"line":127},2,[129],{"type":51,"tag":116,"props":130,"children":132},{"emptyLinePlaceholder":131},true,[133],{"type":57,"value":134},"\n",{"type":51,"tag":116,"props":136,"children":138},{"class":118,"line":137},3,[139],{"type":51,"tag":116,"props":140,"children":141},{},[142],{"type":57,"value":143},"safe_url = scrub_url_credentials(url)\n",{"type":51,"tag":116,"props":145,"children":147},{"class":118,"line":146},4,[148],{"type":51,"tag":116,"props":149,"children":150},{},[151],{"type":57,"value":152},"result = check_url(url)\n",{"type":51,"tag":116,"props":154,"children":156},{"class":118,"line":155},5,[157],{"type":51,"tag":116,"props":158,"children":159},{},[160],{"type":57,"value":161},"if not result.allowed:\n",{"type":51,"tag":116,"props":163,"children":165},{"class":118,"line":164},6,[166],{"type":51,"tag":116,"props":167,"children":168},{},[169],{"type":57,"value":170},"    # Return immediately with status \"refused\" and result.reason\n",{"type":51,"tag":116,"props":172,"children":174},{"class":118,"line":173},7,[175],{"type":51,"tag":116,"props":176,"children":177},{},[178],{"type":57,"value":179},"    # Do NOT create a browser session\n",{"type":51,"tag":116,"props":181,"children":183},{"class":118,"line":182},8,[184],{"type":51,"tag":116,"props":185,"children":186},{},[187],{"type":57,"value":188},"    pass\n",{"type":51,"tag":98,"props":190,"children":192},{"id":191},"_2-write-and-execute-an-orchestration-script",[193],{"type":57,"value":194},"2. Write and execute an orchestration script",{"type":51,"tag":67,"props":196,"children":197},{},[198],{"type":57,"value":199},"Write a Python script that:",{"type":51,"tag":201,"props":202,"children":203},"ul",{},[204,218,223,228,233,238,258],{"type":51,"tag":205,"props":206,"children":207},"li",{},[208,210,216],{"type":57,"value":209},"Opens an AgentCore Browser session (see ",{"type":51,"tag":78,"props":211,"children":213},{"className":212},[],[214],{"type":57,"value":215},"agentcore-browser-contract.md",{"type":57,"value":217},")",{"type":51,"tag":205,"props":219,"children":220},{},[221],{"type":57,"value":222},"Navigates to the URL",{"type":51,"tag":205,"props":224,"children":225},{},[226],{"type":57,"value":227},"Captures a screenshot",{"type":51,"tag":205,"props":229,"children":230},{},[231],{"type":57,"value":232},"Extracts visible text (via screenshot + your interpretation, or via CDP)",{"type":51,"tag":205,"props":234,"children":235},{},[236],{"type":57,"value":237},"Detects any auto-downloads or forms",{"type":51,"tag":205,"props":239,"children":240},{},[241,243,249,251,257],{"type":57,"value":242},"Populates an ",{"type":51,"tag":78,"props":244,"children":246},{"className":245},[],[247],{"type":57,"value":248},"Evidence",{"type":57,"value":250}," object (see ",{"type":51,"tag":78,"props":252,"children":254},{"className":253},[],[255],{"type":57,"value":256},"evidence_schema.py",{"type":57,"value":217},{"type":51,"tag":205,"props":259,"children":260},{},[261,263,269],{"type":57,"value":262},"Stops the browser session in a ",{"type":51,"tag":78,"props":264,"children":266},{"className":265},[],[267],{"type":57,"value":268},"finally",{"type":57,"value":270}," block",{"type":51,"tag":67,"props":272,"children":273},{},[274],{"type":51,"tag":275,"props":276,"children":277},"strong",{},[278],{"type":57,"value":279},"Key rules for the orchestration script:",{"type":51,"tag":201,"props":281,"children":282},{},[283,288,299,311,338,343,348,361],{"type":51,"tag":205,"props":284,"children":285},{},[286],{"type":57,"value":287},"Language: Python 3.11+",{"type":51,"tag":205,"props":289,"children":290},{},[291,293],{"type":57,"value":292},"Use ",{"type":51,"tag":78,"props":294,"children":296},{"className":295},[],[297],{"type":57,"value":298},"boto3.client('bedrock-agentcore', region_name='us-east-1')",{"type":51,"tag":205,"props":300,"children":301},{},[302,304,309],{"type":57,"value":303},"Follow ",{"type":51,"tag":78,"props":305,"children":307},{"className":306},[],[308],{"type":57,"value":215},{"type":57,"value":310}," for exact API shapes",{"type":51,"tag":205,"props":312,"children":313},{},[314,316,322,324,330,331,337],{"type":57,"value":315},"The API provides OS-level actions (mouseClick, keyType, screenshot) NOT\nhigh-level browser automation (no ",{"type":51,"tag":78,"props":317,"children":319},{"className":318},[],[320],{"type":57,"value":321},"navigate",{"type":57,"value":323},", no ",{"type":51,"tag":78,"props":325,"children":327},{"className":326},[],[328],{"type":57,"value":329},"evaluate",{"type":57,"value":323},{"type":51,"tag":78,"props":332,"children":334},{"className":333},[],[335],{"type":57,"value":336},"getHar",{"type":57,"value":217},{"type":51,"tag":205,"props":339,"children":340},{},[341],{"type":57,"value":342},"To navigate: type the URL into the browser address bar or use Playwright via CDP",{"type":51,"tag":205,"props":344,"children":345},{},[346],{"type":57,"value":347},"Screenshots return base64-encoded PNG data",{"type":51,"tag":205,"props":349,"children":350},{},[351,353,359],{"type":57,"value":352},"Always call ",{"type":51,"tag":78,"props":354,"children":356},{"className":355},[],[357],{"type":57,"value":358},"stop_browser_session",{"type":57,"value":360}," in a finally block",{"type":51,"tag":205,"props":362,"children":363},{},[364,366],{"type":57,"value":365},"Save the script to ",{"type":51,"tag":78,"props":367,"children":369},{"className":368},[],[370],{"type":57,"value":371},"\u002Ftmp\u002Frun-artifacts\u002F{run_id}\u002Forchestration.py",{"type":51,"tag":67,"props":373,"children":374},{},[375],{"type":51,"tag":275,"props":376,"children":377},{},[378],{"type":57,"value":379},"Two approaches to browser interaction. Default to CDP. Only fall back to InvokeBrowser if CDP fails at runtime.",{"type":51,"tag":381,"props":382,"children":383},"ol",{},[384,582],{"type":51,"tag":205,"props":385,"children":386},{},[387,392,396,398,404,406,546,549,551,557,559,565,567,573,574,580],{"type":51,"tag":275,"props":388,"children":389},{},[390],{"type":57,"value":391},"Playwright via CDP WebSocket — DEFAULT. USE THIS FIRST.",{"type":51,"tag":393,"props":394,"children":395},"br",{},[],{"type":57,"value":397},"Do NOT reject this path because \"CDP requires SigV4.\" The\n",{"type":51,"tag":78,"props":399,"children":401},{"className":400},[],[402],{"type":57,"value":403},"bedrock-agentcore",{"type":57,"value":405}," SDK handles SigV4 for you. The one-line idiom is:",{"type":51,"tag":105,"props":407,"children":409},{"className":107,"code":408,"language":109,"meta":110,"style":110},"from bedrock_agentcore.tools.browser_client import BrowserClient\nfrom playwright.sync_api import sync_playwright\n\nbc = BrowserClient(region=\"us-east-1\")\nsession_id = bc.start()                     # start_browser_session\nws_url, headers = bc.generate_ws_headers()  # SigV4-signed, ready to use\n\nwith sync_playwright() as p:\n    browser = p.chromium.connect_over_cdp(ws_url, headers=headers)\n    page = browser.contexts[0].pages[0] if browser.contexts else browser.new_context().new_page()\n    page.goto(url, wait_until=\"networkidle\", timeout=30000)\n    screenshot_bytes = page.screenshot(full_page=True)\n    text = page.inner_text(\"body\")\n    # ... extract forms, redirects, etc.\n\nbc.stop()\n",[410],{"type":51,"tag":78,"props":411,"children":412},{"__ignoreMap":110},[413,421,429,436,444,452,460,467,475,484,493,502,511,520,529,537],{"type":51,"tag":116,"props":414,"children":415},{"class":118,"line":29},[416],{"type":51,"tag":116,"props":417,"children":418},{},[419],{"type":57,"value":420},"from bedrock_agentcore.tools.browser_client import BrowserClient\n",{"type":51,"tag":116,"props":422,"children":423},{"class":118,"line":127},[424],{"type":51,"tag":116,"props":425,"children":426},{},[427],{"type":57,"value":428},"from playwright.sync_api import sync_playwright\n",{"type":51,"tag":116,"props":430,"children":431},{"class":118,"line":137},[432],{"type":51,"tag":116,"props":433,"children":434},{"emptyLinePlaceholder":131},[435],{"type":57,"value":134},{"type":51,"tag":116,"props":437,"children":438},{"class":118,"line":146},[439],{"type":51,"tag":116,"props":440,"children":441},{},[442],{"type":57,"value":443},"bc = BrowserClient(region=\"us-east-1\")\n",{"type":51,"tag":116,"props":445,"children":446},{"class":118,"line":155},[447],{"type":51,"tag":116,"props":448,"children":449},{},[450],{"type":57,"value":451},"session_id = bc.start()                     # start_browser_session\n",{"type":51,"tag":116,"props":453,"children":454},{"class":118,"line":164},[455],{"type":51,"tag":116,"props":456,"children":457},{},[458],{"type":57,"value":459},"ws_url, headers = bc.generate_ws_headers()  # SigV4-signed, ready to use\n",{"type":51,"tag":116,"props":461,"children":462},{"class":118,"line":173},[463],{"type":51,"tag":116,"props":464,"children":465},{"emptyLinePlaceholder":131},[466],{"type":57,"value":134},{"type":51,"tag":116,"props":468,"children":469},{"class":118,"line":182},[470],{"type":51,"tag":116,"props":471,"children":472},{},[473],{"type":57,"value":474},"with sync_playwright() as p:\n",{"type":51,"tag":116,"props":476,"children":478},{"class":118,"line":477},9,[479],{"type":51,"tag":116,"props":480,"children":481},{},[482],{"type":57,"value":483},"    browser = p.chromium.connect_over_cdp(ws_url, headers=headers)\n",{"type":51,"tag":116,"props":485,"children":487},{"class":118,"line":486},10,[488],{"type":51,"tag":116,"props":489,"children":490},{},[491],{"type":57,"value":492},"    page = browser.contexts[0].pages[0] if browser.contexts else browser.new_context().new_page()\n",{"type":51,"tag":116,"props":494,"children":496},{"class":118,"line":495},11,[497],{"type":51,"tag":116,"props":498,"children":499},{},[500],{"type":57,"value":501},"    page.goto(url, wait_until=\"networkidle\", timeout=30000)\n",{"type":51,"tag":116,"props":503,"children":505},{"class":118,"line":504},12,[506],{"type":51,"tag":116,"props":507,"children":508},{},[509],{"type":57,"value":510},"    screenshot_bytes = page.screenshot(full_page=True)\n",{"type":51,"tag":116,"props":512,"children":514},{"class":118,"line":513},13,[515],{"type":51,"tag":116,"props":516,"children":517},{},[518],{"type":57,"value":519},"    text = page.inner_text(\"body\")\n",{"type":51,"tag":116,"props":521,"children":523},{"class":118,"line":522},14,[524],{"type":51,"tag":116,"props":525,"children":526},{},[527],{"type":57,"value":528},"    # ... extract forms, redirects, etc.\n",{"type":51,"tag":116,"props":530,"children":532},{"class":118,"line":531},15,[533],{"type":51,"tag":116,"props":534,"children":535},{"emptyLinePlaceholder":131},[536],{"type":57,"value":134},{"type":51,"tag":116,"props":538,"children":540},{"class":118,"line":539},16,[541],{"type":51,"tag":116,"props":542,"children":543},{},[544],{"type":57,"value":545},"bc.stop()\n",{"type":51,"tag":393,"props":547,"children":548},{},[],{"type":57,"value":550},"This gives full DOM access, network interception, form detection, and\ndownload events. See ",{"type":51,"tag":78,"props":552,"children":554},{"className":553},[],[555],{"type":57,"value":556},"examples\u002F001-basic-clean.py",{"type":57,"value":558}," for the complete\ntemplate and ",{"type":51,"tag":78,"props":560,"children":562},{"className":561},[],[563],{"type":57,"value":564},"examples\u002F004",{"type":57,"value":566},"\u002F",{"type":51,"tag":78,"props":568,"children":570},{"className":569},[],[571],{"type":57,"value":572},"005",{"type":57,"value":566},{"type":51,"tag":78,"props":575,"children":577},{"className":576},[],[578],{"type":57,"value":579},"006",{"type":57,"value":581}," for scenario variants.",{"type":51,"tag":205,"props":583,"children":584},{},[585,590,593],{"type":51,"tag":275,"props":586,"children":587},{},[588],{"type":57,"value":589},"InvokeBrowser OS actions — FALLBACK ONLY.",{"type":51,"tag":393,"props":591,"children":592},{},[],{"type":57,"value":594},"Use only when CDP raises a runtime error you can't work around (e.g., a\nspecific site breaks Playwright, or you need OS-level keyboard input\nfor a native dialog). Lower-level, no DOM access, no form detection,\nno network interception. Screenshots from InvokeBrowser are full-OS\ndesktop PNGs — resize them before passing to Claude (see Section 9).",{"type":51,"tag":98,"props":596,"children":598},{"id":597},"_3-enrichment-parallel-with-browser-work-if-possible",[599],{"type":57,"value":600},"3. Enrichment (parallel with browser work if possible)",{"type":51,"tag":105,"props":602,"children":604},{"className":107,"code":603,"language":109,"meta":110,"style":110},"from enrichment import run_enrichment\n\nenrichment_result = run_enrichment(url, region=\"us-east-1\")\n",[605],{"type":51,"tag":78,"props":606,"children":607},{"__ignoreMap":110},[608,616,623],{"type":51,"tag":116,"props":609,"children":610},{"class":118,"line":29},[611],{"type":51,"tag":116,"props":612,"children":613},{},[614],{"type":57,"value":615},"from enrichment import run_enrichment\n",{"type":51,"tag":116,"props":617,"children":618},{"class":118,"line":127},[619],{"type":51,"tag":116,"props":620,"children":621},{"emptyLinePlaceholder":131},[622],{"type":57,"value":134},{"type":51,"tag":116,"props":624,"children":625},{"class":118,"line":137},[626],{"type":51,"tag":116,"props":627,"children":628},{},[629],{"type":57,"value":630},"enrichment_result = run_enrichment(url, region=\"us-east-1\")\n",{"type":51,"tag":67,"props":632,"children":633},{},[634],{"type":57,"value":635},"This calls WHOIS, passive DNS, cert transparency, VT, URLhaus, MISP. Each source\ndegrades gracefully if unavailable.",{"type":51,"tag":98,"props":637,"children":639},{"id":638},"_4-populate-evidence",[640],{"type":57,"value":641},"4. Populate Evidence",{"type":51,"tag":105,"props":643,"children":645},{"className":107,"code":644,"language":109,"meta":110,"style":110},"from evidence_schema import Evidence, ScreenshotCapture, RedirectHop, DetectedForm\n\nevidence = Evidence(\n    target_url=url,\n    final_url=final_url_after_redirects,\n    http_status=200,\n    page_title=title,\n    screenshots=[ScreenshotCapture(...)],\n    visible_text=extracted_text,\n    forms=[DetectedForm(...)],\n    auto_downloads=[...],\n    enrichment={\n        \"whois\": enrichment_result.whois,\n        \"passive_dns\": enrichment_result.passive_dns,\n        \"cert_transparency\": enrichment_result.cert_transparency,\n        \"virustotal\": enrichment_result.virustotal,\n        \"urlhaus\": enrichment_result.urlhaus,\n        \"misp\": enrichment_result.misp,\n    },\n    run_started_at=start_iso,\n    run_completed_at=end_iso,\n)\n",[646],{"type":51,"tag":78,"props":647,"children":648},{"__ignoreMap":110},[649,657,664,672,680,688,696,704,712,720,728,736,744,752,760,768,776,785,794,803,812,821],{"type":51,"tag":116,"props":650,"children":651},{"class":118,"line":29},[652],{"type":51,"tag":116,"props":653,"children":654},{},[655],{"type":57,"value":656},"from evidence_schema import Evidence, ScreenshotCapture, RedirectHop, DetectedForm\n",{"type":51,"tag":116,"props":658,"children":659},{"class":118,"line":127},[660],{"type":51,"tag":116,"props":661,"children":662},{"emptyLinePlaceholder":131},[663],{"type":57,"value":134},{"type":51,"tag":116,"props":665,"children":666},{"class":118,"line":137},[667],{"type":51,"tag":116,"props":668,"children":669},{},[670],{"type":57,"value":671},"evidence = Evidence(\n",{"type":51,"tag":116,"props":673,"children":674},{"class":118,"line":146},[675],{"type":51,"tag":116,"props":676,"children":677},{},[678],{"type":57,"value":679},"    target_url=url,\n",{"type":51,"tag":116,"props":681,"children":682},{"class":118,"line":155},[683],{"type":51,"tag":116,"props":684,"children":685},{},[686],{"type":57,"value":687},"    final_url=final_url_after_redirects,\n",{"type":51,"tag":116,"props":689,"children":690},{"class":118,"line":164},[691],{"type":51,"tag":116,"props":692,"children":693},{},[694],{"type":57,"value":695},"    http_status=200,\n",{"type":51,"tag":116,"props":697,"children":698},{"class":118,"line":173},[699],{"type":51,"tag":116,"props":700,"children":701},{},[702],{"type":57,"value":703},"    page_title=title,\n",{"type":51,"tag":116,"props":705,"children":706},{"class":118,"line":182},[707],{"type":51,"tag":116,"props":708,"children":709},{},[710],{"type":57,"value":711},"    screenshots=[ScreenshotCapture(...)],\n",{"type":51,"tag":116,"props":713,"children":714},{"class":118,"line":477},[715],{"type":51,"tag":116,"props":716,"children":717},{},[718],{"type":57,"value":719},"    visible_text=extracted_text,\n",{"type":51,"tag":116,"props":721,"children":722},{"class":118,"line":486},[723],{"type":51,"tag":116,"props":724,"children":725},{},[726],{"type":57,"value":727},"    forms=[DetectedForm(...)],\n",{"type":51,"tag":116,"props":729,"children":730},{"class":118,"line":495},[731],{"type":51,"tag":116,"props":732,"children":733},{},[734],{"type":57,"value":735},"    auto_downloads=[...],\n",{"type":51,"tag":116,"props":737,"children":738},{"class":118,"line":504},[739],{"type":51,"tag":116,"props":740,"children":741},{},[742],{"type":57,"value":743},"    enrichment={\n",{"type":51,"tag":116,"props":745,"children":746},{"class":118,"line":513},[747],{"type":51,"tag":116,"props":748,"children":749},{},[750],{"type":57,"value":751},"        \"whois\": enrichment_result.whois,\n",{"type":51,"tag":116,"props":753,"children":754},{"class":118,"line":522},[755],{"type":51,"tag":116,"props":756,"children":757},{},[758],{"type":57,"value":759},"        \"passive_dns\": enrichment_result.passive_dns,\n",{"type":51,"tag":116,"props":761,"children":762},{"class":118,"line":531},[763],{"type":51,"tag":116,"props":764,"children":765},{},[766],{"type":57,"value":767},"        \"cert_transparency\": enrichment_result.cert_transparency,\n",{"type":51,"tag":116,"props":769,"children":770},{"class":118,"line":539},[771],{"type":51,"tag":116,"props":772,"children":773},{},[774],{"type":57,"value":775},"        \"virustotal\": enrichment_result.virustotal,\n",{"type":51,"tag":116,"props":777,"children":779},{"class":118,"line":778},17,[780],{"type":51,"tag":116,"props":781,"children":782},{},[783],{"type":57,"value":784},"        \"urlhaus\": enrichment_result.urlhaus,\n",{"type":51,"tag":116,"props":786,"children":788},{"class":118,"line":787},18,[789],{"type":51,"tag":116,"props":790,"children":791},{},[792],{"type":57,"value":793},"        \"misp\": enrichment_result.misp,\n",{"type":51,"tag":116,"props":795,"children":797},{"class":118,"line":796},19,[798],{"type":51,"tag":116,"props":799,"children":800},{},[801],{"type":57,"value":802},"    },\n",{"type":51,"tag":116,"props":804,"children":806},{"class":118,"line":805},20,[807],{"type":51,"tag":116,"props":808,"children":809},{},[810],{"type":57,"value":811},"    run_started_at=start_iso,\n",{"type":51,"tag":116,"props":813,"children":815},{"class":118,"line":814},21,[816],{"type":51,"tag":116,"props":817,"children":818},{},[819],{"type":57,"value":820},"    run_completed_at=end_iso,\n",{"type":51,"tag":116,"props":822,"children":824},{"class":118,"line":823},22,[825],{"type":51,"tag":116,"props":826,"children":827},{},[828],{"type":57,"value":829},")\n",{"type":51,"tag":98,"props":831,"children":833},{"id":832},"_5-verdict-deterministic-do-not-modify",[834],{"type":57,"value":835},"5. Verdict (deterministic - do NOT modify)",{"type":51,"tag":105,"props":837,"children":839},{"className":107,"code":838,"language":109,"meta":110,"style":110},"from verdict import synthesize_verdict\n\nbrowser_evidence_dict = evidence.to_browser_evidence_dict()\nverdict = synthesize_verdict(\n    url=url,\n    domain=domain,\n    browser_evidence=browser_evidence_dict,\n    enrichment=evidence.enrichment,\n)\n",[840],{"type":51,"tag":78,"props":841,"children":842},{"__ignoreMap":110},[843,851,858,866,874,882,890,898,906],{"type":51,"tag":116,"props":844,"children":845},{"class":118,"line":29},[846],{"type":51,"tag":116,"props":847,"children":848},{},[849],{"type":57,"value":850},"from verdict import synthesize_verdict\n",{"type":51,"tag":116,"props":852,"children":853},{"class":118,"line":127},[854],{"type":51,"tag":116,"props":855,"children":856},{"emptyLinePlaceholder":131},[857],{"type":57,"value":134},{"type":51,"tag":116,"props":859,"children":860},{"class":118,"line":137},[861],{"type":51,"tag":116,"props":862,"children":863},{},[864],{"type":57,"value":865},"browser_evidence_dict = evidence.to_browser_evidence_dict()\n",{"type":51,"tag":116,"props":867,"children":868},{"class":118,"line":146},[869],{"type":51,"tag":116,"props":870,"children":871},{},[872],{"type":57,"value":873},"verdict = synthesize_verdict(\n",{"type":51,"tag":116,"props":875,"children":876},{"class":118,"line":155},[877],{"type":51,"tag":116,"props":878,"children":879},{},[880],{"type":57,"value":881},"    url=url,\n",{"type":51,"tag":116,"props":883,"children":884},{"class":118,"line":164},[885],{"type":51,"tag":116,"props":886,"children":887},{},[888],{"type":57,"value":889},"    domain=domain,\n",{"type":51,"tag":116,"props":891,"children":892},{"class":118,"line":173},[893],{"type":51,"tag":116,"props":894,"children":895},{},[896],{"type":57,"value":897},"    browser_evidence=browser_evidence_dict,\n",{"type":51,"tag":116,"props":899,"children":900},{"class":118,"line":182},[901],{"type":51,"tag":116,"props":902,"children":903},{},[904],{"type":57,"value":905},"    enrichment=evidence.enrichment,\n",{"type":51,"tag":116,"props":907,"children":908},{"class":118,"line":477},[909],{"type":51,"tag":116,"props":910,"children":911},{},[912],{"type":57,"value":829},{"type":51,"tag":98,"props":914,"children":916},{"id":915},"_6-report",[917],{"type":57,"value":918},"6. Report",{"type":51,"tag":105,"props":920,"children":922},{"className":107,"code":921,"language":109,"meta":110,"style":110},"from report import render_markdown_report, render_json_report\n\nfindings = {\n    \"url\": safe_url,\n    \"final_url\": evidence.final_url,\n    \"redirect_chain\": [r.to_url for r in evidence.redirects],\n    \"http_status\": evidence.http_status,\n    \"page_title\": evidence.page_title,\n    \"screenshots\": [],  # S3 URIs after upload\n    \"forms_detected\": browser_evidence_dict[\"forms_detected\"],\n    \"auto_downloads\": browser_evidence_dict[\"auto_downloads\"],\n    \"enrichment\": evidence.enrichment,\n    \"iocs\": extracted_iocs,\n}\n\nmd_report = render_markdown_report(safe_url, findings, verdict.to_dict(), duration)\n",[923],{"type":51,"tag":78,"props":924,"children":925},{"__ignoreMap":110},[926,934,941,949,957,965,973,981,989,997,1005,1013,1021,1029,1037,1044],{"type":51,"tag":116,"props":927,"children":928},{"class":118,"line":29},[929],{"type":51,"tag":116,"props":930,"children":931},{},[932],{"type":57,"value":933},"from report import render_markdown_report, render_json_report\n",{"type":51,"tag":116,"props":935,"children":936},{"class":118,"line":127},[937],{"type":51,"tag":116,"props":938,"children":939},{"emptyLinePlaceholder":131},[940],{"type":57,"value":134},{"type":51,"tag":116,"props":942,"children":943},{"class":118,"line":137},[944],{"type":51,"tag":116,"props":945,"children":946},{},[947],{"type":57,"value":948},"findings = {\n",{"type":51,"tag":116,"props":950,"children":951},{"class":118,"line":146},[952],{"type":51,"tag":116,"props":953,"children":954},{},[955],{"type":57,"value":956},"    \"url\": safe_url,\n",{"type":51,"tag":116,"props":958,"children":959},{"class":118,"line":155},[960],{"type":51,"tag":116,"props":961,"children":962},{},[963],{"type":57,"value":964},"    \"final_url\": evidence.final_url,\n",{"type":51,"tag":116,"props":966,"children":967},{"class":118,"line":164},[968],{"type":51,"tag":116,"props":969,"children":970},{},[971],{"type":57,"value":972},"    \"redirect_chain\": [r.to_url for r in evidence.redirects],\n",{"type":51,"tag":116,"props":974,"children":975},{"class":118,"line":173},[976],{"type":51,"tag":116,"props":977,"children":978},{},[979],{"type":57,"value":980},"    \"http_status\": evidence.http_status,\n",{"type":51,"tag":116,"props":982,"children":983},{"class":118,"line":182},[984],{"type":51,"tag":116,"props":985,"children":986},{},[987],{"type":57,"value":988},"    \"page_title\": evidence.page_title,\n",{"type":51,"tag":116,"props":990,"children":991},{"class":118,"line":477},[992],{"type":51,"tag":116,"props":993,"children":994},{},[995],{"type":57,"value":996},"    \"screenshots\": [],  # S3 URIs after upload\n",{"type":51,"tag":116,"props":998,"children":999},{"class":118,"line":486},[1000],{"type":51,"tag":116,"props":1001,"children":1002},{},[1003],{"type":57,"value":1004},"    \"forms_detected\": browser_evidence_dict[\"forms_detected\"],\n",{"type":51,"tag":116,"props":1006,"children":1007},{"class":118,"line":495},[1008],{"type":51,"tag":116,"props":1009,"children":1010},{},[1011],{"type":57,"value":1012},"    \"auto_downloads\": browser_evidence_dict[\"auto_downloads\"],\n",{"type":51,"tag":116,"props":1014,"children":1015},{"class":118,"line":504},[1016],{"type":51,"tag":116,"props":1017,"children":1018},{},[1019],{"type":57,"value":1020},"    \"enrichment\": evidence.enrichment,\n",{"type":51,"tag":116,"props":1022,"children":1023},{"class":118,"line":513},[1024],{"type":51,"tag":116,"props":1025,"children":1026},{},[1027],{"type":57,"value":1028},"    \"iocs\": extracted_iocs,\n",{"type":51,"tag":116,"props":1030,"children":1031},{"class":118,"line":522},[1032],{"type":51,"tag":116,"props":1033,"children":1034},{},[1035],{"type":57,"value":1036},"}\n",{"type":51,"tag":116,"props":1038,"children":1039},{"class":118,"line":531},[1040],{"type":51,"tag":116,"props":1041,"children":1042},{"emptyLinePlaceholder":131},[1043],{"type":57,"value":134},{"type":51,"tag":116,"props":1045,"children":1046},{"class":118,"line":539},[1047],{"type":51,"tag":116,"props":1048,"children":1049},{},[1050],{"type":57,"value":1051},"md_report = render_markdown_report(safe_url, findings, verdict.to_dict(), duration)\n",{"type":51,"tag":98,"props":1053,"children":1055},{"id":1054},"_7-cleanup",[1056],{"type":57,"value":1057},"7. Cleanup",{"type":51,"tag":67,"props":1059,"children":1060},{},[1061,1062,1067],{"type":57,"value":352},{"type":51,"tag":78,"props":1063,"children":1065},{"className":1064},[],[1066],{"type":57,"value":358},{"type":57,"value":1068}," in a finally block. If the session is already\nterminated, the API returns without error (ResourceNotFoundException is safe to ignore).",{"type":51,"tag":98,"props":1070,"children":1072},{"id":1071},"_8-screenshot-handling-mandatory-do-not-skip",[1073],{"type":57,"value":1074},"8. Screenshot handling (MANDATORY — do not skip)",{"type":51,"tag":67,"props":1076,"children":1077},{},[1078,1080,1086],{"type":57,"value":1079},"Browser screenshots at the default viewport (1456×819, full_page=True) can be\nseveral MB. Bedrock rejects over-size images with\n",{"type":51,"tag":78,"props":1081,"children":1083},{"className":1082},[],[1084],{"type":57,"value":1085},"API Error: 400 Could not process image",{"type":57,"value":1087}," and the whole run dies. Resize before\nshowing to Claude OR keep the screenshot on disk and reason from text evidence.",{"type":51,"tag":67,"props":1089,"children":1090},{},[1091],{"type":51,"tag":275,"props":1092,"children":1093},{},[1094],{"type":57,"value":1095},"Before opening a screenshot for visual reasoning, always resize it:",{"type":51,"tag":105,"props":1097,"children":1099},{"className":107,"code":1098,"language":109,"meta":110,"style":110},"from url_analysis.evidence_store import shrink_for_claude\n\nresized_bytes = shrink_for_claude(screenshot_bytes, max_side=1024)\nwith open(\"\u002Ftmp\u002Furl1_screenshot.png\", \"wb\") as f:\n    f.write(resized_bytes)\n",[1100],{"type":51,"tag":78,"props":1101,"children":1102},{"__ignoreMap":110},[1103,1111,1118,1126,1134],{"type":51,"tag":116,"props":1104,"children":1105},{"class":118,"line":29},[1106],{"type":51,"tag":116,"props":1107,"children":1108},{},[1109],{"type":57,"value":1110},"from url_analysis.evidence_store import shrink_for_claude\n",{"type":51,"tag":116,"props":1112,"children":1113},{"class":118,"line":127},[1114],{"type":51,"tag":116,"props":1115,"children":1116},{"emptyLinePlaceholder":131},[1117],{"type":57,"value":134},{"type":51,"tag":116,"props":1119,"children":1120},{"class":118,"line":137},[1121],{"type":51,"tag":116,"props":1122,"children":1123},{},[1124],{"type":57,"value":1125},"resized_bytes = shrink_for_claude(screenshot_bytes, max_side=1024)\n",{"type":51,"tag":116,"props":1127,"children":1128},{"class":118,"line":146},[1129],{"type":51,"tag":116,"props":1130,"children":1131},{},[1132],{"type":57,"value":1133},"with open(\"\u002Ftmp\u002Furl1_screenshot.png\", \"wb\") as f:\n",{"type":51,"tag":116,"props":1135,"children":1136},{"class":118,"line":155},[1137],{"type":51,"tag":116,"props":1138,"children":1139},{},[1140],{"type":57,"value":1141},"    f.write(resized_bytes)\n",{"type":51,"tag":67,"props":1143,"children":1144},{},[1145,1151,1153,1159],{"type":51,"tag":78,"props":1146,"children":1148},{"className":1147},[],[1149],{"type":57,"value":1150},"shrink_for_claude",{"type":57,"value":1152}," downscales the longest side to ",{"type":51,"tag":78,"props":1154,"children":1156},{"className":1155},[],[1157],{"type":57,"value":1158},"max_side",{"type":57,"value":1160}," pixels and\nre-encodes as PNG. It's a no-op if the image is already small. Full-resolution\nbytes stay in the Evidence envelope (uploaded to S3 when the bucket is\nconfigured); the on-disk copy is only for Claude's visual input.",{"type":51,"tag":67,"props":1162,"children":1163},{},[1164,1169,1171,1177,1179,1185],{"type":51,"tag":275,"props":1165,"children":1166},{},[1167],{"type":57,"value":1168},"If Pillow\u002FPIL is unavailable in the runtime",{"type":57,"value":1170},", skip the screenshot read\nentirely — ",{"type":51,"tag":78,"props":1172,"children":1174},{"className":1173},[],[1175],{"type":57,"value":1176},"page.title()",{"type":57,"value":1178}," + ",{"type":51,"tag":78,"props":1180,"children":1182},{"className":1181},[],[1183],{"type":57,"value":1184},"page.inner_text(\"body\")",{"type":57,"value":1186}," + detected forms give\nClaude enough to reason from without the image. A missing image must NEVER\ncrash the run.",{"type":51,"tag":60,"props":1188,"children":1190},{"id":1189},"example-orchestration-scripts",[1191],{"type":57,"value":1192},"Example orchestration scripts",{"type":51,"tag":67,"props":1194,"children":1195},{},[1196,1198,1204],{"type":57,"value":1197},"See ",{"type":51,"tag":78,"props":1199,"children":1201},{"className":1200},[],[1202],{"type":57,"value":1203},"examples\u002F",{"type":57,"value":1205}," for reference scripts covering the common scenarios:",{"type":51,"tag":1207,"props":1208,"children":1209},"table",{},[1210,1239],{"type":51,"tag":1211,"props":1212,"children":1213},"thead",{},[1214],{"type":51,"tag":1215,"props":1216,"children":1217},"tr",{},[1218,1224,1229,1234],{"type":51,"tag":1219,"props":1220,"children":1221},"th",{},[1222],{"type":57,"value":1223},"#",{"type":51,"tag":1219,"props":1225,"children":1226},{},[1227],{"type":57,"value":1228},"File",{"type":51,"tag":1219,"props":1230,"children":1231},{},[1232],{"type":57,"value":1233},"Scenario",{"type":51,"tag":1219,"props":1235,"children":1236},{},[1237],{"type":57,"value":1238},"Evidence surface exercised",{"type":51,"tag":1240,"props":1241,"children":1242},"tbody",{},[1243,1271,1298,1346,1379,1426],{"type":51,"tag":1215,"props":1244,"children":1245},{},[1246,1252,1261,1266],{"type":51,"tag":1247,"props":1248,"children":1249},"td",{},[1250],{"type":57,"value":1251},"001",{"type":51,"tag":1247,"props":1253,"children":1254},{},[1255],{"type":51,"tag":78,"props":1256,"children":1258},{"className":1257},[],[1259],{"type":57,"value":1260},"001-basic-clean.py",{"type":51,"tag":1247,"props":1262,"children":1263},{},[1264],{"type":57,"value":1265},"Clean URL baseline",{"type":51,"tag":1247,"props":1267,"children":1268},{},[1269],{"type":57,"value":1270},"navigation, screenshot, forms, text",{"type":51,"tag":1215,"props":1272,"children":1273},{},[1274,1279,1288,1293],{"type":51,"tag":1247,"props":1275,"children":1276},{},[1277],{"type":57,"value":1278},"002",{"type":51,"tag":1247,"props":1280,"children":1281},{},[1282],{"type":51,"tag":78,"props":1283,"children":1285},{"className":1284},[],[1286],{"type":57,"value":1287},"002-broken-tls.py",{"type":51,"tag":1247,"props":1289,"children":1290},{},[1291],{"type":57,"value":1292},"TLS errors (expired, mismatch)",{"type":51,"tag":1247,"props":1294,"children":1295},{},[1296],{"type":57,"value":1297},"graceful degradation, partial evidence",{"type":51,"tag":1215,"props":1299,"children":1300},{},[1301,1306,1315,1335],{"type":51,"tag":1247,"props":1302,"children":1303},{},[1304],{"type":57,"value":1305},"003",{"type":51,"tag":1247,"props":1307,"children":1308},{},[1309],{"type":51,"tag":78,"props":1310,"children":1312},{"className":1311},[],[1313],{"type":57,"value":1314},"003-malware-delivery.py",{"type":51,"tag":1247,"props":1316,"children":1317},{},[1318,1320,1326,1328,1334],{"type":57,"value":1319},"Direct-file delivery (",{"type":51,"tag":78,"props":1321,"children":1323},{"className":1322},[],[1324],{"type":57,"value":1325},".sh",{"type":57,"value":1327},", ",{"type":51,"tag":78,"props":1329,"children":1331},{"className":1330},[],[1332],{"type":57,"value":1333},".dll",{"type":57,"value":217},{"type":51,"tag":1247,"props":1336,"children":1337},{},[1338,1344],{"type":51,"tag":78,"props":1339,"children":1341},{"className":1340},[],[1342],{"type":57,"value":1343},"page.on(\"download\", ...)",{"type":57,"value":1345},", SHA-256 without persisting payload",{"type":51,"tag":1215,"props":1347,"children":1348},{},[1349,1354,1363,1368],{"type":51,"tag":1247,"props":1350,"children":1351},{},[1352],{"type":57,"value":1353},"004",{"type":51,"tag":1247,"props":1355,"children":1356},{},[1357],{"type":51,"tag":78,"props":1358,"children":1360},{"className":1359},[],[1361],{"type":57,"value":1362},"004-phishing-form.py",{"type":51,"tag":1247,"props":1364,"children":1365},{},[1366],{"type":57,"value":1367},"Credential harvest \u002F brand-impersonation forms",{"type":51,"tag":1247,"props":1369,"children":1370},{},[1371,1377],{"type":51,"tag":78,"props":1372,"children":1374},{"className":1373},[],[1375],{"type":57,"value":1376},"page.evaluate()",{"type":57,"value":1378}," form enumeration, detached-input detection, brand-host mismatch signals",{"type":51,"tag":1215,"props":1380,"children":1381},{},[1382,1386,1395,1400],{"type":51,"tag":1247,"props":1383,"children":1384},{},[1385],{"type":57,"value":572},{"type":51,"tag":1247,"props":1387,"children":1388},{},[1389],{"type":51,"tag":78,"props":1390,"children":1392},{"className":1391},[],[1393],{"type":57,"value":1394},"005-redirect-chain.py",{"type":51,"tag":1247,"props":1396,"children":1397},{},[1398],{"type":57,"value":1399},"Link shorteners, cloaking, exploit-kit hops",{"type":51,"tag":1247,"props":1401,"children":1402},{},[1403,1409,1410,1416,1418,1424],{"type":51,"tag":78,"props":1404,"children":1406},{"className":1405},[],[1407],{"type":57,"value":1408},"page.on(\"response\")",{"type":57,"value":1178},{"type":51,"tag":78,"props":1411,"children":1413},{"className":1412},[],[1414],{"type":57,"value":1415},"page.on(\"framenavigated\")",{"type":57,"value":1417}," → ",{"type":51,"tag":78,"props":1419,"children":1421},{"className":1420},[],[1422],{"type":57,"value":1423},"RedirectHop[]",{"type":57,"value":1425},", TLD-drift + registered-domain-fanout signals",{"type":51,"tag":1215,"props":1427,"children":1428},{},[1429,1433,1442,1447],{"type":51,"tag":1247,"props":1430,"children":1431},{},[1432],{"type":57,"value":579},{"type":51,"tag":1247,"props":1434,"children":1435},{},[1436],{"type":51,"tag":78,"props":1437,"children":1439},{"className":1438},[],[1440],{"type":57,"value":1441},"006-cloudflare-interstitial.py",{"type":51,"tag":1247,"props":1443,"children":1444},{},[1445],{"type":57,"value":1446},"Vendor block pages (Cloudflare \u002F Google SB \u002F SmartScreen)",{"type":51,"tag":1247,"props":1448,"children":1449},{},[1450,1452,1458,1459],{"type":57,"value":1451},"interstitial signature detection, Ray ID extraction, ",{"type":51,"tag":78,"props":1453,"children":1455},{"className":1454},[],[1456],{"type":57,"value":1457},"status=partial",{"type":57,"value":1327},{"type":51,"tag":275,"props":1460,"children":1461},{},[1462],{"type":57,"value":1463},"do not bypass",{"type":51,"tag":67,"props":1465,"children":1466},{},[1467,1469,1474],{"type":57,"value":1468},"Pick the closest match to the URL's signal profile. You can combine\npatterns — a phishing URL that also uses redirects wants forms from\n004 + hop tracking from 005 + the ",{"type":51,"tag":78,"props":1470,"children":1472},{"className":1471},[],[1473],{"type":57,"value":1457},{"type":57,"value":1475}," pattern from 006\nif it gets intercepted.",{"type":51,"tag":67,"props":1477,"children":1478},{},[1479],{"type":57,"value":1480},"Use these as starting points, not as gospel. The API may drift; if the contract\nseems wrong, try small experiments and document the real shape in a comment.",{"type":51,"tag":60,"props":1482,"children":1484},{"id":1483},"outputs",[1485],{"type":57,"value":1486},"Outputs",{"type":51,"tag":67,"props":1488,"children":1489},{},[1490],{"type":57,"value":1491},"Stage envelope (JSON):",{"type":51,"tag":105,"props":1493,"children":1497},{"className":1494,"code":1495,"language":1496,"meta":110,"style":110},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"artifact_id\": \"\u003CARTIFACT_ID>\",\n  \"stage\": \"url-analysis\",\n  \"stage_name\": \"url-analysis\",\n  \"timestamp\": \"\u003CISO8601 UTC>\",\n  \"status\": \"ok | partial | failed | refused\",\n  \"duration_seconds\": 42,\n  \"findings\": { ... },\n  \"verdict\": {\n    \"severity\": \"clean | suspicious | malicious\",\n    \"confidence\": 85,\n    \"category\": \"phishing | malware-delivery | c2 | scam | unclassified-risk | false-positive\",\n    \"reasoning\": \"...\",\n    \"mitre_attack\": [\"T1566.002\"],\n    \"recommended_actions\": [\"block domain at proxy\"]\n  },\n  \"tool_calls\": 8,\n  \"notes\": \"\"\n}\n","json",[1498],{"type":51,"tag":78,"props":1499,"children":1500},{"__ignoreMap":110},[1501,1510,1554,1590,1626,1663,1700,1730,1766,1791,1830,1859,1896,1933,1976,2018,2026,2055,2080],{"type":51,"tag":116,"props":1502,"children":1503},{"class":118,"line":29},[1504],{"type":51,"tag":116,"props":1505,"children":1507},{"style":1506},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1508],{"type":57,"value":1509},"{\n",{"type":51,"tag":116,"props":1511,"children":1512},{"class":118,"line":127},[1513,1518,1524,1529,1534,1539,1545,1549],{"type":51,"tag":116,"props":1514,"children":1515},{"style":1506},[1516],{"type":57,"value":1517},"  \"",{"type":51,"tag":116,"props":1519,"children":1521},{"style":1520},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[1522],{"type":57,"value":1523},"artifact_id",{"type":51,"tag":116,"props":1525,"children":1526},{"style":1506},[1527],{"type":57,"value":1528},"\"",{"type":51,"tag":116,"props":1530,"children":1531},{"style":1506},[1532],{"type":57,"value":1533},":",{"type":51,"tag":116,"props":1535,"children":1536},{"style":1506},[1537],{"type":57,"value":1538}," \"",{"type":51,"tag":116,"props":1540,"children":1542},{"style":1541},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1543],{"type":57,"value":1544},"\u003CARTIFACT_ID>",{"type":51,"tag":116,"props":1546,"children":1547},{"style":1506},[1548],{"type":57,"value":1528},{"type":51,"tag":116,"props":1550,"children":1551},{"style":1506},[1552],{"type":57,"value":1553},",\n",{"type":51,"tag":116,"props":1555,"children":1556},{"class":118,"line":137},[1557,1561,1566,1570,1574,1578,1582,1586],{"type":51,"tag":116,"props":1558,"children":1559},{"style":1506},[1560],{"type":57,"value":1517},{"type":51,"tag":116,"props":1562,"children":1563},{"style":1520},[1564],{"type":57,"value":1565},"stage",{"type":51,"tag":116,"props":1567,"children":1568},{"style":1506},[1569],{"type":57,"value":1528},{"type":51,"tag":116,"props":1571,"children":1572},{"style":1506},[1573],{"type":57,"value":1533},{"type":51,"tag":116,"props":1575,"children":1576},{"style":1506},[1577],{"type":57,"value":1538},{"type":51,"tag":116,"props":1579,"children":1580},{"style":1541},[1581],{"type":57,"value":4},{"type":51,"tag":116,"props":1583,"children":1584},{"style":1506},[1585],{"type":57,"value":1528},{"type":51,"tag":116,"props":1587,"children":1588},{"style":1506},[1589],{"type":57,"value":1553},{"type":51,"tag":116,"props":1591,"children":1592},{"class":118,"line":146},[1593,1597,1602,1606,1610,1614,1618,1622],{"type":51,"tag":116,"props":1594,"children":1595},{"style":1506},[1596],{"type":57,"value":1517},{"type":51,"tag":116,"props":1598,"children":1599},{"style":1520},[1600],{"type":57,"value":1601},"stage_name",{"type":51,"tag":116,"props":1603,"children":1604},{"style":1506},[1605],{"type":57,"value":1528},{"type":51,"tag":116,"props":1607,"children":1608},{"style":1506},[1609],{"type":57,"value":1533},{"type":51,"tag":116,"props":1611,"children":1612},{"style":1506},[1613],{"type":57,"value":1538},{"type":51,"tag":116,"props":1615,"children":1616},{"style":1541},[1617],{"type":57,"value":4},{"type":51,"tag":116,"props":1619,"children":1620},{"style":1506},[1621],{"type":57,"value":1528},{"type":51,"tag":116,"props":1623,"children":1624},{"style":1506},[1625],{"type":57,"value":1553},{"type":51,"tag":116,"props":1627,"children":1628},{"class":118,"line":155},[1629,1633,1638,1642,1646,1650,1655,1659],{"type":51,"tag":116,"props":1630,"children":1631},{"style":1506},[1632],{"type":57,"value":1517},{"type":51,"tag":116,"props":1634,"children":1635},{"style":1520},[1636],{"type":57,"value":1637},"timestamp",{"type":51,"tag":116,"props":1639,"children":1640},{"style":1506},[1641],{"type":57,"value":1528},{"type":51,"tag":116,"props":1643,"children":1644},{"style":1506},[1645],{"type":57,"value":1533},{"type":51,"tag":116,"props":1647,"children":1648},{"style":1506},[1649],{"type":57,"value":1538},{"type":51,"tag":116,"props":1651,"children":1652},{"style":1541},[1653],{"type":57,"value":1654},"\u003CISO8601 UTC>",{"type":51,"tag":116,"props":1656,"children":1657},{"style":1506},[1658],{"type":57,"value":1528},{"type":51,"tag":116,"props":1660,"children":1661},{"style":1506},[1662],{"type":57,"value":1553},{"type":51,"tag":116,"props":1664,"children":1665},{"class":118,"line":164},[1666,1670,1675,1679,1683,1687,1692,1696],{"type":51,"tag":116,"props":1667,"children":1668},{"style":1506},[1669],{"type":57,"value":1517},{"type":51,"tag":116,"props":1671,"children":1672},{"style":1520},[1673],{"type":57,"value":1674},"status",{"type":51,"tag":116,"props":1676,"children":1677},{"style":1506},[1678],{"type":57,"value":1528},{"type":51,"tag":116,"props":1680,"children":1681},{"style":1506},[1682],{"type":57,"value":1533},{"type":51,"tag":116,"props":1684,"children":1685},{"style":1506},[1686],{"type":57,"value":1538},{"type":51,"tag":116,"props":1688,"children":1689},{"style":1541},[1690],{"type":57,"value":1691},"ok | partial | failed | refused",{"type":51,"tag":116,"props":1693,"children":1694},{"style":1506},[1695],{"type":57,"value":1528},{"type":51,"tag":116,"props":1697,"children":1698},{"style":1506},[1699],{"type":57,"value":1553},{"type":51,"tag":116,"props":1701,"children":1702},{"class":118,"line":173},[1703,1707,1712,1716,1720,1726],{"type":51,"tag":116,"props":1704,"children":1705},{"style":1506},[1706],{"type":57,"value":1517},{"type":51,"tag":116,"props":1708,"children":1709},{"style":1520},[1710],{"type":57,"value":1711},"duration_seconds",{"type":51,"tag":116,"props":1713,"children":1714},{"style":1506},[1715],{"type":57,"value":1528},{"type":51,"tag":116,"props":1717,"children":1718},{"style":1506},[1719],{"type":57,"value":1533},{"type":51,"tag":116,"props":1721,"children":1723},{"style":1722},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[1724],{"type":57,"value":1725}," 42",{"type":51,"tag":116,"props":1727,"children":1728},{"style":1506},[1729],{"type":57,"value":1553},{"type":51,"tag":116,"props":1731,"children":1732},{"class":118,"line":182},[1733,1737,1742,1746,1750,1755,1761],{"type":51,"tag":116,"props":1734,"children":1735},{"style":1506},[1736],{"type":57,"value":1517},{"type":51,"tag":116,"props":1738,"children":1739},{"style":1520},[1740],{"type":57,"value":1741},"findings",{"type":51,"tag":116,"props":1743,"children":1744},{"style":1506},[1745],{"type":57,"value":1528},{"type":51,"tag":116,"props":1747,"children":1748},{"style":1506},[1749],{"type":57,"value":1533},{"type":51,"tag":116,"props":1751,"children":1752},{"style":1506},[1753],{"type":57,"value":1754}," {",{"type":51,"tag":116,"props":1756,"children":1758},{"style":1757},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1759],{"type":57,"value":1760}," ... ",{"type":51,"tag":116,"props":1762,"children":1763},{"style":1506},[1764],{"type":57,"value":1765},"},\n",{"type":51,"tag":116,"props":1767,"children":1768},{"class":118,"line":477},[1769,1773,1778,1782,1786],{"type":51,"tag":116,"props":1770,"children":1771},{"style":1506},[1772],{"type":57,"value":1517},{"type":51,"tag":116,"props":1774,"children":1775},{"style":1520},[1776],{"type":57,"value":1777},"verdict",{"type":51,"tag":116,"props":1779,"children":1780},{"style":1506},[1781],{"type":57,"value":1528},{"type":51,"tag":116,"props":1783,"children":1784},{"style":1506},[1785],{"type":57,"value":1533},{"type":51,"tag":116,"props":1787,"children":1788},{"style":1506},[1789],{"type":57,"value":1790}," {\n",{"type":51,"tag":116,"props":1792,"children":1793},{"class":118,"line":486},[1794,1799,1805,1809,1813,1817,1822,1826],{"type":51,"tag":116,"props":1795,"children":1796},{"style":1506},[1797],{"type":57,"value":1798},"    \"",{"type":51,"tag":116,"props":1800,"children":1802},{"style":1801},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1803],{"type":57,"value":1804},"severity",{"type":51,"tag":116,"props":1806,"children":1807},{"style":1506},[1808],{"type":57,"value":1528},{"type":51,"tag":116,"props":1810,"children":1811},{"style":1506},[1812],{"type":57,"value":1533},{"type":51,"tag":116,"props":1814,"children":1815},{"style":1506},[1816],{"type":57,"value":1538},{"type":51,"tag":116,"props":1818,"children":1819},{"style":1541},[1820],{"type":57,"value":1821},"clean | suspicious | malicious",{"type":51,"tag":116,"props":1823,"children":1824},{"style":1506},[1825],{"type":57,"value":1528},{"type":51,"tag":116,"props":1827,"children":1828},{"style":1506},[1829],{"type":57,"value":1553},{"type":51,"tag":116,"props":1831,"children":1832},{"class":118,"line":495},[1833,1837,1842,1846,1850,1855],{"type":51,"tag":116,"props":1834,"children":1835},{"style":1506},[1836],{"type":57,"value":1798},{"type":51,"tag":116,"props":1838,"children":1839},{"style":1801},[1840],{"type":57,"value":1841},"confidence",{"type":51,"tag":116,"props":1843,"children":1844},{"style":1506},[1845],{"type":57,"value":1528},{"type":51,"tag":116,"props":1847,"children":1848},{"style":1506},[1849],{"type":57,"value":1533},{"type":51,"tag":116,"props":1851,"children":1852},{"style":1722},[1853],{"type":57,"value":1854}," 85",{"type":51,"tag":116,"props":1856,"children":1857},{"style":1506},[1858],{"type":57,"value":1553},{"type":51,"tag":116,"props":1860,"children":1861},{"class":118,"line":504},[1862,1866,1871,1875,1879,1883,1888,1892],{"type":51,"tag":116,"props":1863,"children":1864},{"style":1506},[1865],{"type":57,"value":1798},{"type":51,"tag":116,"props":1867,"children":1868},{"style":1801},[1869],{"type":57,"value":1870},"category",{"type":51,"tag":116,"props":1872,"children":1873},{"style":1506},[1874],{"type":57,"value":1528},{"type":51,"tag":116,"props":1876,"children":1877},{"style":1506},[1878],{"type":57,"value":1533},{"type":51,"tag":116,"props":1880,"children":1881},{"style":1506},[1882],{"type":57,"value":1538},{"type":51,"tag":116,"props":1884,"children":1885},{"style":1541},[1886],{"type":57,"value":1887},"phishing | malware-delivery | c2 | scam | unclassified-risk | false-positive",{"type":51,"tag":116,"props":1889,"children":1890},{"style":1506},[1891],{"type":57,"value":1528},{"type":51,"tag":116,"props":1893,"children":1894},{"style":1506},[1895],{"type":57,"value":1553},{"type":51,"tag":116,"props":1897,"children":1898},{"class":118,"line":513},[1899,1903,1908,1912,1916,1920,1925,1929],{"type":51,"tag":116,"props":1900,"children":1901},{"style":1506},[1902],{"type":57,"value":1798},{"type":51,"tag":116,"props":1904,"children":1905},{"style":1801},[1906],{"type":57,"value":1907},"reasoning",{"type":51,"tag":116,"props":1909,"children":1910},{"style":1506},[1911],{"type":57,"value":1528},{"type":51,"tag":116,"props":1913,"children":1914},{"style":1506},[1915],{"type":57,"value":1533},{"type":51,"tag":116,"props":1917,"children":1918},{"style":1506},[1919],{"type":57,"value":1538},{"type":51,"tag":116,"props":1921,"children":1922},{"style":1541},[1923],{"type":57,"value":1924},"...",{"type":51,"tag":116,"props":1926,"children":1927},{"style":1506},[1928],{"type":57,"value":1528},{"type":51,"tag":116,"props":1930,"children":1931},{"style":1506},[1932],{"type":57,"value":1553},{"type":51,"tag":116,"props":1934,"children":1935},{"class":118,"line":522},[1936,1940,1945,1949,1953,1958,1962,1967,1971],{"type":51,"tag":116,"props":1937,"children":1938},{"style":1506},[1939],{"type":57,"value":1798},{"type":51,"tag":116,"props":1941,"children":1942},{"style":1801},[1943],{"type":57,"value":1944},"mitre_attack",{"type":51,"tag":116,"props":1946,"children":1947},{"style":1506},[1948],{"type":57,"value":1528},{"type":51,"tag":116,"props":1950,"children":1951},{"style":1506},[1952],{"type":57,"value":1533},{"type":51,"tag":116,"props":1954,"children":1955},{"style":1506},[1956],{"type":57,"value":1957}," [",{"type":51,"tag":116,"props":1959,"children":1960},{"style":1506},[1961],{"type":57,"value":1528},{"type":51,"tag":116,"props":1963,"children":1964},{"style":1541},[1965],{"type":57,"value":1966},"T1566.002",{"type":51,"tag":116,"props":1968,"children":1969},{"style":1506},[1970],{"type":57,"value":1528},{"type":51,"tag":116,"props":1972,"children":1973},{"style":1506},[1974],{"type":57,"value":1975},"],\n",{"type":51,"tag":116,"props":1977,"children":1978},{"class":118,"line":531},[1979,1983,1988,1992,1996,2000,2004,2009,2013],{"type":51,"tag":116,"props":1980,"children":1981},{"style":1506},[1982],{"type":57,"value":1798},{"type":51,"tag":116,"props":1984,"children":1985},{"style":1801},[1986],{"type":57,"value":1987},"recommended_actions",{"type":51,"tag":116,"props":1989,"children":1990},{"style":1506},[1991],{"type":57,"value":1528},{"type":51,"tag":116,"props":1993,"children":1994},{"style":1506},[1995],{"type":57,"value":1533},{"type":51,"tag":116,"props":1997,"children":1998},{"style":1506},[1999],{"type":57,"value":1957},{"type":51,"tag":116,"props":2001,"children":2002},{"style":1506},[2003],{"type":57,"value":1528},{"type":51,"tag":116,"props":2005,"children":2006},{"style":1541},[2007],{"type":57,"value":2008},"block domain at proxy",{"type":51,"tag":116,"props":2010,"children":2011},{"style":1506},[2012],{"type":57,"value":1528},{"type":51,"tag":116,"props":2014,"children":2015},{"style":1506},[2016],{"type":57,"value":2017},"]\n",{"type":51,"tag":116,"props":2019,"children":2020},{"class":118,"line":539},[2021],{"type":51,"tag":116,"props":2022,"children":2023},{"style":1506},[2024],{"type":57,"value":2025},"  },\n",{"type":51,"tag":116,"props":2027,"children":2028},{"class":118,"line":778},[2029,2033,2038,2042,2046,2051],{"type":51,"tag":116,"props":2030,"children":2031},{"style":1506},[2032],{"type":57,"value":1517},{"type":51,"tag":116,"props":2034,"children":2035},{"style":1520},[2036],{"type":57,"value":2037},"tool_calls",{"type":51,"tag":116,"props":2039,"children":2040},{"style":1506},[2041],{"type":57,"value":1528},{"type":51,"tag":116,"props":2043,"children":2044},{"style":1506},[2045],{"type":57,"value":1533},{"type":51,"tag":116,"props":2047,"children":2048},{"style":1722},[2049],{"type":57,"value":2050}," 8",{"type":51,"tag":116,"props":2052,"children":2053},{"style":1506},[2054],{"type":57,"value":1553},{"type":51,"tag":116,"props":2056,"children":2057},{"class":118,"line":787},[2058,2062,2067,2071,2075],{"type":51,"tag":116,"props":2059,"children":2060},{"style":1506},[2061],{"type":57,"value":1517},{"type":51,"tag":116,"props":2063,"children":2064},{"style":1520},[2065],{"type":57,"value":2066},"notes",{"type":51,"tag":116,"props":2068,"children":2069},{"style":1506},[2070],{"type":57,"value":1528},{"type":51,"tag":116,"props":2072,"children":2073},{"style":1506},[2074],{"type":57,"value":1533},{"type":51,"tag":116,"props":2076,"children":2077},{"style":1506},[2078],{"type":57,"value":2079}," \"\"\n",{"type":51,"tag":116,"props":2081,"children":2082},{"class":118,"line":796},[2083],{"type":51,"tag":116,"props":2084,"children":2085},{"style":1506},[2086],{"type":57,"value":1036},{"type":51,"tag":60,"props":2088,"children":2090},{"id":2089},"guardrails",[2091],{"type":57,"value":2092},"Guardrails",{"type":51,"tag":201,"props":2094,"children":2095},{},[2096,2106,2116,2126,2136,2146],{"type":51,"tag":205,"props":2097,"children":2098},{},[2099,2104],{"type":51,"tag":275,"props":2100,"children":2101},{},[2102],{"type":57,"value":2103},"Never visit internal URLs.",{"type":57,"value":2105}," Denylist is enforced before any session creation.",{"type":51,"tag":205,"props":2107,"children":2108},{},[2109,2114],{"type":51,"tag":275,"props":2110,"children":2111},{},[2112],{"type":57,"value":2113},"Never submit forms.",{"type":57,"value":2115}," Read-only observation of page content.",{"type":51,"tag":205,"props":2117,"children":2118},{},[2119,2124],{"type":51,"tag":275,"props":2120,"children":2121},{},[2122],{"type":57,"value":2123},"Never click downloads.",{"type":57,"value":2125}," Detect auto-downloads but don't interact.",{"type":51,"tag":205,"props":2127,"children":2128},{},[2129,2134],{"type":51,"tag":275,"props":2130,"children":2131},{},[2132],{"type":57,"value":2133},"Session timeout enforced.",{"type":57,"value":2135}," Default 300s, configurable per-tenant.",{"type":51,"tag":205,"props":2137,"children":2138},{},[2139,2144],{"type":51,"tag":275,"props":2140,"children":2141},{},[2142],{"type":57,"value":2143},"Credentials scrubbed.",{"type":57,"value":2145}," Any URL containing auth tokens is masked before persistence.",{"type":51,"tag":205,"props":2147,"children":2148},{},[2149,2154],{"type":51,"tag":275,"props":2150,"children":2151},{},[2152],{"type":57,"value":2153},"Explicit session termination.",{"type":57,"value":2155}," Always call StopBrowserSession in a finally block.",{"type":51,"tag":60,"props":2157,"children":2159},{"id":2158},"failure-handling",[2160],{"type":57,"value":2161},"Failure handling",{"type":51,"tag":201,"props":2163,"children":2164},{},[2165,2170,2175,2180,2185],{"type":51,"tag":205,"props":2166,"children":2167},{},[2168],{"type":57,"value":2169},"URL denylist match: refuse immediately, no session created",{"type":51,"tag":205,"props":2171,"children":2172},{},[2173],{"type":57,"value":2174},"Session creation fails: retry 3x with backoff, then fail with \"browser unavailable\"",{"type":51,"tag":205,"props":2176,"children":2177},{},[2178],{"type":57,"value":2179},"Navigation timeout: terminate session, produce partial report with evidence so far",{"type":51,"tag":205,"props":2181,"children":2182},{},[2183],{"type":57,"value":2184},"Enrichment source unavailable: degrade gracefully, note missing sources",{"type":51,"tag":205,"props":2186,"children":2187},{},[2188],{"type":57,"value":2189},"Session cleanup fails: log warning, AWS will auto-clean after timeout",{"type":51,"tag":2191,"props":2192,"children":2193},"style",{},[2194],{"type":57,"value":2195},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":2197,"total":2375},[2198,2217,2238,2248,2261,2274,2284,2294,2315,2330,2345,2360],{"slug":2199,"name":2199,"fn":2200,"description":2201,"org":2202,"tags":2203,"stars":2214,"repoUrl":2215,"updatedAt":2216},"agentcore-investigation","investigate Bedrock AgentCore runtime sessions","Investigate Bedrock AgentCore runtime sessions via CloudWatch Logs Insights — resolve session\u002Ftrace IDs, query OTEL spans, filter noise, build timelines. Use when debugging AgentCore agent sessions, tracing tool calls, or analyzing latency.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2204,2207,2208,2211],{"name":2205,"slug":2206,"type":16},"AWS","aws",{"name":24,"slug":25,"type":16},{"name":2209,"slug":2210,"type":16},"Logs","logs",{"name":2212,"slug":2213,"type":16},"Observability","observability",9427,"https:\u002F\u002Fgithub.com\u002Fawslabs\u002Fmcp","2026-07-12T08:37:22.601527",{"slug":2218,"name":2219,"fn":2220,"description":2221,"org":2222,"tags":2223,"stars":2214,"repoUrl":2215,"updatedAt":2237},"amazon-aurora-dsql","amazon aurora dsql","build applications with Aurora DSQL","Build with Aurora DSQL — manage schemas, execute queries, handle migrations, diagnose query plans, load data, and develop applications with a serverless, distributed SQL database. Covers IAM auth, multi-tenant patterns, MySQL-to-DSQL and PostgreSQL-to-DSQL schema conversion, FK replacement code generation, OCC retry patterns, ORM migration (Django\u002FHibernate\u002FRails), DDL operations, query plan explainability, SQL compatibility validation, and bulk data loading. Triggers on phrases like: DSQL, Aurora DSQL, create DSQL table, DSQL schema, migrate to DSQL, distributed SQL database, serverless PostgreSQL-compatible database, DSQL query plan, DSQL EXPLAIN ANALYZE, why is my DSQL query slow, DSQL foreign key, DSQL OCC retry, DSQL multi-region, load into DSQL, load CSV into DSQL, bulk load DSQL, aurora-dsql-loader.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2224,2227,2228,2231,2234],{"name":2225,"slug":2226,"type":16},"Aurora","aurora",{"name":2205,"slug":2206,"type":16},{"name":2229,"slug":2230,"type":16},"Database","database",{"name":2232,"slug":2233,"type":16},"Serverless","serverless",{"name":2235,"slug":2236,"type":16},"SQL","sql","2026-08-04T05:35:10.770847",{"slug":2239,"name":2240,"fn":2220,"description":2221,"org":2241,"tags":2242,"stars":2214,"repoUrl":2215,"updatedAt":2247},"aurora-dsql","aurora dsql",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2243,2244,2245,2246],{"name":2205,"slug":2206,"type":16},{"name":2229,"slug":2230,"type":16},{"name":2232,"slug":2233,"type":16},{"name":2235,"slug":2236,"type":16},"2026-08-04T05:35:05.694395",{"slug":2249,"name":2250,"fn":2220,"description":2221,"org":2251,"tags":2252,"stars":2214,"repoUrl":2215,"updatedAt":2260},"aws-dsql","aws dsql",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2253,2254,2255,2258,2259],{"name":2205,"slug":2206,"type":16},{"name":2229,"slug":2230,"type":16},{"name":2256,"slug":2257,"type":16},"Migration","migration",{"name":2232,"slug":2233,"type":16},{"name":2235,"slug":2236,"type":16},"2026-08-04T05:35:08.749669",{"slug":2262,"name":2263,"fn":2220,"description":2221,"org":2264,"tags":2265,"stars":2214,"repoUrl":2215,"updatedAt":2273},"distributed-postgres","distributed postgres",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2266,2267,2268,2271,2272],{"name":2205,"slug":2206,"type":16},{"name":2229,"slug":2230,"type":16},{"name":2269,"slug":2270,"type":16},"PostgreSQL","postgresql",{"name":2232,"slug":2233,"type":16},{"name":2235,"slug":2236,"type":16},"2026-08-04T05:35:06.713102",{"slug":2275,"name":2276,"fn":2220,"description":2221,"org":2277,"tags":2278,"stars":2214,"repoUrl":2215,"updatedAt":2283},"distributed-sql","distributed sql",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2279,2280,2281,2282],{"name":2205,"slug":2206,"type":16},{"name":2229,"slug":2230,"type":16},{"name":2232,"slug":2233,"type":16},{"name":2235,"slug":2236,"type":16},"2026-08-04T05:35:10.086942",{"slug":2285,"name":2285,"fn":2220,"description":2221,"org":2286,"tags":2287,"stars":2214,"repoUrl":2215,"updatedAt":2293},"dsql",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2288,2289,2290,2291,2292],{"name":2205,"slug":2206,"type":16},{"name":2229,"slug":2230,"type":16},{"name":2256,"slug":2257,"type":16},{"name":2232,"slug":2233,"type":16},{"name":2235,"slug":2236,"type":16},"2026-08-04T05:35:07.751779",{"slug":2295,"name":2295,"fn":2296,"description":2297,"org":2298,"tags":2299,"stars":2312,"repoUrl":2313,"updatedAt":2314},"cost-efficiency-analyzer","analyze cost efficiency and expenses","Analyzes cost structure, cost efficiency, and expense management from P&L data. Use when the user asks about costs, expenses, COGS, operating expenses, cost ratios, cost control, spending efficiency, margin compression from cost side, or wants to understand where money is going. Also use for \"are we spending too much\", \"cost breakdown\", \"expense analysis\", or \"how efficient are our operations\". NOT for revenue or top-line analysis.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2300,2303,2306,2309],{"name":2301,"slug":2302,"type":16},"Accounting","accounting",{"name":2304,"slug":2305,"type":16},"Analytics","analytics",{"name":2307,"slug":2308,"type":16},"Cost Optimization","cost-optimization",{"name":2310,"slug":2311,"type":16},"Finance","finance",3176,"https:\u002F\u002Fgithub.com\u002Fawslabs\u002Fagentcore-samples","2026-07-12T08:40:03.29555",{"slug":2316,"name":2316,"fn":2317,"description":2318,"org":2319,"tags":2320,"stars":2312,"repoUrl":2313,"updatedAt":2329},"executive-financial-briefing","generate executive financial briefings","Generates a concise executive-level financial briefing or summary suitable for a CEO, CFO, or board presentation. Use when the user asks for a summary, briefing, executive summary, board update, financial overview, financial health check, or \"how is the business doing\". Covers the full P&L picture in one page. Also use for \"give me the highlights\", \"what do I need to know\", or \"quick financial update\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2321,2322,2323,2326],{"name":2205,"slug":2206,"type":16},{"name":2310,"slug":2311,"type":16},{"name":2324,"slug":2325,"type":16},"Management","management",{"name":2327,"slug":2328,"type":16},"Reporting","reporting","2026-07-12T08:40:02.066471",{"slug":2331,"name":2331,"fn":2332,"description":2333,"org":2334,"tags":2335,"stars":2312,"repoUrl":2313,"updatedAt":2344},"multi-quarter-trend-analysis","analyze multi-quarter financial trends","Analyzes financial trends across multiple quarters by comparing P&L metrics over time. Use when the user wants to see trends, patterns, trajectories, or directional movement across 3 or more quarters. Also use for \"how are we trending\", \"show me the trend\", \"track performance over time\", \"quarter over quarter comparison across all quarters\", or any multi-period longitudinal analysis.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2336,2337,2338,2341],{"name":2304,"slug":2305,"type":16},{"name":2310,"slug":2311,"type":16},{"name":2339,"slug":2340,"type":16},"Financial Statements","financial-statements",{"name":2342,"slug":2343,"type":16},"Variance Analysis","variance-analysis","2026-07-12T08:40:00.79141",{"slug":2346,"name":2346,"fn":2347,"description":2348,"org":2349,"tags":2350,"stars":2312,"repoUrl":2313,"updatedAt":2359},"pdf","process and manipulate PDF documents","Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text\u002Ftables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting\u002Fdecrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2351,2354,2357],{"name":2352,"slug":2353,"type":16},"Automation","automation",{"name":2355,"slug":2356,"type":16},"Documents","documents",{"name":2358,"slug":2346,"type":16},"PDF","2026-07-12T08:41:44.135656",{"slug":2361,"name":2361,"fn":2362,"description":2363,"org":2364,"tags":2365,"stars":2312,"repoUrl":2313,"updatedAt":2374},"quarterly-kpi-calculator","calculate quarterly financial KPIs","Calculates quarterly financial KPIs from P&L data. P&L figures can be provided directly by the user or fetched from the financial data MCP server. Use when the user wants KPI calculations such as Gross Margin %, EBITDA Margin %, Operating Expense Ratio, or Revenue Growth % QoQ. Also use for quarterly performance review, P&L analysis, or interpreting financial ratios against benchmarks.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2366,2367,2370,2371],{"name":2301,"slug":2302,"type":16},{"name":2368,"slug":2369,"type":16},"Data Analysis","data-analysis",{"name":2310,"slug":2311,"type":16},{"name":2372,"slug":2373,"type":16},"KPI","kpi","2026-07-12T08:39:59.54971",155,{"items":2377,"total":155},[2378,2389,2404,2422,2439],{"slug":2379,"name":2379,"fn":2380,"description":2381,"org":2382,"tags":2383,"stars":29,"repoUrl":30,"updatedAt":2388},"stage-1-triage","perform initial malware sample triage","Lightweight fingerprinting of a malware sample — hashes, file type, entropy, strings, candidate IOCs. Use this skill whenever you start a 7-stage malware analysis pipeline, need a quick file identification before deeper analysis, or want to check a sample against known-hash databases before committing compute. This is always the first stage and must run before Stage 2 (OSINT), Stage 3 (static), or Stage 4 (dynamic).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2384,2385,2386,2387],{"name":21,"slug":22,"type":16},{"name":24,"slug":25,"type":16},{"name":14,"slug":15,"type":16},{"name":18,"slug":19,"type":16},"2026-08-04T05:58:50.852669",{"slug":2390,"name":2390,"fn":2391,"description":2392,"org":2393,"tags":2394,"stars":29,"repoUrl":30,"updatedAt":2403},"stage-5-correlation","correlate dynamic findings with threat intelligence","Cross-reference dynamic findings against threat intel (MISP, VT, web reporting) + MITRE ATT&CK to derive family + TTPs + campaign linkage. Use this skill whenever you have Stage 4 dynamic observations (C2 IPs, mutexes, injection targets) and want to link them to known campaigns, confirm Stage 2's hypothesis, or produce MITRE TTP IDs with specific per-stage evidence. Runs after Stage 4, or after Stage 3 if Stage 4 was unavailable — can work with partial data. Skip on Stage 2 short-circuit.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2395,2398,2399,2400],{"name":2396,"slug":2397,"type":16},"Audit","audit",{"name":21,"slug":22,"type":16},{"name":14,"slug":15,"type":16},{"name":2401,"slug":2402,"type":16},"Threat Modeling","threat-modeling","2026-08-04T05:59:09.270695",{"slug":2405,"name":2405,"fn":2406,"description":2407,"org":2408,"tags":2409,"stars":29,"repoUrl":30,"updatedAt":2421},"stage-6-verdict","synthesize security verdicts and recommended actions","Synthesize severity (malicious\u002Fsuspicious\u002Fbenign), confidence (high\u002Fmedium\u002Flow), STIX 2.1 IOC bundle, CSV feed, and concrete recommended actions (host isolation, token revocation, perimeter blocks, fleet-wide hunt queries) from all prior stage envelopes. Use this skill whenever earlier stages have produced findings (or on a Stage 2 short-circuit to benign) and you need a machine-readable verdict that IR teams can ingest into Splunk\u002FElastic\u002FSentinel or block at the perimeter. Always runs — even short-circuits produce a minimal clean-sample verdict. Runs after all other analysis stages; Stage 7 depends on this output.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2410,2411,2414,2417,2420],{"name":2396,"slug":2397,"type":16},{"name":2412,"slug":2413,"type":16},"Compliance","compliance",{"name":2415,"slug":2416,"type":16},"Incident Response","incident-response",{"name":2418,"slug":2419,"type":16},"Policy","policy",{"name":14,"slug":15,"type":16},"2026-08-04T05:59:08.753662",{"slug":2423,"name":2423,"fn":2424,"description":2425,"org":2426,"tags":2427,"stars":29,"repoUrl":30,"updatedAt":2438},"stage-7-report","generate security incident reports and IOC feeds","Produce the final deliverables — executive summary (for leadership), structured technical report (for IR), STIX 2.1 + CSV IOC feeds (for SIEM\u002Ffirewall), copy-pasteable Splunk\u002FElastic\u002FSentinel hunt queries — upload them all to S3 with presigned URLs, and post a single consolidated comment linking everything. Use this skill whenever the pipeline has reached a verdict (Stage 6 done) and the issue needs a handoff-ready set of artifacts for IR follow-up. Always the last stage; runs on benign short-circuits too (produces a concise clean-sample report).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2428,2429,2430,2433,2434,2435],{"name":2396,"slug":2397,"type":16},{"name":2412,"slug":2413,"type":16},{"name":2431,"slug":2432,"type":16},"Elastic","elastic",{"name":2327,"slug":2328,"type":16},{"name":14,"slug":15,"type":16},{"name":2436,"slug":2437,"type":16},"Splunk","splunk","2026-08-04T05:59:08.226613",{"slug":4,"name":4,"fn":5,"description":6,"org":2440,"tags":2441,"stars":29,"repoUrl":30,"updatedAt":31},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2442,2443,2444,2445,2446],{"name":27,"slug":28,"type":16},{"name":21,"slug":22,"type":16},{"name":24,"slug":25,"type":16},{"name":14,"slug":15,"type":16},{"name":18,"slug":19,"type":16}]