-
Notifications
You must be signed in to change notification settings - Fork 23
feat: auth0 audit claude skill #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,228 @@ | ||||||||||||||||||||
| Run a security audit against the configured Auth0 tenant. Produces Markdown receipts and structured JSON findings. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Usage:** | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
| /auth0-audit [--tool actions|tokens|passkeys|all] [--tenant DOMAIN] [--cache] | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Arguments:** | ||||||||||||||||||||
| - `--tool`: Which audit to run. Default: `all` | ||||||||||||||||||||
| - `--tenant`: Override the `AUTH0_DOMAIN` env var for this run | ||||||||||||||||||||
| - `--cache`: Use `scripts/demo-cache.json` instead of live API calls (offline demo mode) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Step 0 — Verify MCP connection | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Before doing anything else, attempt a lightweight MCP call (e.g. `auth0_list_applications` with `per_page=1`) to confirm the auth0-mcp-server is reachable. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| - If the call **succeeds**: proceed to Step 1. | ||||||||||||||||||||
| - If the call **fails** with an MCP connection error or authentication error: stop immediately and tell the user: | ||||||||||||||||||||
|
|
||||||||||||||||||||
| > The auth0-mcp-server is not connected or not authenticated. | ||||||||||||||||||||
| > Please run the following command in your terminal, then re-run `/auth0-audit`: | ||||||||||||||||||||
| > | ||||||||||||||||||||
| > ``` | ||||||||||||||||||||
| > npx @auth0/auth0-mcp-server init | ||||||||||||||||||||
| > ``` | ||||||||||||||||||||
|
Comment on lines
+20
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove manual Line 20–25 currently directs users to a manual init flow that conflicts with this plugin’s automated credential handling path and can send users down the wrong remediation route. Suggested doc fix- > Please run the following command in your terminal, then re-run `/auth0-audit`:
- >
- > ```
- > npx `@auth0/auth0-mcp-server` init
- > ```
+ > Credential setup is managed automatically by the skill hooks.
+ > Please ensure the Auth0 audit skill hooks are active, then re-run `/auth0-audit`.Based on learnings: "Do NOT attempt to run 📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.22.1)[warning] 23-23: Fenced code blocks should have a language specified (MD040, fenced-code-language) 🤖 Prompt for AI Agents |
||||||||||||||||||||
|
|
||||||||||||||||||||
| Do not proceed to any audit steps until the MCP connection is confirmed. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Step 1 — Parse arguments | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Extract `--tool`, `--tenant`, `--cache` from the `/auth0-audit` invocation args. | ||||||||||||||||||||
| Default `--tool` to `all` if not specified. | ||||||||||||||||||||
| If `--tenant` is provided, set `AUTH0_DOMAIN` to that value for this run. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Step 2 — Run selected tools | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Run tools in order: `actions` → `tokens` → `passkeys` (skip any not selected). | ||||||||||||||||||||
|
|
||||||||||||||||||||
| --- | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Tool: ActionsWhisperer (`--tool actions`) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Purpose:** Analyze all Auth0 Actions for security risks. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Steps:** | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 1. Use MCP tool `auth0_list_actions` to get all actions. If `--cache` is set, read from `scripts/demo-cache.json` key `actions_list` instead. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 2. For each action returned, use MCP tool `auth0_get_action` with the action's `id` to fetch its full details including `code`, `secrets` (names only), and `dependencies`. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 3. For each action, analyze the code using the **ActionsWhisperer Analysis Prompt** below. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 4. Collect all findings into an array. Then run: | ||||||||||||||||||||
| ```bash | ||||||||||||||||||||
| node tools/render-findings.js actions '<JSON_ARRAY>' | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
| where `<JSON_ARRAY>` is the JSON-stringified array of per-action findings objects. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 5. Print the console summary line. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **ActionsWhisperer Analysis Prompt** (apply this to each action's code): | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ``` | ||||||||||||||||||||
| You are a CIAM security analyst reviewing Auth0 Actions code. Analyze the following Auth0 Action and return ONLY a valid JSON object matching the schema below. Do not include markdown, explanation, or any text outside the JSON. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Action context: | ||||||||||||||||||||
| - Name: {action_name} | ||||||||||||||||||||
| - Trigger: {trigger_type} (e.g. post-login, credentials-exchange, pre-user-registration, post-user-registration) | ||||||||||||||||||||
| - Named secrets available (values not accessible via API): {secret_names} | ||||||||||||||||||||
| - NPM dependencies declared: {dependencies} | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Code: | ||||||||||||||||||||
| {code} | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Identify and flag the following risk patterns: | ||||||||||||||||||||
|
|
||||||||||||||||||||
| (a) EXTERNAL_HTTP_CALL — any fetch(), axios(), http.request(), or XMLHttpRequest to a non-hardcoded URL or to any URL not in the declared allowlist. If the URL is a string literal, include it. If it uses a variable or env secret, note it. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| (b) PII_METADATA_WRITE — any call to api.user.setUserMetadata() or api.idTokenClaims.setCustomClaim() where the value comes from event.request.* (ip, userAgent, geoip, hostname, query, body) — this persists request-context data as PII in the user record. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| (c) HARDCODED_SECRET — any string literal matching patterns for API keys, tokens, or passwords: | ||||||||||||||||||||
| - Length 20–80 characters with high entropy (mixed alphanumeric + special chars) | ||||||||||||||||||||
| - Matches patterns like: /[A-Za-z0-9_\-]{32,}/ in a string assignment to a variable named *key*, *token*, *secret*, *password*, *apikey*, *api_key* | ||||||||||||||||||||
| - Do NOT flag named secret references like event.secrets.MY_SECRET — those are safe | ||||||||||||||||||||
|
|
||||||||||||||||||||
| (d) EXTERNAL_CLAIM_INJECTION — any call to api.accessToken.setCustomClaim() or api.idTokenClaims.setCustomClaim() where the value originates from an external HTTP response, event.request.*, or event.authorization.* — this could inject attacker-controlled values into tokens | ||||||||||||||||||||
|
|
||||||||||||||||||||
| (e) ACCESS_DENY_CONDITION — any call to api.access.deny() — document the condition, but do not automatically flag as risky; rate this "low" unless the condition itself looks exploitable | ||||||||||||||||||||
|
|
||||||||||||||||||||
| (f) UNALLOWLISTED_SERVICE — any call to an external service (HTTP or SDK) that is not in the declared allowlist (assume the declared allowlist is empty unless the action's code or comments explicitly define one) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| IMPORTANT: event.secrets.ANYTHING is safe — do not flag secret references. Only flag hardcoded literal values. | ||||||||||||||||||||
| IMPORTANT: Do not echo any email addresses, user IDs, or PII you find in code comments. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Return this JSON schema (no other text): | ||||||||||||||||||||
| { | ||||||||||||||||||||
| "action_id": "<id>", | ||||||||||||||||||||
| "action_name": "<name>", | ||||||||||||||||||||
| "trigger": "<trigger_type>", | ||||||||||||||||||||
| "risk_level": "critical|high|medium|low|none", | ||||||||||||||||||||
| "findings": [ | ||||||||||||||||||||
| { | ||||||||||||||||||||
| "pattern": "EXTERNAL_HTTP_CALL|PII_METADATA_WRITE|HARDCODED_SECRET|EXTERNAL_CLAIM_INJECTION|ACCESS_DENY_CONDITION|UNALLOWLISTED_SERVICE", | ||||||||||||||||||||
| "location": "<function name or line description>", | ||||||||||||||||||||
| "description": "<what was found, no PII>", | ||||||||||||||||||||
| "remediation": "<specific fix recommendation>" | ||||||||||||||||||||
| } | ||||||||||||||||||||
| ], | ||||||||||||||||||||
| "plain_english_summary": "<2-3 sentence plain English description of what this Action does and its risk profile>" | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Risk level rules: | ||||||||||||||||||||
| - critical: HARDCODED_SECRET found | ||||||||||||||||||||
| - high: PII_METADATA_WRITE or EXTERNAL_CLAIM_INJECTION with externally sourced values | ||||||||||||||||||||
| - medium: EXTERNAL_HTTP_CALL or UNALLOWLISTED_SERVICE | ||||||||||||||||||||
| - low: ACCESS_DENY_CONDITION or minor issues | ||||||||||||||||||||
| - none: no findings | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Output files written by** `node tools/render-findings.js actions`: | ||||||||||||||||||||
| - `actions-audit.md` — full receipts grouped by trigger type | ||||||||||||||||||||
| - `actions-findings.json` — structured findings array | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Console summary format:** | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
| Analyzed N actions. Found X critical, Y high, Z medium findings. | ||||||||||||||||||||
| Top risk: [action_name] ([trigger]) — [one-line description of worst finding]. | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| --- | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Tool: TokenGraveyard (`--tool tokens`) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Purpose:** Identify dormant and overprivileged M2M (non_interactive) applications and provide approval-gated remediation. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Steps:** | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 1. Use MCP tool `auth0_list_applications` with filter `app_type=non_interactive` (or equivalent parameter). If `--cache`, read from `scripts/demo-cache.json` key `m2m_apps`. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 2. Run the TokenGraveyard analysis script to compute last-used dates and blast-radius scores: | ||||||||||||||||||||
| ```bash | ||||||||||||||||||||
| node tools/token-graveyard.js | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
| This script queries Auth0 logs directly for each app's last `sce` event, computes scores, writes `tokens-audit.md` and `tokens-findings.json`, and prints a ranked remediation list to stdout. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 3. Show the ranked remediation list to the user. For each app in the **"Revoke now"** tier, ask: | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
| Revoke client grant for "[app_name]" (client_id: [id])? [y/N] | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
| Wait for explicit `y` before proceeding. `N` or any other input skips that app. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 4. For each approved revocation, use MCP tool `auth0_delete_client_grant` with the grant ID. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 5. After all approvals processed, run: | ||||||||||||||||||||
| ```bash | ||||||||||||||||||||
| node tools/render-findings.js tokens-receipt '<RECEIPTS_JSON>' | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
| to write `tokens-remediation-receipt.md`. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Blast-radius scoring** (implemented in `tools/token-graveyard.js`): | ||||||||||||||||||||
| - `update:users`, `delete:users` → 4 pts each | ||||||||||||||||||||
| - `create:clients`, `update:clients`, `delete:clients` → 5 pts each | ||||||||||||||||||||
| - `read:user_idp_tokens` → 3 pts | ||||||||||||||||||||
| - `update:tenant_settings` → 5 pts | ||||||||||||||||||||
| - `read:users` → 1 pt | ||||||||||||||||||||
| - All other Management API scopes → 1 pt | ||||||||||||||||||||
| - Non-Management-API scopes → 0.5 pts | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Tier assignments:** | ||||||||||||||||||||
| - **Revoke now:** never used OR (last used >90 days AND blast radius > 5) | ||||||||||||||||||||
| - **Rotate within 7 days:** last used 60–90 days OR blast radius > 8 | ||||||||||||||||||||
| - **Scope-narrow within 30 days:** scope overprivilege relative to app name/purpose | ||||||||||||||||||||
| - **Monitor:** last used <30 days, normal blast radius | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Console summary format:** | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
| Found N M2M applications. X never used, Y dormant >60 days, Z with high blast radius (score >8). | ||||||||||||||||||||
| Recommended: revoke X, rotate Y, scope-narrow Z. | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| --- | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Tool: PasskeysReadiness (`--tool passkeys`) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Purpose:** Assess whether the tenant meets all 4 prerequisites for enabling Passkeys (WebAuthn). | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Steps:** | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 1. Run the PasskeysReadiness script: | ||||||||||||||||||||
| ```bash | ||||||||||||||||||||
| node tools/passkeys-readiness.js | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
| If `--cache`, pass `--cache` flag: `node tools/passkeys-readiness.js --cache` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 2. The script writes `passkeys-readiness.md` and prints the console summary. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 3. Read `passkeys-readiness.md` and present its contents to the user. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| **Console summary format:** | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
| Passkeys readiness: N/4 prerequisites met. [not_ready|partially_ready|ready]. | ||||||||||||||||||||
| Primary blocker: [blocking issue in one sentence, or "None — tenant is ready for Passkeys"]. | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| --- | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Orchestration (`--tool all`) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Run all three tools in sequence: ActionsWhisperer → TokenGraveyard → PasskeysReadiness. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| After all tools complete, write `auth0-audit-summary.md`: | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ```markdown | ||||||||||||||||||||
| # Auth0 Security Audit Summary | ||||||||||||||||||||
| Generated: [ISO timestamp] | ||||||||||||||||||||
| Tenant: [AUTH0_DOMAIN] | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Actions (ActionsWhisperer) | ||||||||||||||||||||
| [Total actions analyzed, finding counts by severity, top risk] | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## M2M Tokens (TokenGraveyard) | ||||||||||||||||||||
| [Total apps, dormancy breakdown, revocations executed] | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ## Passkeys Readiness | ||||||||||||||||||||
| [Score N/4, status, primary blocker] | ||||||||||||||||||||
| ``` | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Print a 5-line console summary on completion. | ||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| { | ||
| "mcpServers": { | ||
| "auth0": { | ||
| "command": "node", | ||
| "args": ["hooks/mcp-server.js"] | ||
| } | ||
| }, | ||
| "hooks": { | ||
| "SessionStart": [ | ||
| { | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": "node hooks/inject-auth0-context.js" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| .env | ||
| .claudecreds | ||
| .auth0-token-cache | ||
| node_modules/ | ||
| ./claude/settings.local.json |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # Auth0 Security Audit Plugin | ||
|
|
||
| This project is an Auth0 Customer Identity Cloud (CIC) security audit plugin for Claude Code. | ||
| It targets Auth0 CIC only — not Okta Workforce Identity Cloud or Okta Identity Engine. | ||
|
|
||
| **Prerequisites:** | ||
| - Node.js ^20.19.0 || ^22.12.0 || ^24.0.0 | ||
| - `auth0-mcp-server` configured in `.claude/settings.json` (already done — runs via `hooks/mcp-server.js`) | ||
|
|
||
| **Credential handling — IMPORTANT:** | ||
| All Auth0 credential acquisition is handled automatically by `hooks/mcp-server.js`. Do NOT look for tokens in the OS keychain, `~/.config`, or any other system location. Do NOT attempt to run `auth0-mcp-server init` manually. | ||
|
|
||
| The wrapper uses the device authorization flow: | ||
| 1. Checks for an existing token in the OS keychain (stored by a previous `auth0-mcp-server init` run) | ||
| 2. If no token is found, runs `npx @auth0/auth0-mcp-server init` (without options) — this opens the Auth0 device-auth page in the browser and persists the token in the OS keychain | ||
| 3. Spawns `npx @auth0/auth0-mcp-server run` | ||
|
|
||
| The MCP tools (`auth0_list_actions`, `auth0_list_applications`, etc.) are ready to use without any additional auth steps after the first browser-based login. | ||
|
|
||
| **Slash command:** `/auth0-audit` — see `.claude/commands/auth0-audit.md` for full implementation steps. | ||
|
|
||
| ## Project Structure | ||
|
|
||
| ``` | ||
| .claude/ | ||
| commands/ | ||
| auth0-audit.md ← slash command definition (skill steps) | ||
| settings.json ← MCP server + hook config | ||
| hooks/ | ||
| inject-auth0-context.js ← SessionStart hook | ||
| mcp-server.js ← MCP server wrapper (token caching) | ||
| tools/ | ||
| render-findings.js ← ActionsWhisperer output renderer | ||
| token-graveyard.js ← TokenGraveyard analysis + scoring | ||
| passkeys-readiness.js ← PasskeysReadiness 4-checkpoint script | ||
| scripts/ | ||
| setup-demo-tenant.js ← Populates dev tenant with synthetic data | ||
| teardown-demo-tenant.js | ||
| demo-cache.json ← Cached API responses for offline demo | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| #!/usr/bin/env node | ||
| /** | ||
| * SessionStart hook — injects Auth0 tenant context into Claude's session. | ||
| * Warns if AUTH0_CLIENT_SECRET is in .env but auth0-mcp-server is not configured. | ||
| * Output is read by Claude Code and prepended to the system context. | ||
| */ | ||
|
|
||
| import { readFileSync, existsSync } from 'fs'; | ||
| import { resolve } from 'path'; | ||
|
|
||
| const cwd = process.cwd(); | ||
|
|
||
| function loadEnvFile(path) { | ||
| if (!existsSync(path)) return {}; | ||
| const vars = {}; | ||
| for (const line of readFileSync(path, 'utf8').split('\n')) { | ||
| const trimmed = line.trim(); | ||
| if (!trimmed || trimmed.startsWith('#')) continue; | ||
| const eq = trimmed.indexOf('='); | ||
| if (eq === -1) continue; | ||
| vars[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim().replace(/^["']|["']$/g, ''); | ||
| } | ||
| return vars; | ||
| } | ||
|
|
||
| function loadClaudeCreds(path) { | ||
| if (!existsSync(path)) return {}; | ||
| try { | ||
| return JSON.parse(readFileSync(path, 'utf8')); | ||
| } catch { | ||
| return {}; | ||
| } | ||
| } | ||
|
|
||
| const envVars = loadEnvFile(resolve(cwd, '.env')); | ||
| const claudeCreds = loadClaudeCreds(resolve(cwd, '.claudecreds')); | ||
|
|
||
| const domain = | ||
| process.env.AUTH0_DOMAIN || | ||
| claudeCreds.AUTH0_DOMAIN || | ||
| envVars.AUTH0_DOMAIN || | ||
| null; | ||
|
|
||
| const settingsPath = resolve(cwd, '.claude/settings.json'); | ||
| let mcpConfigured = false; | ||
| if (existsSync(settingsPath)) { | ||
| try { | ||
| const settings = JSON.parse(readFileSync(settingsPath, 'utf8')); | ||
| mcpConfigured = !!(settings.mcpServers && settings.mcpServers.auth0); | ||
| } catch { /* ignore */ } | ||
| } | ||
|
|
||
| const hasStaticSecret = | ||
| !!(envVars.AUTH0_CLIENT_SECRET || process.env.AUTH0_CLIENT_SECRET); | ||
|
|
||
| const warnings = []; | ||
| if (hasStaticSecret && !mcpConfigured) { | ||
| warnings.push( | ||
| 'WARNING: Static Management API credential detected in .env (AUTH0_CLIENT_SECRET). ' + | ||
| 'Consider using auth0-mcp-server for credential-safe access — it stores credentials ' + | ||
| 'in the OS keychain and avoids committing secrets to source control.' | ||
| ); | ||
| } | ||
|
|
||
| const today = new Date().toISOString().split('T')[0]; | ||
|
|
||
| const lines = [ | ||
| '=== Auth0 Security Audit Plugin — Session Context ===', | ||
| '', | ||
| `Date: ${today}`, | ||
| `Tenant: ${domain || '(not configured — set AUTH0_DOMAIN in .env or .claudecreds)'}`, | ||
| '', | ||
| 'Available audit tools (invoke with /auth0-audit):', | ||
| ' --tool actions → ActionsWhisperer: analyze Action JS code for security risks', | ||
| ' --tool tokens → TokenGraveyard: identify dormant/overprivileged M2M apps', | ||
| ' --tool passkeys → PasskeysReadiness: check 4 prerequisites for enabling Passkeys', | ||
| ' --tool all → Run all three tools in sequence (default)', | ||
| '', | ||
| 'Context for judges: Auth0 Actions are server-side JavaScript functions that execute', | ||
| 'at specific points in the authentication pipeline (e.g., after login, during token', | ||
| 'exchange). They can add custom claims, call external services, and modify user', | ||
| 'metadata — making them a critical surface for security review.', | ||
| '', | ||
| 'Scope: Auth0 Customer Identity Cloud (CIC) only.', | ||
| 'All write operations require explicit human approval before execution.', | ||
| ]; | ||
|
|
||
| if (warnings.length > 0) { | ||
| lines.push(''); | ||
| for (const w of warnings) lines.push(w); | ||
| } | ||
|
|
||
| lines.push(''); | ||
| lines.push('=== End Auth0 Context ==='); | ||
|
|
||
| // Claude Code SessionStart hooks output plain text injected into the system context. | ||
| process.stdout.write(lines.join('\n') + '\n'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add language identifiers to fenced code blocks (MD040).
The unlabeled fenced blocks trigger markdownlint warnings; please mark each with an explicit language (
text,bash,json,markdown, etc.) to keep docs lint-clean.Also applies to: 23-25, 63-118, 125-128, 147-150, 176-179, 200-203
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 4-4: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents