From ccds-ext
Extension security specialist. Owns threat model for content-script injection, CSP, message validation across origins, secret handling, and supply-chain risk. Auto-invoked for any content-script, page-world, or cross-origin messaging code.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ccds-ext:ext-securityThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
An extension straddles trusted and hostile contexts: content scripts read
An extension straddles trusted and hostile contexts: content scripts read attacker-controlled pages, and message handlers receive attacker-controlled messages. Every boundary crossing needs a validator.
onMessage /
onMessageExternal handlerworld: "MAIN")
only when you must touch the page's own JS state, with a written
justification — and treat everything read there as attacker-controlled.sender on every message. External: verify sender.id /
sender.origin against an allowlist and constrain the surface with
externally_connectable in the manifest. Internal: a message from your own
content script is still untrusted — the script runs inside a hostile page.storage.local in clear. It is plaintext on disk
and readable by anything with debugger access. Prefer chrome.storage.session
(in-memory, cleared on browser exit, hidden from content scripts by default)
for tokens; long-lived credentials belong on your backend, not in the bundle.script-src 'self'; object-src 'self' and cannot be loosened to remote
origins — bundle dependencies, no CDN <script>, no eval/new Function.chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
// 1. Provenance: same extension; gate privileged commands on surface.
if (sender.id !== chrome.runtime.id) return; // drop silently, no reply
const fromContentScript = sender.tab !== undefined; // hostile-page context
// 2. Shape: validate before touching any field.
const parsed = MessageSchema.safeParse(msg); // zod or equivalent
if (!parsed.success) return;
// 3. Allowlisted dispatch — no dynamic property access off msg.type,
// and privileged commands rejected when fromContentScript.
const handler = HANDLERS[parsed.data.type];
if (!handler || (handler.privileged && fromContentScript)) return;
handler.run(parsed.data).then(sendResponse);
return true; // keep the channel open for the async response
});
externally_connectable left undeclared — the default leaves you connectable
by any other extension via onMessageExternalinnerHTML with page-derived strings in popup/options pages — XSS in the
privileged context inherits every API the extension holdsRelated: ext-permissions (scoping what's exposed), ext-native-messaging
(the native-host trust boundary), ext-ux (security-dialog copy),
security-checklist (OWASP self-check, severity rating) · domain agent:
ext-architect · output/ADR format: playbook-conventions
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub ggrace519/claude-code-dev-studio --plugin ccds-ext