Two-layer security verification: static source analysis (grep/ESLint) + runtime browser inspection (Playwright). Catches what each layer alone misses. Required by Constitution VII for security invariants. [EXPLICIT] Trigger: "dual-layer", "static + runtime", "security verification", "runtime inspection"
From jm-adknpx claudepluginhub javimontano/jm-adk-alfaThis skill is limited to using the following tools:
agents/guardian.mdagents/lead.mdagents/specialist.mdagents/support.mdevals/evals.jsonknowledge/body-of-knowledge.mdknowledge/knowledge-graph.mdprompts/meta.mdprompts/primary.mdprompts/variations/deep.mdprompts/variations/quick.mdtemplates/output.docx.mdtemplates/output.html"What static analysis misses, the browser reveals. What the browser hides, grep finds."
Verifies security invariants at two independent layers: (1) static analysis of source files and (2) runtime inspection of deployed/served artifacts via Playwright. The marginal cost of the second layer is near-zero when E2E tests already exist; the marginal benefit is closing vectors that static analysis cannot detect. Required by Constitution VII for defense-in-depth. [EXPLICIT]
innerHTML with user-controlled datagrep -r "innerHTML" --include="*.js" → flag user-data assignmentsgrep -rP "(AKIA|AIza|ghp_|sk-)" --include="*.js" → detect secretsno-eval, no-implied-eval, no-script-url rules# Secrets scan
grep -rPl '(AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35}|ghp_[0-9a-zA-Z]{36})' \
--include="*.js" --include="*.html" src/
# innerHTML with variables (not static strings)
grep -rn 'innerHTML\s*=' --include="*.js" src/ | grep -v '= \x27\|= "'
# Scattered Firestore queries
grep -rn 'collection(\|doc(' --include="*.js" src/ | grep -v 'services/'
// Playwright security verification
test('no secrets in page source', async ({ page }) => {
await page.goto('/');
const content = await page.content();
expect(content).not.toMatch(/AKIA[0-9A-Z]{16}/);
expect(content).not.toMatch(/sk-[0-9a-zA-Z]{48}/);
});
test('CSP header present', async ({ page }) => {
const response = await page.goto('/');
const csp = response.headers()['content-security-policy'];
expect(csp).toBeDefined();
});
test('XSS payload stripped', async ({ page }) => {
await page.goto('/admin');
await page.fill('#title-input', '<script>alert(1)</script>Test');
await page.click('#save');
const stored = await page.textContent('#title-display');
expect(stored).toBe('Test');
});
| Anti-Pattern | Why It's Bad | Do This Instead |
|---|---|---|
| Static-only verification | Misses runtime-injected content, dynamic imports | Add runtime layer |
| Runtime-only verification | Misses source patterns that haven't triggered yet | Add static layer |
| Treating layers as redundant | Each catches different classes of issues | Run BOTH, compare |
| Skipping runtime because "too slow" | Marginal cost is near-zero with existing E2E | Add security checks to existing E2E suite |
| No combined report | Findings get lost | Single report with both layers' findings |
security-testing — Broader security testing frameworkinput-sanitization — The sanitization that dual-layer verifiese2e-testing — Playwright infrastructure that runtime layer useslighthouse-ci — Performance verification in the same CI pipelineExample invocations:
| Scenario | Handling |
|---|---|
| Empty or minimal input | Request clarification before proceeding |
| Conflicting requirements | Flag conflicts explicitly, propose resolution |
| Out-of-scope request | Redirect to appropriate skill or escalate |
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.