Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add rules/atlassian/forge-skills/xssgit clone --depth 1 https://github.com/atlassian/forge-skillsWhat it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5 | $0.00012 | $0.01134 |
| Opus 5 | $0.00006 | $0.00567 |
| Sonnet 5 | $0.00002 | $0.00227 |
| Haiku 4.5 | $0.00001 | $0.00113 |
Grade A, and why
xss scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 2d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 150 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Context
- Forge Custom UI apps run in iframes and can be vulnerable to XSS when
unsafe-inlineis enabled in the manifest CSP and user content is rendered without sanitization. - Related CWE: CWE-79 (Cross-Site Scripting).
- Only ~23% of Forge apps (473/2033) enable
unsafe-inline; focus review on these. - Reference: Internal Forge VULN Guide to XSS.
Prerequisites for XSS in Forge
unsafe-inlineenabled in manifest:
permissions:
content:
scripts:
- 'unsafe-inline'
- User-controlled content rendered without sanitization.
Scope & Signals
- Primary sink:
dangerouslySetInnerHTMLin React components. - Secondary sinks: Direct DOM manipulation (
innerHTML,outerHTML,insertAdjacentHTML). - Sources: Data from Atlassian APIs, storage, web triggers, user input forms.
- Note: Some Atlassian API responses are already HTML-escaped (e.g., storage API).
Vulnerable Patterns
// VULNERABLE - dangerouslySetInnerHTML with user content
function CommentDisplay({ comment }) {
return (
<div dangerouslySetInnerHTML={{ __html: comment.body }} />
);
}
// VULNERABLE - Direct HTML from API response
function RenderContent({ content }) {
// If content comes from untrusted source
return <div dangerouslySetInnerHTML={{ __html: content }} />;
}
// VULNERABLE - String replacement doesn't sanitize
const HtmlTag = (text) => {
let temp = `<span>${text.replaceAll('\\n', '</br>')}</span>`;
return <div dangerouslySetInnerHTML={{ __html: temp }} />;
};
// VULNERABLE - Direct DOM manipulation
document.getElementById('output').innerHTML = userData;
Secure Patterns
// SECURE - Use DOMPurify to sanitize
import DOMPurify from 'dompurify';
function SafeHtmlDisplay({ htmlContent }) {
const sanitized = DOMPurify.sanitize(htmlContent);
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
}
// SECURE - Use React's default escaping (no dangerouslySetInnerHTML)
function CommentDisplay({ comment }) {
return <div>{comment.body}</div>; // React escapes by default
}
// SECURE - Use text content instead of HTML
function TextDisplay({ text }) {
return <pre>{text}</pre>;
}
// SECURE - Allowlist-based HTML rendering
import { sanitize } from 'isomorphic-dompurify';
function RichTextDisplay({ content }) {
const clean = sanitize(content, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p', 'br'],
ALLOWED_ATTR: []
});
return <div dangerouslySetInnerHTML={{ __html: clean }} />;
}
Detection Checklist
- Check manifest for
unsafe-inlineinpermissions.content.scripts. - If enabled, search for
dangerouslySetInnerHTMLusage. - Trace the HTML content source - is it user-controlled?
- Check for DOMPurify or similar sanitization before rendering.
- Look for direct DOM manipulation (
innerHTML,outerHTML). - Review library code separately from app code (reduce false positives).
Always verify by testing - don't assume sanitization:
// Test input
<p><script>console.log("XSS")</script></p>
// If sanitized, you'll see escaped output:
<p><script>...
False Positive Indicators
- Static/constant HTML strings (not user-controlled).
- CSS-in-JS libraries (styled-components) using dangerouslySetInnerHTML for styles.
- Content from Atlassian endpoints that sanitize (verify with testing).
- Multiple-choice or enum-only user input (no free text).
Severity Assessment
| Factor | Higher Severity | Lower Severity |
|---|---|---|
| Content source | Direct user input | Indirect/transformed |
| Persistence | Stored XSS | Reflected XSS |
| Target | Other users | Same user only |
| Context | Admin panels | Low-privilege areas |
PoC / Test Leads
- Input:
<img src=x onerror=alert(1)> - Input:
<script>console.log('XSS')</script> - Input:
<svg onload=alert(1)> - Test in Jira issue fields, Confluence page content, comments, custom fields.
- Verify if XSS triggers when another user views the content.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 2d ago First seen · 150 lines · 12 tokens per session scan A e0f3b80fc80d
xss is a cursor rule published in the GitHub repository atlassian/forge-skills (20 stars, last pushed 3d ago), licensed Apache-2.0. It adds 12 tokens to every session and 1,134 once invoked, about $0.0001 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other cursor rules, from other repositories
angular-20
This rule provides comprehensive best practices and coding standards for Angular development, focusing on modern TypeScript, standalone components, signals, and performance optimizations.
dev-standard
Apache Superset development standards and guidelines for Cursor IDE.
cli-error-handling
CLI command error handling patterns.
prefer-direct-imports-over-module-mocks
Prefer extracting a testable core over vi.mock / vi.resetModules when unit tests need to reach production logic entangled with config, env, or singletons.
control-plane-descriptors
Control plane descriptor and instance implementation patterns.
family-instance-domain-actions
Family instance domain action implementation patterns.