agentleFS
TacunsTacuns/vibe-aegis/llms-full.txt

vibe-aegis

llms.txt1 starsChanged 15 days agoMITView on GitHub

This is the self-contained edition of the Vibe Aegis repository. Everything an AI agent needs to understand and execute the framework is below: the full README, the always-on engineering rules, all three skill definitions, the scanner CLI reference, and the JSON report schema. Reading this one document is equivalent to reading the whole repository. Canonical repository: https://github.com/Tacuns/vibe-aegis Structured index: https://raw.githubusercontent.com/Tacuns/vibe-aegis/main/llms.txt License: MIT Scope: Defensive pre-deployment auditing of applications you own. Live --url checks are passive, read-only HTTP GET requests. 1.…

  • Reads credentials
  • Installs packages

We split this llms-full.txt into the rules it gives an agent

62 rules. About 0 are common, 9 are distinctive, and 53 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈9

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 53

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Read the 6-Stage Adversarial Analysis Loop to learn the protocol.

    line 16
  2. Very specific:

    Run the deterministic scanner (scripts/aegis_scan.py) first - it is free of LLM cost and fingerprints the stack for you.

    line 17
  3. Very specific:

    Write .aegis/AUDIT_REPORT.md with the Release Readiness Score.

    line 22
  4. Distinctive:

    Never modify source files without the user's explicit approval.

    line 23
  5. Very specific:

    Never place private API keys, database URLs, service-role keys, or webhook secrets in client-exposed variables (NEXT_PUBLIC_*, VITE_*, …

    line 548
  6. Very specific:

    Keep .env, .env.local, and .env.* in .gitignore.

    line 549
  7. Very specific:

    Every Supabase/PostgreSQL table storing user or tenant data must run ALTER TABLE <name> ENABLE ROW LEVEL SECURITY.

    line 551
  8. Distinctive:

    Every database read, update, or delete by ID must filter by the authenticated user's session ID or tenant ID (preventing IDOR).

    line 552
  9. Very specific:

    Always use parameterized queries or safe ORM methods.

    line 556
  10. Distinctive:

    Never trust client-submitted prices, discounts, or plan IDs.

    line 558
  11. Very specific:

    Verify cryptographic signatures on every incoming webhook (stripe.webhooks.constructEvent, HMAC verification) using the raw request body.

    line 559
  12. Very specific:

    Never render unsanitized HTML via dangerouslySetInnerHTML, v-html, or innerHTML.

    line 562
  13. Very specific:

    Never accept amount, unit_amount, price, quantity, currency or discount from the client.

    line 566
  14. Very specific:

    Verify every webhook signature against the raw unparsed body, and store each processed event.id under a unique constraint so a replay …

    line 567
  15. Very specific:

    Never read a balance, decide, then write it back.

    line 568
  16. Very specific:

    Every list query needs an explicit maximum page size.

    line 570
  17. Very specific:

    Never await a database call inside a loop.

    line 571
  18. Distinctive:

    Never log passwords, tokens, API keys or personal data.

    line 573
  19. Very specific:

    Never leave dead buttons or placeholder links (href="#", empty onClick={() => {}}, or console.log stubs).

    line 578
  20. Very specific:

    Every async button or form submission must disable during flight (disabled={isLoading}) and display a clear loading indicator to prevent …

    line 579
  21. Very specific:

    Every data view or list must explicitly handle 4 states: Loading (skeleton/spinner), Empty (clear message + call-to-action), Error …

    line 580
  22. Very specific:

    Keep interactive touch targets at least 44x44px on mobile and maintain a clear z-index scale for modals, dropdowns, and toasts.

    line 583
  23. Very specific:

    Every form control (<input>, <select>, <textarea>) must have an associated <label> or aria-label.

    line 585
  24. Very specific:

    Every icon-only button must include an aria-label, and every informative <img> must include a descriptive alt attribute.

    line 586
  25. Very specific:

    Never remove keyboard focus rings (outline-none) without providing a high-contrast focus-visible:ring replacement.

    line 587
  26. Very specific:

    Never ship "Lorem ipsum", "TODO", "john@example.com", or hardcoded fake metrics in user-facing components.

    line 589
  27. Distinctive:

    Before publishing or merging major features, run the full Vibe Aegis loop:

    line 593
  28. Very specific:

    Follow the orchestration workflow in .claude/skills/vibe-aegis/SKILL.md (or .agents/skills/vibe-aegis/SKILL.md):

    line 596
  29. Very specific:

    Write the final verified scorecard to .aegis/AUDIT_REPORT.md.

    line 598
  30. Distinctive:

    Run a complete, adversarial pre-publication audit across both Application Security (Low to Critical) and UI/UX Design & Functional …

    line 615
  31. Distinctive:

    Run the bundled zero-dependency scanner first so you never waste context guessing the stack:

    line 639
  32. Very specific:

    Read .aegis/scan-report.json to extract:

    line 657
  33. Very specific:

    All deterministic SECURITY and UI_UX candidate findings.

    line 659
  34. Very specific:

    Do this before line-level hunting.

    line 667
  35. Very specific:

    Verify authentication, ownership scoping (IDOR), Row-Level Security (RLS), payment price integrity, webhook signatures, SSRF, …

    line 674
  36. Very specific:

    Check for dead buttons (href="#", empty onClick), missing async disabled/loading states (double-submit bugs), missing empty/error states, …

    line 699
  37. Very specific:

    If a local dev server is running and agent-browser or Playwright is installed, open the live app and inspect both desktop (1440x900) and …

    line 700
  38. Very specific:

    If a defence completely blocks the trigger, mark the finding DISMISSED and cite the exact defensive file:line.

    line 716
  39. Very specific:

    Never edit source files during a scan-only run without user approval.

    line 735
  40. Very specific:

    Create a dedicated git branch (git checkout -b aegis/hardening-$(date +%Y%m%d-%H%M)).

    line 736
  41. Very specific:

    If any patch introduces a build or test failure, immediately revert that commit and flag the item for MANUAL_REVIEW.

    line 739
  42. Very specific:

    Verify no private keys, database connection strings, or service-role keys appear in client-bundled env vars (NEXT_PUBLIC_*, VITE_*, …

    line 773
  43. Very specific:

    Check git history and root files for committed .env, .pem, .key, or hardcoded bearer tokens.

    line 774
  44. Very specific:

    Verify all package dependencies in package.json or requirements.txt are legitimate packages (catching AI-hallucinated "slopsquatting" …

    line 775
  45. Very specific:

    Check that JWTs are verified with jwt.verify() (never just jwt.decode()) and session tokens are stored in HttpOnly.

    line 782
  46. Very specific:

    Check for raw SQL interpolation ($queryRawUnsafe, template literals inside .query(), Python f"SELECT ...").

    line 788
  47. Very specific:

    Check for race conditions (TOCTOU) in credit balances, coupon redemptions, or quota counters (require atomic UPDATE ...

    line 794
  48. Very specific:

    Check URL-fetching endpoints for Server-Side Request Forgery (SSRF) against internal metadata services (169.254.169.254, localhost).

    line 799
  49. Very specific:

    Verify production configuration sets Content-Security-Policy, Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options: nosniff, …

    line 800
  50. Very specific:

    Do not flag a <div> that already carries role, tabIndex and a key handler - that is a correct retrofit.

    line 836
  51. Very specific:

    Verify every modal, drawer, and dialog has a working close button, Escape key dismissal, and cleans up body scroll locks on unmount.

    line 837
  52. Distinctive:

    Verify that every component performing an async fetch or mutation explicitly implements all 4 states:

    line 841
  53. Very specific:

    Empty State: When a list or query returns 0 items, render a helpful empty state with a clear call-to-action instead of a blank void.

    line 843
  54. Very specific:

    Error State: When a fetch or mutation fails, catch the error and display a user-friendly alert, toast, or inline field error with a retry …

    line 844
  55. Very specific:

    Check layout behavior at Mobile (375x812), Tablet (768x1024), and Desktop (1440x900).

    line 849
  56. Very specific:

    Ensure touch targets (buttons, nav links, close icons) are at least 44x44px on mobile screens and do not overlap with fixed bottom bars or …

    line 851
  57. Very specific:

    Verify every <input>, <select>, and <textarea> is linked to a visible <label> or aria-label.

    line 855
  58. Very specific:

    Verify every icon-only <button> has an aria-label and every <img /> has an alt attribute.

    line 856
  59. Very specific:

    Check color contrast pairings (avoid low-contrast muted text like text-gray-300 on bg-white or text-gray-600 on bg-gray-900).

    line 857
  60. Very specific:

    Ensure keyboard Tab order is logical and focus indicators (focus-visible:ring-2) are never stripped without replacement.

    line 858
  61. Very specific:

    If the app is running locally and agent-browser or Playwright is installed:

    line 862
  62. Very specific:

    Every credential in every output format is redacted to its first 6 and last 4 characters plus a length.

    line 1009

≈ “Common” is an estimate: at least 1 in 5 of the 3,225 llms.txt files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
llms-full.txt
# Vibe Aegis - Complete Framework (Single-Fetch Document)

> This is the self-contained edition of the Vibe Aegis repository. Everything an AI agent
> needs to understand and execute the framework is below: the full README, the always-on
> engineering rules, all three skill definitions, the scanner CLI reference, and the JSON
> report schema. Reading this one document is equivalent to reading the whole repository.
>
> Canonical repository: https://github.com/Tacuns/vibe-aegis
> Structured index: https://raw.githubusercontent.com/Tacuns/vibe-aegis/main/llms.txt
> License: MIT
> Scope: Defensive pre-deployment auditing of applications you own. Live `--url` checks are
> passive, read-only HTTP GET requests.

## How An Agent Should Use This Document

1. Read the **6-Stage Adversarial Analysis Loop** to learn the protocol.
2. Run the deterministic scanner (`scripts/aegis_scan.py`) first - it is free of LLM cost and
   fingerprints the stack for you.
3. Execute Stage 2 using the `security-redteam-loop` skill and Stage 3 using the
   `ui-ux-bug-finder` skill, both reproduced in full below.
4. Apply the Skeptic stage to disprove your own findings before reporting any of them.
5. Write `.aegis/AUDIT_REPORT.md` with the Release Readiness Score.
6. Never modify source files without the user's explicit approval.

---

# TABLE OF CONTENTS

- PART 1: README - Full Documentation
- PART 2: AGENTS.md - Always-On Engineering Rules
- PART 3: SKILL - vibe-aegis (Master 6-Stage Orchestrator)
- PART 4: SKILL - security-redteam-loop (Low-to-Critical Security Auditor)
- PART 5: SKILL - ui-ux-bug-finder (UI/UX, Layout & Accessibility Auditor)
- PART 6: SKILL - artifact-leak-hunter (Shipped-Artifact Verification)
- PART 7: Scanner CLI Reference (scripts/aegis_scan.py)
- PART 8: JSON Report Schema (.aegis/scan-report.json)

---

# =============================================================================
# PART 1: README - FULL DOCUMENTATION
# =============================================================================

# 🛡️ Vibe Aegis (`vibe-aegis`)

**The 10-Stage First-to-Last Full-Stack Safeguard for Vibe-Coded Apps — across 8 domains.**

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.8+ Zero-Deps](https://img.shields.io/badge/Python-3.8%2B%20zero--deps-3776AB?logo=python&logoColor=white)](scripts/aegis_scan.py)
[![Node >= 18 NPX CLI](https://img.shields.io/badge/Node-%3E%3D18%20npx%20CLI-339933?logo=node.js&logoColor=white)](bin/vibe-aegis.mjs)
[![CI](https://github.com/Tacuns/vibe-aegis/actions/workflows/ci.yml/badge.svg)](https://github.com/Tacuns/vibe-aegis/actions/workflows/ci.yml)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
[![AI-Ready llms.txt](https://img.shields.io/badge/AI--Ready-llms.txt-8A2BE2)](llms.txt)
[![SARIF + SBOM](https://img.shields.io/badge/output-SARIF%20%7C%20SBOM%20%7C%20JSON-0A7E8C)](schemas/scan-report.schema.json)

---

## ⚡ Start in 2 Lines (Paste into Any AI Agent)

Open your project in **Claude Code, VS Code Copilot, OpenAI Codex, Cursor, Windsurf, Cline, Gemini CLI**, ChatGPT, Claude, Gemini, Perplexity or Grok — and paste this. Nothing to clone, nothing to install first:

```text
Read https://raw.githubusercontent.com/Tacuns/vibe-aegis/main/llms.txt and run the Vibe Aegis setup and 10-stage Security + UI/UX audit in this project.
```

That single URL teaches the agent the whole framework. For everything in one fetch, point it at [`llms-full.txt`](llms-full.txt) instead.

**Prefer a plugin?**

```text
/plugin marketplace add Tacuns/vibe-aegis        # Claude Code, then type /aegis
codex plugin marketplace add Tacuns/vibe-aegis   # OpenAI Codex, then type $vibe-aegis
```

---

AI coding assistants build features at lightning speed, but they routinely ship hidden security holes (exposed client secrets, missing Row-Level Security, IDOR, unverified webhooks, prompt injection) and broken UI/UX states (dead placeholder buttons, missing loading/disabled states, mobile overflow traps, WCAG accessibility failures).

**Vibe Aegis** combines a **zero-dependency static + live deployment scanner** (`aegis_scan.py`) with a **10-stage adversarial multi-agent analysis loop across 8 domains** that installs in one command across **Claude Code, VS Code (GitHub Copilot), OpenAI Codex, Cursor, Windsurf, Cline, Gemini CLI, and OpenCode**.


## 🧭 The 8 Domains

A single pass over eight separate failure modes. Each has its own skill, its own rules, and its own place in the 10-stage loop.

| # | Domain | Catches | Skill |
| :--- | :--- | :--- | :--- |
| 1 | **Architecture & Tenancy** | Broken tenant isolation, missing RLS, weak trust boundaries | `architecture-threat-model` |
| 2 | **Application Security** | Secrets, IDOR, injection, XSS, SSRF, auth & session flaws | `security-redteam-loop` |
| 3 | **Payments & Business Logic** | Client-trusted prices, replayable webhooks, double-spend races | `payments-logic-auditor` |
| 4 | **AI / LLM** | Prompt injection, denial-of-wallet, unsafe output, tool scope | `ai-llm-security-shield` |
| 5 | **Backend Reliability** | Unbounded queries, N+1 loops, missing timeouts, PII in logs | `backend-reliability-scale` |
| 6 | **UI/UX & Accessibility** | Dead buttons, missing async states, mobile overflow, WCAG 2.2 AA | `ui-ux-bug-finder` |
| 7 | **Shipped Artifacts** | Secrets in the built bundle, source maps, unsigned/debuggable APKs | `artifact-leak-hunter` |
| 8 | **Production Readiness** | Headers, exposed files, container & CI hardening, go/no-go verdict | `production-preflight-gate` |

Security bugs leak data. **Payment bugs leak money.** **Reliability bugs only appear the day you succeed.** They need separate passes, because each one looks fine from inside the others.

## 🔄 The Adversarial Analysis Loop

```mermaid
flowchart TD
    A["🔍 Stage 1 — Recon & Triage<br/>aegis_scan.py<br/>Fingerprint stack · 40+ deterministic rules"]
    B["🛡️ Stage 2 — Security Hunter<br/>Secrets · Auth & IDOR · RLS<br/>Payments · SSRF · AI/LLM"]
    C["🎨 Stage 3 — UI/UX Hunter<br/>Dead controls · Async states<br/>Mobile overflow · WCAG 2.2 AA"]
    D["🤔 Stage 4 — Adversarial Skeptic<br/>Try to DISPROVE every claim<br/>middleware · ORM · auto-escaping"]
    E["⚖️ Stage 5 — Evidence Referee<br/>CONFIRMED · MANUAL_REVIEW · DISMISSED<br/>CWE · CVSS · Readiness Score 0-100"]
    F{"Score >= 90 and zero<br/>CRITICAL / HIGH?"}
    G["✅ READY TO PUBLISH"]
    H["🔧 Stage 6 — Guarded Fixer --fix<br/>Branch · patch one at a time<br/>re-scan + rebuild · auto-revert regressions"]

    A --> B
    A --> C
    B --> D
    C --> D
    D --> E
    E --> F
    F -->|Yes| G
    F -->|No| H
    H --> A

    style A fill:#1e3a8a,stroke:#3b82f6,color:#fff
    style B fill:#7f1d1d,stroke:#ef4444,color:#fff
    style C fill:#713f12,stroke:#f59e0b,color:#fff
    style D fill:#4c1d95,stroke:#8b5cf6,color:#fff
    style E fill:#164e63,stroke:#06b6d4,color:#fff
    style F fill:#374151,stroke:#9ca3af,color:#fff
    style G fill:#14532d,stroke:#22c55e,color:#fff
    style H fill:#78350f,stroke:#f97316,color:#fff
```

1. **Stage 1 — Deterministic Recon & Triage (`scripts/aegis_scan.py`)**
   Runs the fast local scanner to fingerprint your stack (frameworks, auth, database, payment provider, UI library), map trust boundaries, and produce `.aegis/scan-report.json` with zero LLM token waste.
2. **Stage 2 — Deep Security Hunter (`skills/security-redteam-loop/SKILL.md`)**
   Traces every entry point, API route, Server Action, database query, webhook, and environment variable from **Low to Critical** severity using STRIDE threat modeling and OWASP Top 10 + AI-specific vulnerability rules.
3. **Stage 3 — Deep UI/UX Design & Flow Bug Finder (`skills/ui-ux-bug-finder/SKILL.md`)**
   Audits every page and component for dead click handlers (`href="#"`, empty `onClick`), missing async `loading`/`disabled` states (double-submit bugs), missing empty/error states, responsive overflow traps, z-index collisions, and WCAG 2.2 AA accessibility violations. If `agent-browser` or Playwright is available, it also inspects the live rendered DOM across mobile (`375x812`) and desktop (`1440x900`) viewports.
4. **Stage 4 — Adversarial Skeptic (False-Positive Filter)**
   Challenges every claim from Stages 2 and 3 by checking middleware (`middleware.ts`), ORM parameterization, framework auto-escaping, and parent layout containers. Any speculative claim without a reachable trigger is dismissed.
5. **Stage 5 — Evidence Referee & Release Readiness Scorecard**
   Assigns final verdicts (`CONFIRMED`, `MANUAL_REVIEW`, `DISMISSED`), CWE IDs, CVSS 3.1 / UX severity scores, and calculates a **0–100 Release Readiness Score** inside `.aegis/AUDIT_REPORT.md`. Publishing is blocked if any `CRITICAL` or `HIGH` issue remains open.
6. **Stage 6 — Guarded Fixer & Verification Loop (Opt-In `--fix`)**
   Creates a safe git branch (`aegis/hardening-<timestamp>`), patches confirmed bugs one by one, re-runs `aegis_scan.py` plus your project's build/test suite after each patch, and automatically reverts any fix that introduces a regression.

## ⚡ Why Vibe Aegis?

| Capability | Single-Skill Security Checklists | Binary Reverse-Engineering Tools | **Vibe Aegis (`vibe-aegis`)** |
| :--- | :--- | :--- | :--- |
| **Pre-Publish Vibe-Code Security Gate** | Partial (15–30 static rules) | No (focused on binary/app decompilation) | **40+ Static + Live HTTP Posture Checks (Low to Critical)** |
| **Adversarial Verification Loop** | Single-pass prompt (high false positives) | Evidence tracing only | **10 stages: Hunter → Skeptic → Referee → Guarded Fixer** |
| **UI/UX Design & Browser QA Bug Finder** | None | None | **Detects dead buttons, missing async loading states, mobile overflow, a11y & visual bugs** |
| **Stack-Aware Rules** | Basic | JS/Electron/Native | **Next.js, React, Supabase, Firebase, Prisma, Stripe, Razorpay, FastAPI, Express, Mobile** |
| **Universal Agent Support** | 1–2 agents | MCP clients | **Claude Code, VS Code, Codex, Cursor, Windsurf, Cline, Gemini CLI, GitHub Actions** |
| **Machine-Readable Output** | Prose only | Tool-specific | **`.aegis/scan-report.json` validated by a published JSON Schema** |

## 🚀 Install Options

### Option 1: Universal Shell Installer (macOS / Linux / WSL / Git Bash)

```bash
git clone https://github.com/Tacuns/vibe-aegis.git
cd vibe-aegis

# Install into a project for ALL agents (Claude Code, VS Code Copilot, Codex, Cursor, Windsurf, Cline, Gemini)
bash install.sh --target /path/to/your/app --agent all

# Or install globally for your user profile
bash install.sh --global --agent all
```

### Option 2: `npx` CLI Installer (Node.js 18+)

```bash
npx vibe-aegis setup --target . --agent all

# Or select a specific agent: claude-code | vscode | codex | cursor | windsurf | cline | gemini
npx vibe-aegis setup --target . --agent claude-code
```

### Option 3: Run the Deterministic Scanner Directly (Python 3.8+, Zero Dependencies)

```bash
# 1. Full static codebase audit (Security + UI/UX bugs)
python3 scripts/aegis_scan.py /path/to/your/app

# 2. Scan codebase + verify live/staging URL headers, CORS & exposed files (.env, .git)
python3 scripts/aegis_scan.py /path/to/your/app --url https://staging.yourapp.com

# 3. Export structured JSON report for CI/CD or agent ingestion
python3 scripts/aegis_scan.py /path/to/your/app --json --output .aegis/scan-report.json

# 4. CI gate — exit code 1 if any CRITICAL or HIGH finding exists
python3 scripts/aegis_scan.py /path/to/your/app --fail-on-high
```

### Scanner CLI Reference

**Output**

| Argument | Description |
| :--- | :--- |
| `target` | Path to the repository to scan (default `.`) |
| `--json` | Print the full JSON report to stdout |
| `--output <PATH>` | Write the JSON report to a file (parent directories are created) |
| `--sarif <PATH>` | Write SARIF 2.1.0 so findings appear in GitHub's Security tab |
| `--sbom <PATH>` | Write a CycloneDX 1.5 SBOM of all detected dependencies |
| `--quiet` | Print only the one-line summary |

**Release gate**

| Argument | Description |
| :--- | :--- |
| `--fail-on-high` | Exit `1` if any `CRITICAL` or `HIGH` finding exists |
| `--fail-on <level>` | Exit `1` at or above `critical`/`high`/`medium`/`low` |
| `--include-tests` | Also audit test and fixture files (excluded by default — they contain deliberately insecure code) |
| `--fail-on-incomplete` | Exit `1` if any check could not run, **or if zero source files were scanned** — use when a green pipeline must mean *fully audited*, not merely *nothing found* |
| `--min-confidence <level>` | `high` / `medium` / `low` (default `low`). Only findings at or above this confidence affect the **exit code**; everything is still reported |

**Three axes, not one.** A release gate is lied to in three different ways, so they are kept apart:

| Axis | Question | Gate |
| :--- | :--- | :--- |
| **Coverage** | Did the check actually run? | `--fail-on-incomplete` |
| **Severity** | If this is real, how bad is it? | `--fail-on-high` / `--fail-on` |
| **Confidence** | How sure are we it is real? | `--min-confidence` |

Some rules cannot prove their case — `SEC-03` matches a list of known auth helpers and
cannot recognise a guard it has never seen; `REL-*` cannot know your data volume. Those are
reported at `MEDIUM` confidence. `--min-confidence high` gates only on what is demonstrable:

```bash
# Block only on findings the scanner can actually prove, but still refuse to
# certify an audit that did not fully run.
python3 scripts/aegis_scan.py . --fail-on-high --min-confidence high --fail-on-incomplete
```

A coverage gap can never be suppressed. `.aegis-ignore` and `--baseline` accept known
*defects*; a check that did not run carries nothing to accept, so gaps are always reported
and `--write-baseline` refuses to record them.

**Scope — how you adopt this on a real codebase**

| Argument | Description |
| :--- | :--- |
| `--diff [REF]` | Scan only files changed vs `REF` (default `origin/main`). Ideal for pull requests |
| `--baseline <PATH>` | Suppress findings recorded in a baseline file |
| `--write-baseline <PATH>` | Accept every current finding as pre-existing, so future scans show only new issues |

**Deep analysis**

| Argument | Description |
| :--- | :--- |
| `--artifact [PATH]` | Verify a build directory or an `.apk`/`.aab`/`.ipa`. Auto-detects `dist/`, `build/`, `.next/` |
| `--git-history [N]` | Hunt credentials committed in the last `N` commits (default 300) |
| `--deps` | Check dependencies against the OSV vulnerability database |
| `--url <URL>` | Passive, read-only live header & exposure checks |
| `--all` | Enable artifacts + git history + dependencies |
| `--offline` | Never make a network request |

**What leaves your machine.** The scanner is offline by default and sends nothing anywhere —
there is no telemetry, ever. Exactly two flags make a network request, and both are opt-in:

| Flag | Request | What is disclosed |
| :--- | :--- | :--- |
| `--deps` (also via `--all`) | `POST https://api.osv.dev/v1/querybatch` | Your dependency **names and versions** — not your source, not your file names |
| `--url <URL>` | `GET` against the URL you supply | Nothing of yours; it reads your own deployment's headers |

`--offline` hard-disables both. A stage that could not reach the network is recorded as a
coverage gap (`DEP-00` / `LIVE-00`) and **blocks** a `READY TO PUBLISH` verdict rather than
silently passing.

**Credentials in reports are redacted** to first 6 + last 4 characters before anything is
written, so `.aegis/scan-report.json` is safe to commit, attach to an issue, or upload as a
CI artifact.

**Exit codes:** `0` success · `1` blocking findings with a gate flag · `2` target path does not exist.

Also honoured: a `.aegis-ignore` file in the repo root, one entry per line — either a rule id (`SEC-03`) or a path glob (`src/legacy/**`).

## 🔍 Complete Audit Coverage Matrix (Low to Critical)

### A. Security & Architecture Safeguards

| ID | Category | Severity | What Vibe Aegis Catches |
| :--- | :--- | :--- | :--- |
| `SEC-01` | **Client-Exposed Secrets** | Critical | Private keys or tokens in `NEXT_PUBLIC_`, `VITE_`, `EXPO_PUBLIC_`, `REACT_APP_`, or hardcoded in source files |
| `SEC-02` | **Database RLS Disabled** | Critical | Supabase/PostgreSQL tables without `ENABLE ROW LEVEL SECURITY` or permissive `USING (true)` policies; Firebase `allow read, write: if true` |
| `SEC-03` | **Unprotected API / Server Actions** | Critical | Next.js `/api/*` routes, `"use server"` actions, FastAPI, or Express mutations lacking session/auth verification |
| `SEC-04` | **Broken Access Control (IDOR)** | Critical | Queries fetching/mutating records by user-supplied `id` without scoping to `auth.uid()` / authenticated session owner |
| `SEC-05` | **Payment & Checkout Tampering** | Critical | Trusting client-submitted prices, plan tiers, or quantities in Stripe/Razorpay checkout sessions |
| `SEC-06` | **Unverified Webhooks** | Critical | Payment or auth webhooks processing payloads without cryptographic signature verification (`stripe.webhooks.constructEvent`) |
| `SEC-07` | **SQL / Raw Query Injection** | High | String interpolation in SQL, `prisma.$queryRawUnsafe()`, `sequelize.query()`, or Python `cursor.execute(f"...")` |
| `SEC-08` | **Command & Code Injection** | High | Unsanitized input passed to `child_process.exec`, `eval()`, `new Function()`, `os.system()`, or `subprocess(..., shell=True)` |
| `SEC-09` | **Cross-Site Scripting (XSS)** | High | Unsanitized `dangerouslySetInnerHTML`, `v-html`, `innerHTML`, or `javascript:` URLs in user-controlled hrefs |
| `SEC-10` | **JWT & Session Flaws** | High | `jwt.decode()` used without `jwt.verify()`, weak JWT secrets, or sensitive auth tokens stored in `localStorage` |
| `SEC-11` | **Server-Side Request Forgery (SSRF)** | High | Server endpoints fetching user-supplied URLs without allowlisting or private-IP (`127.0.0.1`, `169.254.169.254`) blocking |
| `SEC-12` | **AI / LLM Prompt Injection & Spend** | High | Unbounded LLM endpoints without auth, rate limiting, max-token caps, or system/user prompt boundary separation |
| `SEC-13` | **Wildcard CORS & CSRF** | High | `Access-Control-Allow-Origin: *` combined with credentials, or cookie-authenticated state changes lacking CSRF protection |
| `SEC-14` | **Missing Rate Limiting** | Medium | Auth login, OTP, password reset, AI generation, and email endpoints lacking IP/user rate limiters |
| `SEC-15` | **Insecure File Uploads** | Medium | Upload handlers accepting arbitrary MIME types, missing size limits, or storing files with user-supplied paths (path traversal) |
| `SEC-16` | **Supply-Chain & Slopsquatting** | Medium | Unpinned dependencies, suspicious AI-hallucinated package names, or lockfile mismatches |
| `SEC-17` | **Live Posture & Exposed Artifacts** | Low–Crit | Publicly reachable `.env`, `.git/config`, `.map` source maps, debug endpoints, or missing CSP / HSTS / `X-Frame-Options` headers |

### B. UI/UX Design & Frontend QA Bug Finder

**The element must match the behaviour.** If it performs an action it is a `<button>`; if it navigates it is an `<a>` with a real `href`. Get that right and the browser supplies focus, Tab order, Enter *and* Space, and the correct screen-reader role for free — no `role`, `tabIndex` or `onKeyDown` needed. These three rules are separated because each has a different fix.

| ID | Category | Severity | What Vibe Aegis Catches |
| :--- | :--- | :--- | :--- |
| `UX-01` | **Dead Buttons & Placeholder Links** | High | A control that does nothing: `<a href="#">` with no handler, or `onClick={() => {}}` / `console.log` stubs |
| `UX-11` | **Action Rendered As A Link** | High | `<a href="#" onClick={...}>` or `href="javascript:"` — works with a mouse, but screen readers announce "link", Space does not activate it, and the page jumps to top. Use `<button>` |
| `UX-12` | **Clickable `div` / `span`** | High | An `onClick` on a non-interactive element with no `role` or `tabIndex` — unreachable by Tab, unusable by keyboard, announced as plain text |
| `UX-02` | **Missing Async Loading / Disabled State** | High | Async form submissions or mutation buttons that don't disable during flight, allowing duplicate charges or duplicate records |
| `UX-03` | **Silent Catch & Missing Error Feedback** | High | `catch (err) {}` blocks that swallow API failures without showing a toast, inline error message, or fallback UI |
| `UX-04` | **Missing Empty & Skeleton States** | Medium | `.map()` list renders that show a blank screen when the array is empty (`length === 0`) or loading |
| `UX-05` | **Mobile Viewport & Overflow Traps** | Medium | Fixed pixel widths (`w-[600px]`, `min-w-[500px]`, `width: 700px`) and `100vw` containers causing horizontal scrollbars on mobile |
| `UX-06` | **Form Accessibility & Validation Gaps** | Medium | `<input>`, `<select>`, or `<textarea>` missing associated `<label>`, `id`/`name`, or accessible error states |
| `UX-07` | **Icon Buttons & Image Accessibility** | Medium | Icon-only buttons without `aria-label` and `<img>` tags missing `alt` attributes |
| `UX-08` | **Focus Ring Suppression** | Low | `outline-none` or `outline: 0` applied without a replacement `focus-visible:ring` keyboard indicator |
| `UX-09` | **Unfinished AI Placeholders in UI** | High | Leftover `"Lorem ipsum"`, `"TODO:"`, `"placeholder"`, `"example.com"`, or fake `$99,999` mock metrics in production views |
| `UX-10` | **Z-Index & Modal Scroll Traps** | Low | Arbitrary `z-[99999]` collisions or modals that lock `document.body.style.overflow` without cleanup on unmount |

### C. Payments & Business Logic

| ID | Category | Severity | What it catches |
| :--- | :--- | :--- | :--- |
| `PAY-01` | Client-trusted price | Critical | `amount`, `unit_amount`, `price`, `quantity`, `currency` or `discount` taken from the request body |
| `PAY-02` | Non-atomic balance update | High | Read-then-write on credits or balances — two parallel requests both succeed (double-spend) |
| `PAY-03` | Unverified webhook | Critical | Payment webhook without signature verification against the raw body |

### D. Backend Reliability & Privacy

| ID | Category | Severity | What it catches |
| :--- | :--- | :--- | :--- |
| `REL-01` | Unbounded query | Medium | `findMany()` with no `take` — fine at 100 rows, fatal at 100,000 |
| `REL-02` | N+1 query loop | Medium | A database `await` inside a `for` loop or `.map(async …)` |
| `REL-03` | Sensitive data in logs | High | Passwords, tokens, API keys or PII passed to `console.log` or a logger |
| `REL-04` | Missing timeout | Medium | `await fetch()` with no `AbortSignal.timeout()` — a hung upstream eats your concurrency |

`REL` findings are reported at `MEDIUM` confidence: a pattern cannot know your data volume, so the Skeptic stage confirms against real table sizes.

### E. Data-Flow Analysis (follows the value, not the pattern)

A regex says *"there is a template literal in a query."* Taint analysis says *"**this** value came from the request and reaches **that** query unvalidated."* Input is traced from request sources (`req.body`, `req.json()`, `searchParams.get`, `formData.get`, route `params`) through assignments to dangerous sinks. A value that passes a validator (`zod.parse`, `parseInt`, `encodeURIComponent`, an allowlist check) is treated as clean and **not** reported.

| ID | Flow | Severity |
| :--- | :--- | :--- |
| `FLOW-01` | Request input reaches a raw SQL query | Critical |
| `FLOW-02` | Request input reaches a shell or code-execution sink | Critical |
| `FLOW-03` | Request input reaches an HTML rendering sink | High |
| `FLOW-04` | Request input reaches a server-side fetch (SSRF) | High |
| `FLOW-05` | Request input reaches a filesystem path | High |

Reported at `MEDIUM` confidence by design — the tracker works within a function scope, so the Skeptic stage confirms before anything is called CONFIRMED.

### F. Shipped-Artifact Verification (what your users actually receive)

Source code says what you wrote. The build output says what ships. Because the scanner already read your source, it can **cross-reference** — turning a guess into proof.

| ID | Category | Severity | What it proves |
| :--- | :--- | :--- | :--- |
| `ART-01` | **Confirmed secret leak** | Critical | A credential from your source is present in the shipped bundle. Confirmed by construction |
| `ART-02` | Source map shipped | Medium / Low | With `sourcesContent`, your original unminified source reaches every visitor |
| `ART-03` | Credential in bundle | Critical–Medium | A provider-format key found directly in shipped JS/HTML/JSON |
| `ART-11` | Unsigned package | High | Neither a v1 signature under `META-INF/` nor a v2/v3 APK Signing Block. A v2-only release (the modern default) is correctly recognised as signed; an unreadable archive or an `.aab` reports `ART-10` instead of guessing |
| `ART-12` | Config bundled in app | Critical | `.env`, `id_rsa` or `service-account.json` inside the `.apk`/`.aab`/`.ipa` |
| `ART-13` | Cleartext traffic | Medium | Manifest references cleartext HTTP |
| `ART-14` | Debuggable release | Medium | The `debuggable` attribute appears in the manifest. A binary manifest stores the *value* separately, so correct `debuggable="false"` hardening looks identical — verify with `aapt dump badging` |
| `ART-15` | Credential in package | Critical–Medium | A key embedded in packaged assets, resources or code |

### G. Supply Chain & Git History

| ID | Category | Severity | What it catches |
| :--- | :--- | :--- | :--- |
| `DEP-01` | Known dependency vulnerability | Medium | Package versions with OSV advisories (npm, PyPI, crates.io, Go) |
| `HIST-01` | Credential in git history | Critical–Medium | A key committed at any point — **even if deleted later**, it is still readable and still compromised |

### Rule Variants

Some rules have narrower sub-variants, reported with their own id so you can suppress them individually:

| ID | Covers |
| :--- | :--- |
| `SEC-01B` | Secret-named value exposed through a client-bundled env prefix |
| `SEC-01C` | `.env` present in the project root but not in `.gitignore` |
| `SEC-02B` | Permissive Firebase / Firestore rule (`allow read, write: if true`) |
| `SEC-10B` | Auth token stored in `localStorage` rather than an HttpOnly cookie |
| `SEC-17B` | `/.env` or `/.git/config` publicly reachable on the live server |
| `DEP-00`, `LIVE-00`, `GIT-00`, `ART-10` | **Coverage gaps**, not defects — a check that could not run. Any id ending `-00` is always a gap |

### Secret Detection Precision

A noisy scanner gets uninstalled. Credential rules only fire on real provider key shapes (AWS, Stripe, GitHub, Google, Slack, OpenAI, Anthropic, SendGrid, Twilio, Razorpay, npm, PEM private keys, Supabase service-role JWTs, database URLs with inline credentials) or on secret-named variables holding high-entropy values. Placeholders such as `your-api-key-here`, `changeme`, `${process.env.X}` and AWS's own documentation key `AKIAIOSFODNN7EXAMPLE` are rejected.

**Every credential in every report is redacted** to its first 6 and last 4 characters, so `.aegis/scan-report.json` is safe to commit, attach to an issue, or hand to an agent.

### Fail-Closed: Coverage Is Not Severity

A check that **could not run** is an unknown, not a pass. The gate fails closed:

| Condition | Verdict |
| :--- | :--- |
| 0 source files scanned | `INCOMPLETE_SCAN` — score forced to 0 |
| Any `CRITICAL` / `HIGH` open | `BLOCKED` |
| Any check skipped or errored | `VERIFIED_PARTIAL - INCOMPLETE_SCAN` |
| Score < 90, nothing skipped | `NEEDS REVIEW` |
| Files scanned · nothing skipped · no `CRITICAL`/`HIGH` · score ≥ 90 | **`READY TO PUBLISH`** |

`READY TO PUBLISH` requires **all four** conditions. Pass `allow_skipped=True` to `compute_readiness_score()` to override deliberately.

Called in isolation, `compute_readiness_score([DEP-00])` also fails closed — any rule id ending `-00` is treated as a coverage gap regardless of how the `Finding` was built. Skipped checks (offline mode, an unreachable URL or OSV, an unopenable package) are reported separately in `skipped_checks`, never counted in the score, and they force the verdict to `INCOMPLETE`:

```text
Readiness Score  : 100/100 - INCOMPLETE (1 check did not run: Dependency
                   Vulnerability Check Skipped). Not certified.

CHECKS THAT DID NOT RUN (1) - result UNKNOWN, not clean:
  - Dependency Vulnerability Check Skipped (offline mode)
```

`READY TO PUBLISH` is only ever issued for a **complete** audit. Use `--fail-on-incomplete` to enforce that in CI.

### Release Readiness Score

The scanner starts at **100** and subtracts **25** per `CRITICAL`, **10** per `HIGH`, **4** per `MEDIUM` and **1** per `LOW`, floored at `0`.

| Condition | Verdict |
| :--- | :--- |
| Any open `CRITICAL` or `HIGH` | `BLOCKED (Fix Critical/High findings before publishing)` |
| Score ≥ 90, no blockers | `READY TO PUBLISH` |
| Score < 90, no blockers | `NEEDS REVIEW (Address Medium/Low polish items)` |

## 🖥️ How to Use Across Every AI Coding Agent

| AI Agent / IDE | Installed Files | How to Trigger the Full Audit Loop |
| :--- | :--- | :--- |
| **Claude Code** | `.claude/skills/vibe-aegis/SKILL.md`, `.claude/commands/aegis.md`, `CLAUDE.md` | Type `/aegis` or `/aegis --fix` in Claude Code |
| **VS Code (GitHub Copilot)** | `.github/copilot-instructions.md`, `.github/prompts/aegis-audit.prompt.md`, `.vscode/tasks.json` | Run `/aegis-audit` in Copilot Chat or run task `Vibe Aegis: Full Audit` |
| **OpenAI Codex** | `.agents/skills/vibe-aegis/SKILL.md`, `AGENTS.md` | Type `$vibe-aegis` or ask *"Run the Vibe Aegis security and UI/UX audit loop"* |
| **Cursor** | `.cursor/rules/vibe-aegis.mdc`, `.cursorrules`, `AGENTS.md` | Tag `@vibe-aegis.mdc` or ask *"Run the Vibe Aegis pre-publish audit loop"* |
| **Windsurf / Cline / Gemini CLI** | `.windsurf/rules/vibe-aegis.md`, `.clinerules`, `GEMINI.md`, `AGENTS.md` | Ask *"Run the Vibe Aegis security and UI/UX audit loop on this repo"* |
| **Any AI chat (ChatGPT, Claude, Gemini, Perplexity, Grok)** | none — remote fetch | Paste the 2-line prompt at the top of this README |

## 🤖 AI-First Discoverability

This repository is built to be consumed by AI agents in a single pass:

| File | Purpose |
| :--- | :--- |
| [`llms.txt`](llms.txt) | Structured index following the llms.txt standard: summary, one-line remote execution prompts, and a complete annotated file map |
| [`llms-full.txt`](llms-full.txt) | Self-contained document holding the README, agent rules, all three skills, the CLI reference, and the JSON report schema |
| [`schemas/scan-report.schema.json`](schemas/scan-report.schema.json) | Draft 2020-12 JSON Schema so CI pipelines and agents can validate `.aegis/scan-report.json` deterministically |
| [`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json) | Plugin marketplace registration for Claude Code and OpenAI Codex |
| [`docs/prompts/`](docs/prompts/) | Three copy-paste bootstrap prompt recipes requiring no clone |

## 📁 Repository Structure

```text
vibe-aegis/
├── README.md                                  # Full documentation & usage guide
├── llms.txt                                   # AI-agent index (llms.txt standard) with remote execution prompts
├── llms-full.txt                              # Entire framework in one fetchable document
├── AGENTS.md                                  # Universal always-on safeguard rules (Codex, Cursor, Windsurf, Copilot)
├── CLAUDE.md                                  # Claude Code bridge & workflow triggers
├── SECURITY.md                                # Defensive scope, passive --url behaviour, vulnerability reporting
├── CONTRIBUTING.md                            # How to add SEC-XX / UX-XX rules with tests
├── CHANGELOG.md                               # Release history
├── LICENSE                                    # MIT License
├── package.json                               # NPX installer & CLI entry point
├── install.sh                                 # Universal zero-dependency shell installer
├── bin/
│   └── vibe-aegis.mjs                         # Node CLI wrapper (`npx vibe-aegis setup | scan`)
├── scripts/
│   └── aegis_scan.py                          # Deterministic 40+ rule static + live HTTP security & UI/UX scanner
├── schemas/
│   └── scan-report.schema.json                # JSON Schema (Draft 2020-12) for .aegis/scan-report.json
├── skills/
│   ├── vibe-aegis/
│   │   ├── SKILL.md                           # Master 10-stage orchestrator skill
│   │   └── agents/openai.yaml                 # OpenAI/Codex workspace skill metadata
│   ├── security-redteam-loop/
│   │   ├── SKILL.md                           # Deep security auditor skill (OWASP, RLS, Auth, Payments, AI/LLM)
│   │   └── agents/openai.yaml                 # OpenAI/Codex workspace skill metadata
│   ├── ui-ux-bug-finder/
│   │   ├── SKILL.md                           # Deep UI/UX, layout, state & accessibility skill
│   │   └── agents/openai.yaml                 # OpenAI/Codex workspace skill metadata
│   └── artifact-leak-hunter/
│       ├── SKILL.md                           # Verify what the build actually ships (bundles, maps, APK)
│       └── agents/openai.yaml                 # OpenAI/Codex workspace skill metadata
├── docs/
│   └── prompts/
│       ├── 01-full-prelaunch-audit.md         # Full 10-stage Security + UI/UX audit prompt
│       ├── 02-security-redteam-loop.md        # Security-only deep red-team prompt
│       └── 03-ui-ux-and-browser-qa.md         # UI/UX & accessibility browser QA prompt
├── adapters/
│   ├── claude/aegis.md                        # Claude Code `/aegis` slash command
│   ├── vscode/                                # Copilot instructions, prompt file, VS Code task
│   ├── cursor/vibe-aegis.mdc                  # Cursor `.cursor/rules/` rule file
│   └── github-actions/vibe-aegis-ci.yml       # Ready-to-use GitHub Actions pre-merge gate
├── .claude-plugin/
│   ├── marketplace.json                       # Claude Code / Codex plugin marketplace manifest
│   └── plugin.json                            # Plugin manifest (4 skills + /aegis command)
├── .github/
│   └── workflows/ci.yml                       # Unit tests, installer smoke test, schema validation
└── tests/
    └── test_scanner.py                        # Automated unit test suite for `aegis_scan.py`
```

## 🧪 Development

```bash
# Run the unit test suite
python3 -B -m unittest discover -s tests -v

# Smoke-test the installer
bash install.sh --target /tmp/test-app --agent all
```

See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the rule-authoring guide and severity rubric.

## ⚖️ Responsible Use & Scope

Vibe Aegis is a **defensive pre-deployment security and UI/UX quality assurance framework**. Its live URL posture checks (`--url`) perform strictly passive, read-only HTTP `GET` requests to inspect security headers and accidental file exposure. It sends no payloads and no credentials.

**Only scan applications and deployments that you own or have explicit authorization to test.** See [`SECURITY.md`](SECURITY.md) for the full scope statement and vulnerability reporting process.

## 📄 License

[MIT](LICENSE) © Tacuns

---

# =============================================================================
# PART 2: AGENTS.md - ALWAYS-ON ENGINEERING RULES
# =============================================================================

These rules apply while code is being written, not only during an audit. The installer
places this file as `AGENTS.md`, `.cursorrules`, `.clinerules`, `GEMINI.md` and
`.windsurf/rules/vibe-aegis.md`.

# 🛡️ Vibe Aegis — Always-On Security & UI/UX Engineering Rules

You are operating in a repository protected by **Vibe Aegis**. Every code change you write or review must satisfy both **Defensive Security Rules** and **UI/UX Production Quality Rules** before completion.

## 1. Non-Negotiable Security Rules (Prevent Vulnerabilities While Writing Code)

1. **Zero Client-Side Secrets (`SEC-01`)**:
   - Never place private API keys, database URLs, service-role keys, or webhook secrets in client-exposed variables (`NEXT_PUBLIC_*`, `VITE_*`, `EXPO_PUBLIC_*`, `REACT_APP_*`) or source files.
   - Keep `.env`, `.env.local`, and `.env.*` in `.gitignore`. Only commit `.env.example` with blank placeholders.
2. **Database Row-Level Security & Ownership Scoping (`SEC-02`, `SEC-04`)**:
   - Every Supabase/PostgreSQL table storing user or tenant data must run `ALTER TABLE <name> ENABLE ROW LEVEL SECURITY;` with explicit `SELECT`, `INSERT`, `UPDATE`, and `DELETE` policies scoped to `auth.uid()`. Never use `USING (true)` on non-public tables.
   - Every database read, update, or delete by ID must filter by the authenticated user's session ID or tenant ID (preventing IDOR).
3. **Server-Side Authentication & Input Validation (`SEC-03`, `SEC-07`, `SEC-08`)**:
   - Authenticate every API route, Server Action (`"use server"`), and RPC handler on the server. UI route hiding or client-side checks are never a security boundary.
   - Validate all external inputs (body, query, params, headers) using schema validators (e.g., `zod`, `pydantic`) before touching business logic.
   - Always use parameterized queries or safe ORM methods. Never interpolate strings into SQL, `$queryRawUnsafe`, or shell commands (`exec`, `subprocess` with `shell=True`).
4. **Payments, Webhooks & Rate Limiting (`SEC-05`, `SEC-06`, `SEC-12`, `SEC-14`)**:
   - Never trust client-submitted prices, discounts, or plan IDs; look up pricing on the server from trusted product tables.
   - Verify cryptographic signatures on every incoming webhook (`stripe.webhooks.constructEvent`, HMAC verification) using the raw request body.
   - Enforce rate limiting and token/cost budgets on login, OTP, password reset, email, and AI/LLM generation endpoints.
5. **Safe Output Rendering & Headers (`SEC-09`, `SEC-10`, `SEC-13`)**:
   - Never render unsanitized HTML via `dangerouslySetInnerHTML`, `v-html`, or `innerHTML`.
   - Store session tokens in `HttpOnly; Secure; SameSite=Lax/Strict` cookies—never in `localStorage`.

5. **Payments & Entitlements (`PAY-01`, `PAY-02`, `PAY-03`)**:
   - Never accept `amount`, `unit_amount`, `price`, `quantity`, `currency` or `discount` from the client. Take a plan or product ID and resolve the real price on the server.
   - Verify every webhook signature against the raw unparsed body, and store each processed `event.id` under a unique constraint so a replay cannot grant an entitlement twice.
   - Never read a balance, decide, then write it back. Use one atomic statement: `UPDATE wallets SET balance = balance - $1 WHERE user_id = $2 AND balance >= $1`, and treat zero affected rows as insufficient funds.
6. **Reliability & Privacy (`REL-01` to `REL-04`)**:
   - Every list query needs an explicit maximum page size. `findMany()` with no `take` loads the whole table into memory.
   - Never `await` a database call inside a loop. Batch with `WHERE id IN (...)` or a join.
   - Attach `AbortSignal.timeout(10000)` to outbound `fetch()` so a hung dependency cannot consume your concurrency budget.
   - Never log passwords, tokens, API keys or personal data. Log an identifier instead of the value.

## 2. Non-Negotiable UI/UX Quality Rules (Prevent Broken Frontend Experiences)

1. **Complete Interactive States (`UX-01`, `UX-02`, `UX-03`, `UX-04`)**:
   - Never leave dead buttons or placeholder links (`href="#"`, empty `onClick={() => {}}`, or `console.log` stubs). Every interactive control must wire to real behavior.
   - Every async button or form submission must disable during flight (`disabled={isLoading}`) and display a clear loading indicator to prevent double submissions.
   - Every data view or list must explicitly handle 4 states: **Loading** (skeleton/spinner), **Empty** (clear message + call-to-action), **Error** (actionable retry/error banner, never a silent `catch {}`), and **Populated**.
2. **Responsive Layout & Touch Ergonomics (`UX-05`, `UX-10`)**:
   - Design mobile-first (`320px–375px` up to `1440px+`). Never use rigid unguarded pixel widths (`w-[600px]`, `width: 800px`) that cause horizontal overflow on mobile screens.
   - Keep interactive touch targets at least `44x44px` on mobile and maintain a clear z-index scale for modals, dropdowns, and toasts.
3. **Accessibility Floor — WCAG 2.2 AA (`UX-06`, `UX-07`, `UX-08`)**:
   - Every form control (`<input>`, `<select>`, `<textarea>`) must have an associated `<label>` or `aria-label`.
   - Every icon-only button must include an `aria-label`, and every informative `<img>` must include a descriptive `alt` attribute.
   - Never remove keyboard focus rings (`outline-none`) without providing a high-contrast `focus-visible:ring` replacement.
4. **Zero Synthetic Placeholders in Production Views (`UX-09`)**:
   - Never ship `"Lorem ipsum"`, `"TODO"`, `"john@example.com"`, or hardcoded fake metrics in user-facing components.

## 3. Running the Vibe Aegis 10-Stage Pre-Publish Audit Loop

Before publishing or merging major features, run the full Vibe Aegis loop:

1. Execute `python3 .aegis/scripts/aegis_scan.py . --json --output .aegis/scan-report.json` (or `python3 scripts/aegis_scan.py .`).
2. Follow the orchestration workflow in `.claude/skills/vibe-aegis/SKILL.md` (or `.agents/skills/vibe-aegis/SKILL.md`):
   - **Recon** -> **Security Hunter** -> **UI/UX Hunter** -> **Adversarial Skeptic** -> **Evidence Referee** -> **Guarded Fixer**.
3. Write the final verified scorecard to `.aegis/AUDIT_REPORT.md`. Do not declare an app ready for production until all `CRITICAL` and `HIGH` confirmed findings are resolved.

---

# =============================================================================
# PART 3: SKILL - `vibe-aegis` (MASTER 6-STAGE ORCHESTRATOR)
# =============================================================================

Source file: `skills/vibe-aegis/SKILL.md`

---
name: vibe-aegis
description: Master 10-stage First-to-Last full-stack safeguard loop for vibe-coded apps across 8 domains. Orchestrates deterministic triage, deep Low-to-Critical security auditing, UI/UX design & browser bug finding, adversarial false-positive filtering (Skeptic), evidence grading (Referee), and guarded branch auto-fixing. Use whenever the user asks to audit, secure, test UI/UX, or prepare an app for production.
---

# Vibe Aegis — Master 10-Stage Pre-Launch Audit & Hardening Loop

Run a complete, adversarial pre-publication audit across both **Application Security (Low to Critical)** and **UI/UX Design & Functional Completeness** before any vibe-coded application ships to production.

## When to Trigger

- The user types `/aegis`, `/aegis-audit`, or `$vibe-aegis`
- The user asks to "check if my app is safe to publish", "find security holes and UI/UX bugs", "run a pre-launch audit", or "harden this vibe-coded app"

## The 8 Domains

| # | Domain | Skill |
| :--- | :--- | :--- |
| 1 | Architecture, tenancy & RLS | `architecture-threat-model` |
| 2 | Application security | `security-redteam-loop` |
| 3 | Payments & business logic | `payments-logic-auditor` |
| 4 | AI / LLM | `ai-llm-security-shield` |
| 5 | Backend reliability & scale | `backend-reliability-scale` |
| 6 | UI/UX & accessibility | `ui-ux-bug-finder` |
| 7 | Shipped artifacts | `artifact-leak-hunter` |
| 8 | Production readiness | `production-preflight-gate` |

## 10-Stage Execution Protocol

### Stage 1: Deterministic Recon & Triage (`aegis_scan.py`)

Run the bundled zero-dependency scanner first so you never waste context guessing the stack:

```bash
# Full sweep: source + data-flow + git history + dependencies + build artifacts
python3 .aegis/scripts/aegis_scan.py . --all --output .aegis/scan-report.json

# Fallback if running directly from the vibe-aegis repo:
python3 scripts/aegis_scan.py . --all --output .aegis/scan-report.json

# Reviewing a pull request? Scan only what changed, and suppress pre-existing noise:
python3 .aegis/scripts/aegis_scan.py . --diff origin/main --baseline .aegis/baseline.json
```

The scanner now reports six domains: `SECURITY`, `UI_UX`, `DATAFLOW` (request input traced
to a dangerous sink), `SUPPLY_CHAIN` (known dependency vulnerabilities), `ARTIFACT` (what the
build actually ships) and `HISTORY` (credentials committed at any point). Credentials in the
report are always redacted, so `.aegis/scan-report.json` is safe to attach to an issue.

Read `.aegis/scan-report.json` to extract:
1. Detected frameworks, database/BaaS, auth libraries, payment SDKs, UI libraries, and AI SDKs.
2. All deterministic `SECURITY` and `UI_UX` candidate findings.
3. Map all public entry points (`app/api/**`, `pages/api/**`, `"use server"` actions, webhooks, public routes, and database schema/migrations).

### Stage 1.5: Architecture, Tenancy & Threat Model

Load `skills/architecture-threat-model/SKILL.md`. Map entry points, trust boundaries, assets and
actors, verify tenant isolation and Row-Level Security, and write `.aegis/THREAT_MODEL.md`.

Do this **before** line-level hunting. Without the map, a missing `aria-label` and a missing tenant
filter look like two findings of similar size. They are not.

### Stage 2: Deep Security Red-Team Hunter (Low -> Critical)

Load and follow the instructions in `skills/security-redteam-loop/SKILL.md` (or `.claude/skills/security-redteam-loop/SKILL.md`).
- Trace data flows across files—do not stop at single-line regex matches.
- Verify authentication, ownership scoping (IDOR), Row-Level Security (RLS), payment price integrity, webhook signatures, SSRF, SQLi/XSS/CSRF, JWT verification, rate limits, and LLM token/cost caps.
- Record each candidate finding with exact `file:line`, concrete trigger path, STRIDE category, and CWE ID.

### Stage 2.5: Payments, Webhooks & Race Conditions

Load `skills/payments-logic-auditor/SKILL.md`. Security bugs leak data; payment bugs leak money
while the app appears to work. Check server-side pricing authority (`PAY-01`), webhook signature
verification and idempotency (`PAY-03`), and atomic balance updates (`PAY-02`).

### Stage 2.6: AI / LLM Security & Spend

Load `skills/ai-llm-security-shield/SKILL.md`. Confirm every model call has authentication, rate
limits, an input cap and an explicit `max_tokens`. Map every untrusted text source reaching a
prompt, follow model output to its sinks, and state the blast radius of a successful injection.

### Stage 2.7: Backend Reliability & Scale

Load `skills/backend-reliability-scale/SKILL.md`. Find the failures that only appear under real
traffic: unbounded queries, N+1 loops, missing indexes, serverless connection exhaustion, missing
timeouts, and personal data written to logs.

### Stage 3: Deep UI/UX Design & Browser QA Hunter

Load and follow the instructions in `skills/ui-ux-bug-finder/SKILL.md` (or `.claude/skills/ui-ux-bug-finder/SKILL.md`).
- Inspect every user-facing page, form, modal, and navigation component.
- Check for dead buttons (`href="#"`, empty `onClick`), missing async `disabled`/`loading` states (double-submit bugs), missing empty/error states, mobile viewport overflow (`320px–375px`), z-index collisions, and WCAG 2.2 AA accessibility issues.
- If a local dev server is running and `agent-browser` or Playwright is installed, open the live app and inspect both desktop (`1440x900`) and mobile (`375x812`) viewports plus the accessibility tree (`agent-browser snapshot`).

### Stage 3.5: Shipped-Artifact Verification

Load and follow `skills/artifact-leak-hunter/SKILL.md`. Source code says what you wrote; the
build output says what users receive. Cross-reference the credentials found in Stage 2 against
`dist/`, `.next/`, `build/` and any `.apk`/`.aab`/`.ipa`.

An `ART-01` finding is the one result in this framework that is **confirmed by construction** -
the same value is demonstrably present in both the source and the shipped bundle. Never downgrade
it, and always give the rotation-first remediation order.

### Stage 4: Adversarial Skeptic (False-Positive Elimination)

Switch perspective to the **Skeptic**. For every candidate finding from Stages 1–3:
- Attempt to **disprove** the claim by checking upstream middleware (`middleware.ts`), layout auth guards, ORM automatic parameterization, framework auto-escaping, or parent responsive containers.
- If a defence completely blocks the trigger, mark the finding `DISMISSED` and cite the exact defensive `file:line`.
- `DATAFLOW` findings are reported at `MEDIUM` confidence by design: the tracker works within a
  single function scope, so confirm the value really is attacker-controlled and really is unvalidated
  before promoting one to `CONFIRMED`.
- `ART-01` is the exception - it is already confirmed evidence and must not be dismissed.
- A publishable key (Supabase anon, Stripe publishable, Firebase web config) in a bundle is **not**
  a leak. Instead verify the protection it depends on: an anon key is only safe when Row-Level
  Security is enabled and enforced. Check that, and report on the RLS, not the key.

### Stage 5: Evidence Referee & Release Readiness Report

Switch perspective to the **Referee**. Evaluate all surviving claims and write `.aegis/AUDIT_REPORT.md` containing:
1. **Release Readiness Score (0–100)** and Release Gate Status (`READY TO PUBLISH` vs `BLOCKED`).
2. **Confirmed Security Findings Table** (ordered `CRITICAL` -> `HIGH` -> `MEDIUM` -> `LOW` with `file:line`, CWE, trigger explanation, and exact code fix).
3. **Confirmed UI/UX & Accessibility Findings Table** (ordered `HIGH` -> `MEDIUM` -> `LOW` with component location, visual/interaction impact, and exact code fix).
4. **Dismissed False Positives Log** (showing why each dismissed item is already safe).

### Stage 6: Guarded Auto-Fix & Verification Loop (When `--fix` or Remediation is Requested)

Never edit source files during a scan-only run without user approval. When the user requests `--fix` or approves remediation:
1. Create a dedicated git branch (`git checkout -b aegis/hardening-$(date +%Y%m%d-%H%M)`).
2. Apply minimal, surgical fixes for each `CONFIRMED` finding in priority order (`CRITICAL` -> `HIGH` -> `MEDIUM` -> `LOW`).
3. Re-run `python3 .aegis/scripts/aegis_scan.py .` and the project's native typecheck/test/build command (`npm run build`, `npm test`, or `pytest`).
4. If any patch introduces a build or test failure, immediately revert that commit and flag the item for `MANUAL_REVIEW`.
5. Repeat until the Release Readiness Score reaches `>= 90/100` with zero open `CRITICAL` or `HIGH` issues.

### Stage 7: Production Pre-Flight Gate

Load `skills/production-preflight-gate/SKILL.md`. The final go/no-go: live HTTP posture, exposed
artifacts, container and CI hardening, privacy and account-deletion readiness, and operational
readiness (rollback, monitoring, tested backups).

Issue exactly one verdict - `READY`, `READY WITH KNOWN LIMITATIONS` or `NOT READY` - and say for
each section what was checked, how, and what was **not** covered. Never issue `READY` because a
check was not run; mark it `NOT VERIFIED` and say so.

---

# =============================================================================
# PART 4: SKILL - `security-redteam-loop` (LOW-TO-CRITICAL SECURITY AUDITOR)
# =============================================================================

Source file: `skills/security-redteam-loop/SKILL.md`

---
name: security-redteam-loop
description: Deep Low-to-Critical application security auditor for vibe-coded apps. Performs multi-file data-flow analysis, STRIDE threat modeling, OWASP Top 10 auditing, BaaS/RLS verification, payment flow validation, and AI/LLM endpoint hardening.
---

# Security Red-Team Loop — Low-to-Critical Vulnerability Auditor

Perform a thorough, defensive architectural and source-code security audit tailored to the exact failure modes of AI-generated ("vibe-coded") applications.

## Audit Checklist Across 5 Trust Boundaries

### 1. Secrets, Environment & Supply Chain (`CRITICAL` / `HIGH`)

- Verify no private keys, database connection strings, or service-role keys appear in client-bundled env vars (`NEXT_PUBLIC_*`, `VITE_*`, `EXPO_PUBLIC_*`, `REACT_APP_*`).
- Check git history and root files for committed `.env`, `.pem`, `.key`, or hardcoded bearer tokens.
- Verify all package dependencies in `package.json` or `requirements.txt` are legitimate packages (catching AI-hallucinated "slopsquatting" package names).

### 2. Authentication, Session & Access Control (`CRITICAL`)

- Enumerate every API route (`app/api/**`, `pages/api/**`, FastAPI `@app.post/put/delete`, Express routers) and every Next.js Server Action (`"use server"`).
- Confirm each route verifies the caller's session on the server before executing logic.
- Trace every database read/write that accepts an `id`, `userId`, `orgId`, or `slug` from the request. Confirm the query filters by the authenticated session owner (`WHERE id = $1 AND user_id = $2` or enforced RLS) to prevent **Insecure Direct Object Reference (IDOR)**.
- Check that JWTs are verified with `jwt.verify()` (never just `jwt.decode()`) and session tokens are stored in `HttpOnly; Secure; SameSite` cookies rather than `localStorage`.

### 3. Database & Backend-as-a-Service (Supabase / Firebase / SQL / Prisma) (`CRITICAL` / `HIGH`)

- Inspect all `.sql` migrations: every table in the `public` schema must enable Row-Level Security (`ALTER TABLE ... ENABLE ROW LEVEL SECURITY;`) and define granular policies. Flag any `USING (true)` policy on write operations or sensitive tables.
- Inspect `firestore.rules` / `database.rules.json`: flag `allow read, write: if true`.
- Check for raw SQL interpolation (`$queryRawUnsafe`, template literals inside `.query()`, Python `f"SELECT ..."`).

### 4. Payments, Webhooks & Business Logic (`CRITICAL` / `HIGH`)

- Trace Stripe, Razorpay, LemonSqueezy, or PayPal checkout creation: confirm prices, plan IDs, and trial eligibility are resolved on the server from trusted constants or database records—never from client request bodies.
- Confirm webhook endpoints verify cryptographic signatures (`stripe.webhooks.constructEvent`) using the raw unparsed request body and enforce idempotency against replay of already-processed `event.id`s.
- Check for race conditions (TOCTOU) in credit balances, coupon redemptions, or quota counters (require atomic `UPDATE ... SET credits = credits - 1 WHERE credits >= 1`).

### 5. AI/LLM Endpoints, Network & Deployment Posture (`HIGH` / `MEDIUM` / `LOW`)

- For apps calling OpenAI, Anthropic, Gemini, or open-weight models: verify authentication, per-user rate limits, explicit `max_tokens` / `maxTokens` caps, and separation between untrusted user data and system instructions.
- Check URL-fetching endpoints for Server-Side Request Forgery (SSRF) against internal metadata services (`169.254.169.254`, `localhost`).
- Verify production configuration sets `Content-Security-Policy`, `Strict-Transport-Security`, `X-Frame-Options`, `X-Content-Type-Options: nosniff`, and strict CORS origins.

---

# =============================================================================
# PART 5: SKILL - `ui-ux-bug-finder` (UI/UX, LAYOUT & ACCESSIBILITY AUDITOR)
# =============================================================================

Source file: `skills/ui-ux-bug-finder/SKILL.md`

---
name: ui-ux-bug-finder
description: Comprehensive UI/UX design, interaction flow, responsive layout, and WCAG 2.2 AA accessibility bug finder for vibe-coded apps. Detects dead buttons, missing loading/empty/error states, mobile overflow traps, z-index collisions, and live DOM layout defects.
---

# UI/UX Design & Browser QA Bug Finder

Audit frontend code and live rendered pages to catch the visual, interaction, state-management, and accessibility bugs frequently introduced during vibe coding.

## 5-Point UI/UX Inspection Protocol

### 1. Interactive Wiring & Dead Control Detection (`HIGH`)

- Scan all `<button>`, `<a>`, `<form>`, dropdowns, and action cards across every page/route.
- Flag any control with `href="#"`, missing `onClick` / `type="submit"`, or stubbed handlers (`() => {}` or `console.log`).

**Separate three distinct bugs - they have three different fixes:**

| Pattern | Rule | Why it is wrong | Fix |
| :--- | :--- | :--- | :--- |
| `<a href="#">Terms</a>` | `UX-01` | Goes nowhere | Give it a real destination |
| `<a href="#" onClick={del}>` | `UX-11` | Announced as "link" so the user expects navigation; Space does not activate it; `#` jumps to top and pollutes history | `<button type="button" onClick={del}>` |
| `<div onClick={go}>` | `UX-12` | Not focusable, not keyboard operable, announced as plain text | `<button type="button">` |

The principle: **if it performs an action it is a button; if it navigates it is a link with a real `href`.** Choose the right element and the browser gives you focus, Tab order, Enter *and* Space, and the correct role for free. Retrofitting a `<div>` requires `role="button"` **and** `tabIndex={0}` **and** an `onKeyDown` handling both Enter and Space - three things to get right instead of zero, which is why the real button is the better answer.

Do not flag a `<div>` that already carries `role`, `tabIndex` and a key handler - that is a correct retrofit.
- Verify every modal, drawer, and dialog has a working close button, `Escape` key dismissal, and cleans up body scroll locks on unmount.

### 2. Async State Matrix Completeness (`HIGH` / `MEDIUM`)

Verify that every component performing an async fetch or mutation explicitly implements all 4 states:
- **Loading State**: Skeleton loader or spinner shown; submit/action buttons set `disabled={isLoading}` to prevent duplicate submissions.
- **Empty State**: When a list or query returns `0` items, render a helpful empty state with a clear call-to-action instead of a blank void.
- **Error State**: When a fetch or mutation fails, catch the error and display a user-friendly alert, toast, or inline field error with a retry option (never swallow errors in an empty `catch {}`).
- **Success Feedback**: Confirm mutations give clear visual confirmation (toast, redirect, or optimistic UI update).

### 3. Responsive Layout & Mobile Viewport Audit (`MEDIUM`)

- Check layout behavior at **Mobile (`375x812`)**, **Tablet (`768x1024`)**, and **Desktop (`1440x900`)**.
- Flag hardcoded pixel widths (`w-[600px]`, `min-w-[500px]`, `width: 800px`), un-wrapped wide tables (`overflow-x-auto` missing), or `100vw` containers that cause horizontal scrolling on mobile.
- Ensure touch targets (buttons, nav links, close icons) are at least `44x44px` on mobile screens and do not overlap with fixed bottom bars or floating action buttons.

### 4. Accessibility & Keyboard Ergonomics — WCAG 2.2 AA (`MEDIUM` / `LOW`)

- Verify every `<input>`, `<select>`, and `<textarea>` is linked to a visible `<label>` or `aria-label`.
- Verify every icon-only `<button>` has an `aria-label` and every `<img />` has an `alt` attribute.
- Check color contrast pairings (avoid low-contrast muted text like `text-gray-300` on `bg-white` or `text-gray-600` on `bg-gray-900`).
- Ensure keyboard `Tab` order is logical and focus indicators (`focus-visible:ring-2`) are never stripped without replacement.

### 5. Live Browser DOM Inspection (When Dev Server + Browser Tool Available)

If the app is running locally and `agent-browser` or Playwright is installed:
```bash
agent-browser open http://localhost:3000
agent-browser set viewport 375 812
agent-browser snapshot
agent-browser screenshot --annotate .aegis/mobile-audit.png
agent-browser set viewport 1440 900
agent-browser screenshot --annotate .aegis/desktop-audit.png
agent-browser close
```
Inspect the accessibility tree and screenshots to verify zero overlapping elements, zero console errors, and clean visual alignment.

---

# =============================================================================
# PART 7: SCANNER CLI REFERENCE - `scripts/aegis_scan.py`
# =============================================================================

Zero-dependency Python 3.8+ static and passive-live scanner. No pip install required.

## Usage

```text
python3 scripts/aegis_scan.py [target] [--url URL] [--json] [--output PATH] [--fail-on-high]
```

## Arguments

**Output**

| Argument | Default | Description |
| :--- | :--- | :--- |
| `target` | `.` | Path to the repository to scan. Exits `2` if it does not exist. |
| `--json` | off | Print the full JSON report to stdout. |
| `--output <PATH>` | none | Write the JSON report to a file. Parent directories are created. |
| `--sarif <PATH>` | none | Write SARIF 2.1.0 so findings appear in GitHub's Security tab. |
| `--sbom <PATH>` | none | Write a CycloneDX 1.5 SBOM of detected dependencies. |
| `--quiet` | off | Print only the one-line summary. |

**Release gate**

| Argument | Description |
| :--- | :--- |
| `--fail-on-high` | Exit `1` if any `CRITICAL` or `HIGH` finding exists. |
| `--fail-on <level>` | Exit `1` at or above `critical`/`high`/`medium`/`low`. |

**Scope - how a team adopts this on an existing codebase**

| Argument | Description |
| :--- | :--- |
| `--diff [REF]` | Scan only files changed vs `REF` (default `origin/main`). Use for pull requests. |
| `--baseline <PATH>` | Suppress findings recorded in a baseline file. |
| `--write-baseline <PATH>` | Accept all current findings as pre-existing; future scans show only new issues. |

Also honoured: a `.aegis-ignore` file in the repo root, one entry per line, either a rule id
(`SEC-03`) or a path glob (`src/legacy/**`).

**Deep analysis**

| Argument | Description |
| :--- | :--- |
| `--artifact [PATH]` | Verify a build directory or an `.apk`/`.aab`/`.ipa`. Auto-detects `dist/`, `build/`, `out/`, `.next/`, `.output/`, `.svelte-kit/`. |
| `--git-history [N]` | Hunt credentials committed in the last `N` commits (default 300). |
| `--deps` | Check dependencies against the OSV vulnerability database. |
| `--url <URL>` | Passive, read-only live header and exposure checks. |
| `--all` | Enable artifacts + git history + dependencies. |
| `--offline` | Never make a network request. |

## Exit Codes

| Code | Meaning |
| :--- | :--- |
| `0` | Scan completed with no blocking findings, or no gate flag was set. |
| `1` | A gate flag was set and a finding met the threshold. |
| `2` | The target path does not exist. |

## Common Invocations

```bash
# Everything, machine-readable, for an agent or CI pipeline
python3 scripts/aegis_scan.py . --all --output .aegis/scan-report.json

# Verify what actually ships before deploying or uploading
python3 scripts/aegis_scan.py . --artifact dist/
python3 scripts/aegis_scan.py . --artifact app/build/outputs/apk/release/app-release.apk

# Pull-request review: only what changed, minus pre-existing noise
python3 scripts/aegis_scan.py . --diff origin/main --baseline .aegis/baseline.json --quiet

# First adoption on a large existing repo
python3 scripts/aegis_scan.py . --write-baseline .aegis/baseline.json

# GitHub code scanning + SBOM
python3 scripts/aegis_scan.py . --all --sarif .aegis/results.sarif --sbom .aegis/sbom.json

# CI merge gate
python3 scripts/aegis_scan.py . --fail-on-high
```

## What `--url` Actually Does

Strictly passive and read-only. It issues:

1. One `GET` to the supplied URL, reading response headers only. It checks for
   `Content-Security-Policy`, `X-Frame-Options`, `X-Content-Type-Options`,
   `Strict-Transport-Security` (HTTPS targets only), and a wildcard
   `Access-Control-Allow-Origin: *`.
2. One `GET` each to `/.env` and `/.git/config` to detect accidental public exposure,
   reading at most 512 bytes of the response.

It sends the User-Agent `VibeAegis-PreLaunch-Audit/1.0 (Passive-Read-Only)`, no credentials,
no payloads, and no `POST`/`PUT`/`DELETE`. It does not crawl or spider. If the URL is
unreachable the scanner records a `LIVE-00` LOW informational finding rather than failing.

**Only use `--url` against deployments you own or are authorized to test.**

## Release Readiness Score

The score starts at `100` and subtracts a weight per finding, floored at `0`:

| Severity | Penalty |
| :--- | :--- |
| `CRITICAL` | 25 |
| `HIGH` | 10 |
| `MEDIUM` | 4 |
| `LOW` | 1 |

| Condition | `release_verdict` |
| :--- | :--- |
| Any `CRITICAL` or `HIGH` present | `BLOCKED (Fix Critical/High findings before publishing)` |
| Score >= 90 and no blockers | `READY TO PUBLISH` |
| Score < 90 and no blockers | `NEEDS REVIEW (Address Medium/Low polish items)` |

## Rule Identifier Reference

- `SEC-01` .. `SEC-17` - security rules, `domain` is `SECURITY`.
- `SEC-17B` - live server exposure of `/.env` or `/.git/config`, `CRITICAL`.
- `LIVE-00` - the supplied `--url` could not be reached, `LOW`, informational only.
- `UX-01` .. `UX-10` - UI/UX rules, `domain` is `UI_UX`.
- `FLOW-01` .. `FLOW-05` - data-flow (taint) findings, `domain` is `DATAFLOW`, confidence `MEDIUM` by design.
- `DEP-00`/`DEP-01` - dependency vulnerabilities, `domain` is `SUPPLY_CHAIN`.
- `ART-01` .. `ART-15` - build artifact and mobile package findings, `domain` is `ARTIFACT`.
  `ART-01` is confirmed by construction (same credential present in both source and bundle) and must not be dismissed.
- `HIST-01` - credentials found in git history, `domain` is `HISTORY`.

## Reports Are Safe To Share

Every credential in every output format is redacted to its first 6 and last 4 characters plus a
length. `.aegis/scan-report.json` can be committed, attached to an issue, or handed to an agent
without leaking the value it is warning about.

---

# =============================================================================
# PART 8: JSON REPORT SCHEMA - `.aegis/scan-report.json`
# =============================================================================

Produced by `--output`. Validate with `schemas/scan-report.schema.json`
(JSON Schema Draft 2020-12). Top-level keys: `scanner`, `version`, `timestamp`,
`target_path`, `live_url`, `scanned_files`, `tech_stack`, `readiness_score`,
`release_verdict`, `summary_counts`, `findings`.

Each entry in `findings` has: `rule_id`, `domain` (`SECURITY` or `UI_UX`),
`severity` (`CRITICAL`/`HIGH`/`MEDIUM`/`LOW`), `title`, `file`, `line`, `snippet`,
`cwe_or_standard`, `remediation`, `confidence`.

Findings arrive pre-sorted: severity first (CRITICAL to LOW), then domain, file, line.

## Full Schema

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://raw.githubusercontent.com/Tacuns/vibe-aegis/main/schemas/scan-report.schema.json",
  "title": "Vibe Aegis Scan Report",
  "description": "Deterministic output of `python3 scripts/aegis_scan.py <target> --json --output .aegis/scan-report.json`. CI pipelines and AI agents can validate scan output against this schema before acting on it.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "scanner",
    "version",
    "timestamp",
    "target_path",
    "live_url",
    "stages",
    "scanned_files",
    "dependencies_parsed",
    "tech_stack",
    "readiness_score",
    "release_verdict",
    "summary_counts",
    "findings",
    "coverage",
    "skipped_checks"
  ],
  "properties": {
    "scanner": {
      "description": "Scanner identifier. Always the constant `vibe-aegis`.",
      "const": "vibe-aegis"
    },
    "version": {
      "description": "Semantic version of the scanner that produced this report.",
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+$"
    },
    "timestamp": {
      "description": "UTC ISO-8601 timestamp of when the scan completed.",
      "type": "string",
      "format": "date-time"
    },
    "target_path": {
      "description": "Absolute resolved filesystem path of the scanned repository.",
      "type": "string",
      "minLength": 1
    },
    "live_url": {
      "description": "The live or staging URL passed via `--url`, or null when only a static scan was run.",
      "type": [
        "string",
        "null"
      ]
    },
    "scanned_files": {
      "description": "Number of source files read during the static scan.",
      "type": "integer",
      "minimum": 0
    },
    "tech_stack": {
      "description": "Fingerprinted stack. Each key maps to the list of detected technologies in that category; an empty array means nothing was detected for it.",
      "type": "object",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "uniqueItems": true
      }
    },
    "readiness_score": {
      "description": "Release Readiness Score from 0 to 100. Starts at 100 and subtracts 25 per CRITICAL, 10 per HIGH, 4 per MEDIUM and 1 per LOW finding, floored at 0.",
      "type": "integer",
      "minimum": 0,
      "maximum": 100
    },
    "release_verdict": {
      "description": "Fail-closed release gate. One of: 'INCOMPLETE_SCAN (...)' when no source files were scanned; 'BLOCKED (...)' when any CRITICAL/HIGH is open; 'VERIFIED_PARTIAL - INCOMPLETE_SCAN (...)' when any check was skipped or errored; 'NEEDS REVIEW (...)' below 90; 'READY TO PUBLISH' only when files were scanned, nothing was skipped, there are no CRITICAL/HIGH findings and the score is >= 90.",
      "type": "string",
      "minLength": 1,
      "examples": [
        "READY TO PUBLISH",
        "NEEDS REVIEW (Address Medium/Low polish items)",
        "BLOCKED (Fix Critical/High findings before publishing)",
        "VERIFIED_PARTIAL - INCOMPLETE_SCAN (1 check skipped/offline: ...)",
        "INCOMPLETE_SCAN (0 source files scanned - cannot certify readiness)"
      ]
    },
    "summary_counts": {
      "description": "Finding tallies by severity and by domain.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "CRITICAL",
        "HIGH",
        "MEDIUM",
        "LOW",
        "SECURITY_TOTAL",
        "UI_UX_TOTAL",
        "SUPPLY_CHAIN_TOTAL",
        "ARTIFACT_TOTAL",
        "HISTORY_TOTAL",
        "DATAFLOW_TOTAL",
        "SUPPRESSED",
        "PAYMENTS_TOTAL",
        "RELIABILITY_TOTAL"
      ],
      "properties": {
        "CRITICAL": {
          "type": "integer",
          "minimum": 0
        },
        "HIGH": {
          "type": "integer",
          "minimum": 0
        },
        "MEDIUM": {
          "type": "integer",
          "minimum": 0
        },
        "LOW": {
          "type": "integer",
          "minimum": 0
        },
        "SECURITY_TOTAL": {
          "type": "integer",
          "minimum": 0
        },
        "UI_UX_TOTAL": {
          "type": "integer",
          "minimum": 0
        },
        "SUPPLY_CHAIN_TOTAL": {
          "type": "integer",
          "minimum": 0
        },
        "ARTIFACT_TOTAL": {
          "type": "integer",
          "minimum": 0
        },
        "HISTORY_TOTAL": {
          "type": "integer",
          "minimum": 0
        },
        "DATAFLOW_TOTAL": {
          "type": "integer",
          "minimum": 0
        },
        "SUPPRESSED": {
          "description": "Findings hidden by a baseline file or .aegis-ignore.",
          "type": "integer",
          "minimum": 0
        },
        "PAYMENTS_TOTAL": {
          "type": "integer",
          "minimum": 0
        },
        "RELIABILITY_TOTAL": {
          "type": "integer",
          "minimum": 0
        }
      }
    },
    "findings": {
      "description": "All deterministic findings, pre-sorted by severity (CRITICAL first), then domain, file and line.",
      "type": "array",
      "items": {
        "$ref": "#/$defs/finding"
      }
    },
    "stages": {
      "description": "Which analysis stages actually ran, e.g. static, diff:origin/main, git-history, dependencies, artifacts, live-url, baseline:<n>.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "dependencies_parsed": {
      "description": "Number of dependencies parsed from lockfiles and manifests (0 when the dependency stage did not run).",
      "type": "integer",
      "minimum": 0
    },
    "coverage": {
      "description": "Audit completeness, tracked separately from severity. A check that could not run is an UNKNOWN, not a clean result, and never contributes to the score.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "complete",
        "checks_skipped",
        "note"
      ],
      "properties": {
        "complete": {
          "description": "True only when every requested check ran.",
          "type": "boolean"
        },
        "checks_skipped": {
          "type": "integer",
          "minimum": 0
        },
        "note": {
          "type": "string"
        }
      }
    },
    "skipped_checks": {
      "description": "Checks that could not run (offline mode, unreachable URL or database, unopenable package). Same shape as a finding, but these are coverage gaps: they are excluded from readiness_score and summary_counts, and their presence forces release_verdict to INCOMPLETE.",
      "type": "array",
      "items": {
        "$ref": "#/$defs/finding"
      }
    }
  },
  "$defs": {
    "finding": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "rule_id",
        "domain",
        "severity",
        "title",
        "file",
        "line",
        "snippet",
        "cwe_or_standard",
        "remediation",
        "confidence",
        "fingerprint",
        "kind",
        "status"
      ],
      "properties": {
        "rule_id": {
          "description": "Stable rule identifier. SEC/UX/LIVE are source and live-posture rules; PAY is payments and business logic; REL is backend reliability and scale; FLOW is data-flow (taint) analysis; DEP is dependency vulnerabilities; ART is build-artifact and mobile-package findings; HIST is git-history forensics. A rule id ending in -00 is always a coverage gap, never a defect.",
          "type": "string",
          "pattern": "^(SEC|UX|LIVE|DEP|ART|HIST|GIT|FLOW|PAY|REL)-[0-9]{2}[A-Z]?$"
        },
        "domain": {
          "description": "Which analysis stage produced this finding.",
          "enum": [
            "SECURITY",
            "UI_UX",
            "PAYMENTS",
            "RELIABILITY",
            "SUPPLY_CHAIN",
            "ARTIFACT",
            "HISTORY",
            "DATAFLOW"
          ]
        },
        "severity": {
          "description": "Impact rating used by the Release Readiness Score.",
          "enum": [
            "CRITICAL",
            "HIGH",
            "MEDIUM",
            "LOW"
          ]
        },
        "title": {
          "description": "Short human-readable description of the defect.",
          "type": "string",
          "minLength": 1
        },
        "file": {
          "description": "Repository-relative file path, or the probed URL for live posture findings.",
          "type": "string",
          "minLength": 1
        },
        "line": {
          "description": "1-indexed line number, or 0 for findings that are not tied to a source line (live URL checks).",
          "type": "integer",
          "minimum": 0
        },
        "snippet": {
          "description": "Trimmed evidence excerpt. Credentials are always redacted (first 6 and last 4 characters only) so reports are safe to commit and share.",
          "type": "string"
        },
        "cwe_or_standard": {
          "description": "Cited authority: a CWE ID, an OWASP Top 10 category, or a WCAG 2.2 success criterion.",
          "type": "string",
          "minLength": 1
        },
        "remediation": {
          "description": "Concrete, actionable fix instruction.",
          "type": "string",
          "minLength": 1
        },
        "confidence": {
          "description": "Scanner confidence before the adversarial Skeptic stage reviews the claim.",
          "enum": [
            "HIGH",
            "MEDIUM",
            "LOW"
          ],
          "default": "HIGH"
        },
        "fingerprint": {
          "description": "Stable 16-hex-character id derived from rule, file and normalised evidence. Used for baseline suppression and SARIF partialFingerprints; survives line-number shifts.",
          "type": "string",
          "pattern": "^[0-9a-f]{16}$"
        },
        "kind": {
          "description": "'finding' is a real defect that counts toward the score. 'skipped_check' is a check that could not run - it never affects the score and forces an INCOMPLETE verdict.",
          "enum": [
            "finding",
            "skipped_check"
          ],
          "default": "finding"
        },
        "status": {
          "description": "VULNERABILITY is a real defect that counts toward the score. SKIPPED and SCAN_ERROR are coverage gaps: they never affect the score and they force release_verdict away from READY TO PUBLISH.",
          "enum": [
            "VULNERABILITY",
            "SKIPPED",
            "SCAN_ERROR"
          ],
          "default": "VULNERABILITY"
        }
      }
    }
  }
}
```

---

# END OF VIBE AEGIS COMPLETE FRAMEWORK

Repository: https://github.com/Tacuns/vibe-aegis
License: MIT
Report issues and contribute new SEC-XX / UX-XX rules: see CONTRIBUTING.md
Security policy and authorized-use scope: see SECURITY.md

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.