T09 · Insecure Skill Coding Practices
- Location
html-mark.js:697- Finding
Persistent Plaintext Storage of Annotated DOM Content and Input Values
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This annotation skill appears legitimate, but it can be injected into arbitrary live sites and stores or exports captured page content without enough privacy guardrails.
Use this mainly on local prototypes or pages you own or are authorized to review. Avoid running the bookmarklet on authenticated, production, financial, healthcare, admin, or third-party pages, and review/redact clipboard exports before pasting them into AI tools or shared systems.
html-mark.js:697Persistent Plaintext Storage of Annotated DOM Content and Input Values
Referenced artifact was not completely inspected
A single-file self-contained runtime (`html-mark.js`). After injection it gives the page:
Referenced artifact was not completely inspected
A single-file self-contained runtime (`html-mark.js`). After injection it gives the page:
Referenced artifact was not completely inspected
A single-file self-contained runtime (`html-mark.js`). After injection it gives the page:
Referenced artifact was not completely inspected
A single-file self-contained runtime (`html-mark.js`). After injection it gives the page:
The skill instructs reading a file from the agent's configuration directory under ~/.claude/skills, which is a sensitive local path outside the user's project workspace. Guidance that encourages access to agent config directories can expose secrets, other installed skills, or private local assets if reused or generalized by an agent.
Default action: inline the runtime as a <script> block before the target HTML's </body> (keeps the HTML self-contained so the user can email or AirDrop it).
cat ~/.claude/skills/html-mark/html-mark.js
Then use Edit to wrap the runtime in <script>…</script> and insert before </body>. Do not trim anything — the script is fully self-contained (CSS is inlined, DOM is self-injected, all class names use the .mm-* prefix for isolation).
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
sed -i '' '/<\/body>/i\
<script>\
'"$(cat ~/.claude/skills/html-mark/html-mark.js)"'\
</script>
' /tmp/mm-test.html
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
sed -i '' '/<\/body>/i\
<script>\
'"$(cat ~/.claude/skills/html-mark/html-mark.js)"'\
</script>
' /tmp/mm-test.html
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
# HTML Mark
> **Click-to-annotate overlay for any HTML page.** Drop coral-gradient pins on any element, write feedback inline, copy out as Markdown / Plain / JSON — or as a **For AI** handoff that pastes straight into Claude Code for one-pass fixes.
   
The skill persists annotations in localStorage and promotes exporting notes plus HTML snapshots for later AI-assisted processing. This creates retention of potentially sensitive review data in the browser and increases exposure if the device, browser profile, or shared machine is accessed by others.
name: html-mark
version: 1.2.0
title: HTML Mark — Click-to-annotate overlay for HTML prototypes
description: Drop coral-gradient pins on any HTML page, write feedback in an inline glass note popup, copy out as Markdown / Plain / JSON — or a For-AI format (unique CSS selector + HTML snapshot per pin) built to paste into Claude Code for one-pass fixes. Pins anchor to their elements and persist in localStorage. Glass-morphism aesthetic, keyboard-friendly, self-contained single file.
author: xuxinmaxen
type: agent
category: productivity
The 'For AI' export is designed to collect a unique selector plus an HTML snapshot from reviewed elements and paste that data into an external AI workflow. On arbitrary or live pages, this can leak proprietary markup, user-visible sensitive information, or third-party content beyond the original browsing context.
The skill explicitly instructs users to generate bookmarklets or hosted loaders that inject code into arbitrary live websites, including competitor sites. That creates a cross-site script-injection workflow and normalizes running unvetted code in sensitive browsing contexts, which can expose page content, session-visible data, and user interactions to the injected runtime.
The bookmarklet guidance targets live and competitor pages without any warning about consent, terms-of-service, privacy, or handling of visible data. In context, this omission increases the likelihood of unsafe deployment on third-party sites and downstream disclosure of captured content.
The documented workflow combines injection into arbitrary live pages with copy/export features, creating a practical path to extract semantically rich page content into external tools. Even if intended for annotation, this materially increases the risk of proprietary or sensitive third-party data leakage.
The tool persists annotations in localStorage, including freeform notes plus page-derived selector, text, path, and HTML snapshot data. On sensitive or shared systems, this can retain confidential page content beyond the session and expose it to other scripts running on the same origin, later users of the browser profile, or accidental recovery after logout. The skill's purpose of annotating arbitrary HTML pages makes this more dangerous because users may run it on internal prototypes or authenticated pages containing sensitive business or user data.
The export feature copies page-derived content including element text, CSS selectors, and in 'For AI' / JSON modes a snapshot of the target element's outerHTML. If a user annotates pages containing secrets, personal data, tokens, hidden values, or internal-only content, this data can be silently packaged into clipboard output and then pasted into another tool or LLM, causing unintended disclosure. The skill context increases risk because it is explicitly designed to collect exact DOM snapshots for handoff to coding agents.
The hosted bookmarklet variant instructs users to inject a remote script into whatever page they visit, which gives that external code the same DOM access as the bookmarklet itself. Without an explicit warning about trust, supply-chain risk, and privacy implications, users may unknowingly execute modified or malicious code from a CDN, fork, or mutable branch such as @main.
The advertised AI-oriented workflow encourages packaging DOM selectors and HTML snapshots for pasting into a coding agent. In this context, the feature increases the likelihood that sensitive on-page text, user-entered values, or embedded tokens are transferred into a third-party natural-language channel outside the application's trust boundary.
The skill persistently stores annotation metadata in localStorage, including captured element text, CSS paths, relative coordinates, and HTML snapshots. Because those snapshots can include user-visible content or form-derived text and localStorage is readable by any script running on the same origin, this creates an unintended local data retention and disclosure risk even if the tool's purpose is legitimate.
The element description logic explicitly captures input placeholders or current input values as annotation text. If a user clicks a populated form control, secrets or personal data can be stored and later exported, making this more dangerous than generic page-text capture because it can directly expose credentials, PII, or other entered data.
Storing outerHTML for clicked elements can capture inline text, hidden data attributes, prefilled form values, and other sensitive DOM content that the user may not realize is being retained. Because this snapshot is later persisted and exportable, it creates a direct mechanism for leaking confidential page state to other people, systems, or AI tools.
The export feature copies all collected annotations, selectors, text, and possibly HTML snapshots directly to the clipboard without warning that sensitive page content may be included. Clipboard contents are easy to paste into external tools or AI systems, so this creates a realistic exfiltration path for confidential data captured during annotation.
The 'For AI' export specifically instructs users to send exact selectors and HTML snapshots to a coding agent, normalizing disclosure of captured page data to an external processor. In the skill context, this is more dangerous because AI handoff is a core feature rather than an incidental side effect, so users are steered toward a potentially unsafe sharing pattern.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
cat > /tmp/mm-test.html <<'EOF'
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.
permit persons to whom the Software is furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
Declared permissions with no matching code capability may indicate removed functionality or pre-staging for future abuse.