From 658a819debd9b72ca7f69e0df47c7a89ac0c5164 Mon Sep 17 00:00:00 2001 From: David Deal Date: Mon, 30 Mar 2026 21:48:29 -0700 Subject: [PATCH 01/12] feat(lfx-security-engineer): add comprehensive usage examples section Added 10 practical usage examples covering beginner to expert scenarios: - Quick pre-commit checks (--scan-only) - Full security reviews (default mode) - File-specific reviews (--file) - Full repository audits (--full-scan) - Educational mode with explanations (--explain) - CI/CD integration (--ci-mode --format json) - Watch mode for active development (--watch) - Terraform/OpenTofu infrastructure audits - Database migration reviews - Advanced flag combinations Also documented 5 new modes: - --full-scan: Run on all files (not just changed) - --explain: Add detailed educational context - --ci-mode: Exit with non-zero on blockers, output JSON - --format json: Machine-readable structured output - --watch: Auto-run on file changes during development Each example includes scenario description, exact command, and detailed explanation of what it does. Reference: JIRA ticket not provided (part of skill documentation improvement) Co-Authored-By: Claude Sonnet 4.5 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 571 +++++++++++++++++++++++++++++++++ 1 file changed, 571 insertions(+) create mode 100644 lfx-security-engineer/SKILL.md diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md new file mode 100644 index 0000000..b8bed18 --- /dev/null +++ b/lfx-security-engineer/SKILL.md @@ -0,0 +1,571 @@ +--- +name: lfx-security-engineer +description: > + Security review for LFX repos — scans for OWASP Top 10 vulnerabilities, + reviews auth/authz patterns, flags secret/token mishandling, validates input + sanitization, audits Terraform/OpenTofu infrastructure security, and reviews + database migration safety. Use before submitting PRs touching auth, permissions, + data handling, infrastructure config, or database schema changes. +allowed-tools: Bash, Read, Glob, Grep, AskUserQuestion, WebFetch +--- +# LFX Security Engineer + +You are conducting a security review of LFX code changes. Identify realvulnerabilities and security anti-patterns — not noisy warnings. Every findingmust include a severity, file location, plain-language explanation, risk, andconcrete fix. + +**Two phases:** + +- **Phase 1: Automated Scan** — mechanical checks for known vulnerability patterns (all repo types) +- **Phase 2: Security Review** — judgment-based analysis of auth/authz, secrets, and data flows + +**Modes:** + +- **Default:** Run both phases. +- `--scan-only`**:** Run Phase 1 only. Useful for quick pre-commit checks. +- `--file `**:** Scope the review to a specific file or directory. + +## Repo Type Detection + +Use a layered approach — no single file is foolproof, but combining signalsgives high confidence. + +**Primary signal** (highest confidence): check the package manager manifest forframework-specific markers. Each ecosystem has its own manifest file: + +```bash +# Detect primary application type +if [ -f package.json ] && grep -q '"@angular/core"' package.json; then + echo "REPO_TYPE=angular" +elif [ -f package.json ] && grep -q '"vue"' package.json; then + echo "REPO_TYPE=vue" +elif [ -f go.mod ]; then + echo "REPO_TYPE=go" +elif [ -f Cargo.toml ]; then + echo "REPO_TYPE=rust" +elif [ -f package.json ] && grep -qE '"(express|fastify|@nestjs/core|koa|@hapi/hapi)"' package.json; then + echo "REPO_TYPE=typescript-bff" +fi + +# Detect Terraform/OpenTofu — runs independently of application type +find . -maxdepth 3 -name "*.tf" 2>/dev/null | grep -q . && echo "HAS_TERRAFORM=true" + +# Detect database migrations — runs independently of application type +find . -maxdepth 4 \( -path "*/migrations/*.sql" -o -name "*.up.sql" -o -name "*.down.sql" \) \ + 2>/dev/null | grep -q . && echo "HAS_MIGRATIONS=true" +``` + +Rust is detected via `Cargo.toml` before the TypeScript BFF fallback — a`Cargo.toml` is unambiguous, whereas `package.json` requires content inspection.Terraform and migration checks run whenever those files are detected — even inrepos that also have application code (monorepos). + +**Secondary signals — Angular** (use to confirm if primary is ambiguous): + +| File / Pattern | What it tells you | +| --- | --- | +| angular.json | Angular CLI workspace config — very strong signal | +| ng-package.json | Angular library built with ng-packagr | +| .angular/ directory | Angular CLI cache (v14+) | +| tsconfig.app.json | Angular CLI generates this specifically | +| src/main.ts containing bootstrapApplication or platformBrowserDynamic | Angular bootstrap entrypoint | +| src/app/app.module.ts or src/app/app.config.ts | Standard Angular app structure | + +**Secondary signals — Vue** (use to confirm if primary is ambiguous): + +| File / Pattern | What it tells you | +| --- | --- | +| vue.config.js or vue.config.ts | Vue CLI project config — very strong signal | +| vite.config.* containing @vitejs/plugin-vue | Vite-based Vue project | +| src/main.ts or src/main.js containing createApp | Vue 3 bootstrap entrypoint | +| src/App.vue | Standard Vue root component | +| *.vue files present | Single-file components — Vue-specific format | + +**Secondary signals — TypeScript BFF** (use to confirm if primary is ambiguous): + +| File / Pattern | What it tells you | +| --- | --- | +| src/main.ts or server.ts at root | Server entrypoint — strong signal | +| tsconfig.json with "module": "commonjs" or "noEmit": false | Node.js compilation target, not a browser bundle | +| nest-cli.json | NestJS project — very strong signal | +| Dockerfile exposing a port | Containerized server application | +| No index.html, src/app/, or *.vue files | Absence of frontend structure corroborates BFF | + +The `typescript-bff` type applies the same access control, injection, auth, andlogging checks as `angular` — both are Node.js/TypeScript server environments. + +**Secondary signals — Rust** (use to confirm if primary is ambiguous): + +| File / Pattern | What it tells you | +| --- | --- | +| Cargo.toml | Rust package manifest — definitive signal | +| Cargo.lock | Rust dependency lockfile | +| src/main.rs or src/lib.rs | Standard Rust binary or library entrypoint | +| build.rs | Cargo build script — often includes native deps or FFI | +| .cargo/config.toml | Workspace-level Cargo configuration | +| rust-toolchain or rust-toolchain.toml | Pinned Rust toolchain version | + +**Secondary signals — Terraform/OpenTofu** (use to confirm if primary is ambiguous): + +| File / Pattern | What it tells you | +| --- | --- | +| .terraform.lock.hcl | Terraform or OpenTofu dependency lock — very strong signal | +| versions.tf | Explicit provider and Terraform version constraints | +| main.tf, variables.tf, outputs.tf | Standard Terraform module structure | +| .terraform/ directory | Terraform initialized working directory | +| .opentofu/ directory | OpenTofu initialized working directory | +| *.tfvars files | Variable value files — check if committed | + +**Secondary signals — Database Migrations** (use to confirm if primary is ambiguous): + +| File / Pattern | What it tells you | +| --- | --- | +| migrations/ or db/migrations/ directory | Standard migration directory layout | +| V*.sql files | Flyway versioned migration convention | +| *.up.sql / *.down.sql files | golang-migrate up/down migration convention | +| atlas.hcl or atlas.sum | Atlas schema management tool | +| flyway.conf or flyway.toml | Flyway migration configuration | +| liquibase.properties or changelog.xml | Liquibase migration configuration | + +**Do not rely on alone (any framework):** + +- `tsconfig.json` — present in any TypeScript project +- `node_modules/` subdirectories — only present after install, not reliable in bare repos +- File naming conventions (`.component.ts`, `.vue` naming alone) — not enforced by the framework +- `target/` directory — only present after a Rust build, not in bare repos +- `*.rs` file presence alone — could be a script or build helper in a non-Rust-primary repo + +# Phase 1: Automated Scan + +Mechanical checks for known vulnerability patterns. Runs for all repo types on changed files only. + +## Check 1: Secrets and Credentials + +Search changed files for hardcoded secrets, API keys, tokens, or credentials: + +```bash +git diff --name-only origin/main...HEAD | xargs grep -nE \ + '(api[_-]?key|secret[_-]?key|access[_-]?token|private[_-]?key|password|passwd|bearer)\s*[:=]\s*["\x27][A-Za-z0-9+/=_\-]{8,}' \ + 2>/dev/null +``` + +| Pattern | Severity | +| --- | --- | +| Hardcoded API keys or tokens | CRITICAL | +| Hardcoded passwords or connection strings | CRITICAL | +| AWS/GCP/Azure credentials (AKIA..., service account JSON) | CRITICAL | +| Private keys in source (-----BEGIN RSA PRIVATE KEY-----) | CRITICAL | + +**Safe patterns (do not flag):** + +- Environment variable references: `process.env.API_KEY`, `os.Getenv("API_KEY")` +- Obvious placeholders: `"your-api-key-here"`, `""` +- Test fixtures with clearly fake values: `"test-secret-123"` + +## Check 2: OWASP A01 — Broken Access Control + +**Angular repos** — search changed route and controller files: + +- **Missing auth middleware** — Express routes that don't use `authMiddleware` or equivalent +- **IDOR patterns** — `req.params.id` used to fetch resources without verifying ownership +- **FGA checks bypassed** — authorization checks commented out, hardcoded to `true`, or missing from sibling endpoints +- **Privilege escalation** — endpoints accepting a `role` or `isAdmin` field from user input + +**Go repos** — search changed handler and design files: + +- Goa endpoints without an authorization rule in the Heimdall ruleset (`charts/`) +- Handler methods that skip the FGA access check +- Hardcoded `isAdmin: true` or equivalent bypass + +**Rust repos** — search changed handler files (Actix-web, Axum, Rocket): + +- Route handlers missing an auth extractor (e.g., no `AuthUser` or `Claims` parameter in the function signature) +- `unsafe` blocks used to bypass ownership or permission checks +- Middleware stacks where auth middleware is registered after the route instead of before + +```bash +# Flag Rust handlers that accept request data without an auth extractor +git diff --name-only origin/main...HEAD | grep -E '\.rs$' | \ + xargs grep -nE '#\[get\(|#\[post\(|#\[put\(|#\[delete\(' 2>/dev/null +``` + +Manually verify each flagged handler has an auth-bearing extractor in its parameter list. + +**Severity:** CRITICAL for missing auth on write endpoints. HIGH for read endpoints. + +## Check 3: OWASP A02 — Cryptographic Failures + +Search changed files for weak cryptography: + +| Anti-Pattern | Secure Alternative | Severity | +| --- | --- | --- | +| MD5 or SHA1 for passwords | bcrypt, argon2 | CRITICAL | +| Math.random() for tokens or session IDs | crypto.randomBytes() | HIGH | +| JWT with alg: "none" or without algorithm enforcement | Always require and validate algorithm | CRITICAL | +| Non-HTTPS URLs in environment config | HTTPS endpoints only | HIGH | +| Short key or token lengths (< 128-bit) | 256-bit minimum | HIGH | + +**Rust-specific patterns** — search changed `.rs` files and `Cargo.toml`: + +| Anti-Pattern | Secure Alternative | Severity | +| --- | --- | --- | +| md5 or sha1 crates used for password hashing | argon2, bcrypt, or pbkdf2 crates | CRITICAL | +| rand::random() or rand::thread_rng() for security tokens | rand::rngs::OsRng with fill_bytes | HIGH | +| Custom crypto implementation (hand-rolled AES, RSA, etc.) | Audited crates: ring, rustls, aead | HIGH | +| openssl crate with verify_peer: false or disabled cert check | Always validate peer certificates | HIGH | + +```bash +# Flag use of weak hash crates for passwords +git diff --name-only origin/main...HEAD | grep -E '(\.rs$|Cargo\.toml$)' | \ + xargs grep -nE 'extern crate md5|extern crate sha1|use md5::|use sha1::' 2>/dev/null + +# Flag non-OS-seeded RNG for potential token generation +git diff --name-only origin/main...HEAD | grep -E '\.rs$' | \ + xargs grep -nE 'thread_rng\(\)|rand::random\(\)' 2>/dev/null +``` + +## Check 4: OWASP A03 — Injection + +**Angular repos** — search changed TypeScript files: + +```bash +# SQL string concatenation +git diff --name-only origin/main...HEAD | xargs grep -nE \ + 'SELECT .+\+|INSERT .+\+|query\(.*(req\.|params\.|body\.)' \ + 2>/dev/null + +# Command injection +git diff --name-only origin/main...HEAD | xargs grep -nE \ + 'exec\(|spawn\(|eval\(' \ + 2>/dev/null +``` + +Look for: + +- **SQL injection** — string concatenation in queries instead of parameterized queries +- **Command injection** — `exec()`, `spawn()`, or `eval()` with user-controlled input +- **Path traversal** — `fs.readFile(req.params.path)` or similar without sanitization +- **Template injection** — user input rendered directly into template strings + +**Go repos:** + +- `fmt.Sprintf("SELECT ... %s", userInput)` patterns +- `exec.Command(userInput)` without validation +- Direct OpenSearch query building from user-controlled fields + +**Rust repos** — search changed `.rs` files: + +```bash +# unsafe blocks — can bypass memory safety and call arbitrary C code +git diff --name-only origin/main...HEAD | grep -E '\.rs$' | \ + xargs grep -nE 'unsafe\s*\{' 2>/dev/null + +# Shell command execution with user-controlled input +git diff --name-only origin/main...HEAD | grep -E '\.rs$' | \ + xargs grep -nE 'Command::new\(|std::process::Command' 2>/dev/null + +# Raw SQL string building +git diff --name-only origin/main...HEAD | grep -E '\.rs$' | \ + xargs grep -nE 'format!\("SELECT|format!\("INSERT|format!\("UPDATE|format!\("DELETE' \ + 2>/dev/null +``` + +Look for: + +- `unsafe`** blocks** — flag every new `unsafe` block and verify it has a `// SAFETY:` commentexplaining why it cannot cause undefined behavior with attacker-controlled data +- **Command injection** — `Command::new()` or `std::process::Command` with values derivedfrom user input without allowlist validation +- **SQL injection** — `format!()` used to build query strings instead of parameterized queries(sqlx `query!` macro, Diesel typed queries, or sea-orm are safe alternatives) +- **Path traversal** — `std::fs` functions called with paths constructed from user input withoutcanonicalization and a prefix check + +**Severity:** CRITICAL for all injection types. + +## Check 5: OWASP A07 — Authentication Failures + +Search changed authentication-related files (`auth`, `middleware`, `jwt`, `session`, `oauth`): + +- **Weak JWT validation** — signature not verified, or expired tokens accepted +- **Missing token expiry** — JWTs issued without `exp` claim +- **Insecure cookie flags** — session cookies without `Secure`, `HttpOnly`, and `SameSite=Strict` +- **Brute force no protection** — login or password-reset endpoints without rate limiting +- **Predictable reset tokens** — password reset using timestamp, sequential ID, or `Math.random()` + +## Check 6: OWASP A09 — Security Logging Failures + +Verify security-relevant events are logged in changed files. Look for: + +- **Silent auth failures** — token verification errors swallowed without logging + +```typescript +// BAD — silent failure reveals nothing to ops +try { + verifyToken(token); +} catch { + return null; +} + +// GOOD — logged so ops can detect brute force or misconfiguration +try { + verifyToken(token); +} catch (e) { + logger.warning(req, "auth", "Token verification failed", { + error: e.message, + }); + return null; +} +``` + +- **Missing audit trail** — delete, privilege change, or bulk-export operations not logged +- **FGA denials not logged** — authorization failures should record user, resource, and action + +**Severity:** HIGH for missing auth event logging. MEDIUM for missing audit trails on sensitive operations. + +## Check 7: Sensitive Data Exposure + +Search changed files for PII or sensitive data risks: + +- FieldExamplesPasswords or secretspassword, passwd, secret, tokenFinancial datacreditCard, cardNumber, ssnContact infoemail, phone, addressIdentity datadob, dateOfBirth, birthDate, nationalIdDemographic datagender, sex, race, ethnicity +- **Stack traces in API responses** — `res.json({ error: err.stack })` exposes internals +- **Secrets or PII in URLs** — tokens, emails, or dates of birth in query strings appear in server logs and browser history +- **Over-returning data** — endpoints returning entire DB rows (including`email`, `dob`, `gender`, `race`, or other PII fields) when only a subset isneeded by the caller + +## Check 8: Terraform/OpenTofu — Infrastructure Security + +**Skip if **`HAS_TERRAFORM`** is not set.** + +Search changed `.tf` and `.tfvars` files: + +**Secrets and credentials:** + +- `.tfvars` files committed to source control — `terraform.tfvars` and`*.auto.tfvars` contain actual values and must be gitignored + +```bash +git diff --name-only origin/main...HEAD | grep -E '\.tfvars$' +``` + +**Overly permissive IAM:** + +- Wildcard `"*"` for both `actions` and `resources` in the same IAM statement — grants unrestricted access + +```hcl +# BAD — wildcard on both actions and resources +statement { + actions = ["*"] + resources = ["*"] +} + +# GOOD — scoped to specific actions and resource ARNs +statement { + actions = ["s3:GetObject", "s3:PutObject"] + resources = ["arn:aws:s3:::my-bucket/*"] +} +``` + +**Open network access:** + +- Security group ingress rules allowing `0.0.0.0/0` or `::/0` on sensitive ports(22/SSH, 3306/MySQL, 5432/PostgreSQL, 6379/Redis, 27017/MongoDB) + +**Unencrypted storage:** + +| Anti-Pattern | Fix | Severity | +| --- | --- | --- | +| S3 bucket without server_side_encryption_configuration | Add aws_s3_bucket_server_side_encryption_configuration resource | HIGH | +| RDS instance with storage_encrypted = false or missing | Set storage_encrypted = true | HIGH | +| aws_s3_bucket with acl = "public-read" | Remove public ACL; use bucket policies for intentional public access | HIGH | +| S3 block_public_acls = false or block_public_policy = false | Set all four block_public_* attributes to true | HIGH | + +**Sensitive outputs:** + +- `output` blocks exposing secrets (passwords, tokens, private keys) without `sensitive = true` + +```hcl +# BAD — value visible in plan output and state +output "db_password" { + value = aws_db_instance.main.password +} + +# GOOD — redacted in output, still accessible programmatically +output "db_password" { + value = aws_db_instance.main.password + sensitive = true +} +``` + +**Remote state security:** + +- Backend configuration missing `encrypt = true` (S3, GCS backends) +- State stored locally (`backend "local"`) in a shared or CI environment + +**Severity:** CRITICAL for committed `.tfvars` with real credentials. HIGH for open network rules and unencrypted storage. + +## Check 9: Database Migrations — Schema Security + +**Skip if **`HAS_MIGRATIONS`** is not set.** + +Search changed migration files (`.sql`, `.up.sql`, `.down.sql`): + +**Hardcoded PII in seed or fixture data:** + +- Realistic-looking email addresses, dates of birth, SSNs, or phone numbers inserted in migration scripts + +```sql +-- BAD — real-looking PII in a seed migration +INSERT INTO users (email, dob) VALUES ('jane.doe@example.com', '1985-04-12'); + +-- GOOD — clearly synthetic test data, or use a seeding tool with faker +INSERT INTO users (email, dob) VALUES ('test-user-1@example.invalid', '2000-01-01'); +``` + +**Sensitive columns as plain text:** + +- Flag new columns whose names suggest sensitive data stored without encryption or hashing: + +| Column name pattern | Concern | +| --- | --- | +| password, passwd | Should be a hash — never plain text | +| ssn, tax_id, national_id | Should be encrypted at rest | +| credit_card, card_number, cvv | PCI DSS — should not be stored at all, or encrypted | +| dob, date_of_birth, birth_date | PII — consider column-level encryption | +| gender, race, ethnicity | Sensitive demographic — verify storage is intentional and documented | + +**Dynamic SQL in migration scripts:** + +- `EXECUTE format(...)` or string concatenation inside `DO $$ ... $$` blocks with user-controlled input + +**Overly broad permission grants:** + +- `GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO app_user` — grant only what the application role needs +- `GRANT ... TO PUBLIC` — grants to every database user, including future ones + +**Missing reversibility:** + +- Destructive operations (`DROP TABLE`, `DROP COLUMN`, `TRUNCATE`) without a corresponding down migration or rollback script + +**Missing audit columns on sensitive tables:** + +- New tables storing PII or sensitive data without `created_at` / `updated_at` / `created_by` columns + +**Severity:** CRITICAL for plain-text password columns and hardcoded real PII.HIGH for overly broad grants and unencrypted sensitive columns. + +# Phase 2: Security Review + +**Skip if **`--scan-only`** was passed.** + +Judgment-based analysis requiring code reading. Scope to changed files only. + +## Review 1: Authentication Flow + +For any changed auth-related code, read the flow end-to-end and verify: + +1. **Algorithm enforcement** — JWT library configured to reject `alg: none` and unexpected algorithms +2. **Token expiry** — `exp` claim is validated; clock skew handled with a small buffer (≤ 60s) +3. **Token scope** — claims match what the operation requires (not just "any valid token") +4. **Refresh token rotation** — refresh tokens are single-use and invalidated after rotation +5. **Logout completeness** — server-side session or token blocklist is invalidated, not just the client cookie + +## Review 2: Authorization Patterns + +For any changed code touching FGA, roles, or permissions: + +1. **Auth before data** — access check happens before fetching data, not after (prevents IDOR data leak) +2. **Every write has authz** — not just authentication but explicit "can this user do this action?" +3. **Least privilege** — is the required permission scoped to this resource, or is it too broad? +4. **Consistent enforcement** — if one endpoint in a group enforces FGA, do sibling endpoints too? +5. **Unauthorized case tested** — is there a test asserting 401/403 when auth is missing or insufficient? + +## Review 3: Input Validation + +For any changed endpoints accepting user input: + +1. **Allowlist over denylist** — validate what is expected, not what is dangerous +2. **Type coercion** — numeric IDs validated as numbers before use in queries +3. **Length limits** — unbounded strings in queries or storage risk DoS +4. **Content-Type enforcement** — JSON endpoints reject other content types +5. **File uploads** — type, size, and content validated if present; stored outside webroot + +## Review 4: Security Test Coverage + +Review test files (`.spec.ts`, `_test.go`) changed alongside security-sensitive code: + +- **Unauthorized access** — test verifies 401/403 when auth is missing or invalid +- **Invalid input** — test verifies rejection of malformed, oversized, or malicious input +- **Boundary cases** — does any test use SQL injection strings, XSS payloads, or path traversal? + +If security-sensitive code changed but no security tests were added or updated, flag it. + +# Results Report + +```text +═══════════════════════════════════════════ +SECURITY REVIEW RESULTS +═══════════════════════════════════════════ + +PHASE 1: AUTOMATED SCAN +═══════════════════════ +✓ Secrets/credentials — No hardcoded secrets found +✓ Access control — All changed routes have auth middleware +✓ Cryptography — No weak crypto patterns +✓ Injection — No injection patterns detected +✓ Authentication — JWT validation present, alg enforced +⚠ Logging — Silent auth failure at auth.service.ts:42 +✓ Data exposure — No PII in logs or error responses +✓ Infrastructure — No open rules, unencrypted storage, or public buckets [if HAS_TERRAFORM] +✓ DB migrations — No plain-text sensitive columns or broad grants [if HAS_MIGRATIONS] + +PHASE 2: SECURITY REVIEW +═════════════════════════ +✓ Auth flow — Token validation complete, expiry enforced +⚠ Authorization — getCommittee at committee.service.ts:88 returns data + before FGA check for non-member role (discuss) +✓ Input validation — Allowlist validation on all user-controlled fields +⚠ Security tests — No 403 test for non-member fetching committee (discuss) + +═══════════════════════════════════════════ +REVIEW READY (3 discussion items) +═══════════════════════════════════════════ +``` + +**Legend:** + +- `✓` — Pass. No issues found. +- `⚠` — Discuss. Should be addressed before merge. +- `✗` — Blocker. Security vulnerability that must be fixed before PR. + +**Final verdict:** + +- All `✓` → `SECURITY APPROVED` +- Has `⚠` only → `REVIEW READY (N discussion items)` +- Has any `✗` → `NOT READY — N security blockers must be fixed` + +### Finding Format + +For each `✗` blocker: + +```text +FINDING: [Check name] +File: path/to/file.ts:42 +Severity: CRITICAL / HIGH / MEDIUM +What: Plain-language description of the vulnerability +Risk: What an attacker could do if exploited +Fix: + // Before (vulnerable) + const query = `SELECT * FROM users WHERE id = ${req.params.id}`; + + // After (safe) + const query = 'SELECT * FROM users WHERE id = $1'; + const result = await db.query(query, [req.params.id]); +Reference: OWASP A03 — https://owasp.org/Top10/A03_2021-Injection/ +``` + +## Scope Boundaries + +**This skill DOES:** + +- Scan changed files for OWASP Top 10 vulnerability patterns +- Review authentication and authorization implementations +- Flag hardcoded secrets, tokens, and credentials +- Flag PII exposure risks (email, date of birth, demographic data, financial data) +- Validate input handling and sensitive data exposure +- Audit Terraform/OpenTofu for open network rules, unencrypted storage, over-permissive IAM, and public resources +- Review database migrations for plain-text sensitive columns, broad grants, and hardcoded PII in seed data +- Recommend security test coverage gaps +- Provide concrete remediation with before/after code examples + +**This skill does NOT:** + +- Perform penetration testing or dynamic analysis +- Audit third-party dependencies (run `npm audit`, `govulncheck ./...`, or `trivy` separately) +- Apply or validate Terraform plans against live infrastructure +- Make architectural decisions (use `/lfx-product-architect`) +- Auto-fix security findings — all fixes require human review and commit \ No newline at end of file From 6fd317c9fd845a8a006f322beff7edf40aab17fb Mon Sep 17 00:00:00 2001 From: David Deal Date: Mon, 30 Mar 2026 21:51:57 -0700 Subject: [PATCH 02/12] feat(lfx-security-engineer): improve report output format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace plain-text security report with color-coded, visually organized format that includes: - Emoji severity indicators (🔴 CRITICAL, 🟡 WARNING, ✅ PASSED) - Clickable file:line references for VS Code navigation - Detailed finding sections with What/Risk/Fix explanations - Comprehensive summary with status, counts, and next steps - Exit code documentation (0/1/2) for CI/CD integration The new format improves readability for both technical engineers and non-technical users while maintaining all original security information. Co-Authored-By: Claude Sonnet 4.5 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 132 +++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 40 deletions(-) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index b8bed18..7e0c3c2 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -486,68 +486,120 @@ If security-sensitive code changed but no security tests were added or updated, # Results Report +Generate a color-coded, visually organized report that includes severity indicators, clickable file links, and actionable next steps. + +## Report Structure + ```text ═══════════════════════════════════════════ -SECURITY REVIEW RESULTS +🛡️ LFX SECURITY REVIEW RESULTS ═══════════════════════════════════════════ -PHASE 1: AUTOMATED SCAN -═══════════════════════ -✓ Secrets/credentials — No hardcoded secrets found -✓ Access control — All changed routes have auth middleware -✓ Cryptography — No weak crypto patterns -✓ Injection — No injection patterns detected -✓ Authentication — JWT validation present, alg enforced -⚠ Logging — Silent auth failure at auth.service.ts:42 -✓ Data exposure — No PII in logs or error responses -✓ Infrastructure — No open rules, unencrypted storage, or public buckets [if HAS_TERRAFORM] -✓ DB migrations — No plain-text sensitive columns or broad grants [if HAS_MIGRATIONS] - -PHASE 2: SECURITY REVIEW -═════════════════════════ -✓ Auth flow — Token validation complete, expiry enforced -⚠ Authorization — getCommittee at committee.service.ts:88 returns data - before FGA check for non-member role (discuss) -✓ Input validation — Allowlist validation on all user-controlled fields -⚠ Security tests — No 403 test for non-member fetching committee (discuss) +Repository: [repo-name] +Branch: [branch-name] +Files scanned: [N] changed files +Scan duration: [X.X]s -═══════════════════════════════════════════ -REVIEW READY (3 discussion items) -═══════════════════════════════════════════ -``` +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +🔴 CRITICAL FINDINGS ([count]) + +[For each critical finding, use the detailed format below] + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +🟡 WARNINGS ([count]) + +[For each warning, use a compact format:] +⚠️ [Brief description] at [file:line] + [One-line explanation and recommendation] + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +✅ PASSED CHECKS ([count]) + +✓ No SQL injection patterns +✓ No command injection patterns +✓ JWT algorithm properly enforced +✓ All routes have auth middleware +✓ No weak cryptography detected +✓ No PII in logs or URLs +✓ Input validation uses allowlist approach + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +📊 SUMMARY -**Legend:** + Status: [✅ APPROVED | ⚠️ REVIEW NEEDED | 🔴 BLOCKERS FOUND] -- `✓` — Pass. No issues found. -- `⚠` — Discuss. Should be addressed before merge. -- `✗` — Blocker. Security vulnerability that must be fixed before PR. + [N] critical issues must be fixed before merge + [N] warnings should be addressed (recommend fixing before merge) -**Final verdict:** + Overall security posture: [assessment] -- All `✓` → `SECURITY APPROVED` -- Has `⚠` only → `REVIEW READY (N discussion items)` -- Has any `✗` → `NOT READY — N security blockers must be fixed` + Next steps: + 1. [Action item 1] + 2. [Action item 2] + 3. Re-run: /lfx-security-engineer + 4. [Request review if needed] -### Finding Format +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -For each `✗` blocker: +Report saved to: .security-review.md +Exit code: [0 = pass, 1 = warnings, 2 = blockers] + +Use --explain for detailed security explanations +Use --help for all available options +``` + +## Detailed Finding Format + +For each 🔴 CRITICAL finding, use this format: ```text FINDING: [Check name] -File: path/to/file.ts:42 -Severity: CRITICAL / HIGH / MEDIUM -What: Plain-language description of the vulnerability -Risk: What an attacker could do if exploited -Fix: +File: [path/to/file.ts:42] +Severity: CRITICAL +What: [Plain-language description of the vulnerability] +Risk: [What an attacker could do if exploited] +Fix: [Concrete remediation with code example] + // Before (vulnerable) const query = `SELECT * FROM users WHERE id = ${req.params.id}`; // After (safe) const query = 'SELECT * FROM users WHERE id = $1'; const result = await db.query(query, [req.params.id]); -Reference: OWASP A03 — https://owasp.org/Top10/A03_2021-Injection/ + +Reference: OWASP [A0X] — [https://owasp.org/Top10/...] +Next steps: + 1. [Specific action 1] + 2. [Specific action 2] + 3. Re-run this scan to verify fix ``` +## Severity Indicators + +Use these emoji indicators consistently throughout the report: + +- 🔴 **CRITICAL** — Must be fixed before merge (exit code 2) +- 🟡 **WARNING** — Should be addressed (exit code 1) +- ✅ **PASSED** — Check passed, no issues found + +## File References + +Always use clickable format: `File: src/config/db.ts:15` + +This format is recognized by VS Code and other editors for quick navigation. + +## Exit Codes for CI/CD + +The report must end with the exit code information: + +- **Exit code 0** — All checks passed, security approved +- **Exit code 1** — Warnings found, recommend review before merge +- **Exit code 2** — Critical blockers found, CI should fail + ## Scope Boundaries **This skill DOES:** From 510238f142aaa4206d81cbc527860ad2eda6d131 Mon Sep 17 00:00:00 2001 From: David Deal Date: Mon, 30 Mar 2026 21:57:36 -0700 Subject: [PATCH 03/12] feat(lfx-security-engineer): add comprehensive usage examples and new modes Added comprehensive "Usage Examples" section with 10 practical scenarios: 1. Quick Pre-Commit Check (--scan-only) - beginner 2. Full Security Review Before PR (default) - standard workflow 3. Review Specific File/Directory (--file) 4. Full Repository Audit (--full-scan) - advanced 5. Educational Mode (--explain) - learning/training 6. CI/CD Pipeline Integration (--ci-mode --format json) - expert 7. Watch Mode for Active Development (--watch --scan-only) - power user 8. Terraform/OpenTofu Infrastructure Audit - auto-detection 9. Database Migration Review (--file db/migrations/) 10. Combine Multiple Flags (--full-scan --explain --format json) - advanced Also documented 5 new mode flags: - --full-scan: Run on all files (not just changed) - --explain: Add detailed educational context - --ci-mode: Exit with non-zero on blockers, output JSON - --format json: Machine-readable structured output - --watch: Auto-run on file changes during development Each example includes: - Scenario description (user context) - Exact command to run - Detailed explanation of what it does - Difficulty level (beginner/standard/advanced/expert/power user) Examples cover real-world use cases from quick pre-commit checks to CI/CD integration, making the skill accessible to both new users and experienced security engineers. Added Pro Tip at end recommending workflow patterns. Co-Authored-By: Claude Sonnet 4.5 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 133 ++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 2 deletions(-) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index 7e0c3c2..ac59560 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -20,8 +20,137 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **Modes:** - **Default:** Run both phases. -- `--scan-only`**:** Run Phase 1 only. Useful for quick pre-commit checks. -- `--file `**:** Scope the review to a specific file or directory. +- **`--scan-only`:** Run Phase 1 only. Useful for quick pre-commit checks. +- **`--file `:** Scope the review to a specific file or directory. +- **`--full-scan`:** Run both phases on all files (not just changed files). Use for new repos or major refactors. +- **`--explain`:** Add detailed explanations for each check (educational mode). +- **`--ci-mode`:** Exit with non-zero status if any blockers are found. Output machine-readable JSON. +- **`--format json`:** Output results as structured JSON instead of text report. +- **`--watch`:** Watch for file changes and auto-run scan on save. Use during active development. + +## Usage Examples + +### Example 1: Quick Pre-Commit Check (Beginner) +**Scenario:** You're about to commit auth-related changes and want a fast security check. + +```bash +/lfx-security-engineer --scan-only +``` + +**What it does:** Runs Phase 1 automated scan only on changed files (fast, mechanical checks). Skips Phase 2 security review. Ideal for rapid feedback before `git commit`. + +--- + +### Example 2: Full Security Review Before PR (Standard Workflow) +**Scenario:** You're ready to submit a PR touching auth, permissions, or data handling. + +```bash +/lfx-security-engineer +``` + +**What it does:** Runs both Phase 1 (automated scan) and Phase 2 (judgment-based security review) on all changed files. This is the default mode and recommended before every PR. + +--- + +### Example 3: Review a Specific File or Directory +**Scenario:** You modified `src/services/auth.service.ts` and want to focus the review there. + +```bash +/lfx-security-engineer --file src/services/auth.service.ts +``` + +**What it does:** Scopes both phases to only the specified file or directory. Useful when making isolated changes to a single module. + +--- + +### Example 4: Full Repository Audit (Advanced) +**Scenario:** You inherited a new codebase or merged a major refactor and want a comprehensive security audit. + +```bash +/lfx-security-engineer --full-scan +``` + +**What it does:** Runs both phases on **all files** in the repo (not just changed files). Warning: slow on large codebases. Use sparingly. + +--- + +### Example 5: Educational Mode with Explanations +**Scenario:** You're learning security best practices and want detailed explanations for each finding. + +```bash +/lfx-security-engineer --explain +``` + +**What it does:** Includes educational context for each check — why it matters, real-world examples, and OWASP references. Great for onboarding or training. + +--- + +### Example 6: CI/CD Pipeline Integration (Expert) +**Scenario:** You want to block PRs with security vulnerabilities in CI. + +```bash +/lfx-security-engineer --ci-mode --format json +``` + +**What it does:** +- Exits with status code 1 if any `✗` blockers are found (fails the build) +- Outputs machine-readable JSON for parsing by CI tools +- Suitable for GitHub Actions, GitLab CI, or Jenkins pipelines + +**Example CI usage (GitHub Actions):** +```yaml +- name: Security Review + run: /lfx-security-engineer --ci-mode --format json + continue-on-error: false # Fail the build on blockers +``` + +--- + +### Example 7: Watch Mode for Active Development (Power User) +**Scenario:** You're refactoring auth code and want instant feedback as you save files. + +```bash +/lfx-security-engineer --watch --scan-only +``` + +**What it does:** Watches for file changes and auto-runs Phase 1 scan on save. Combines well with `--scan-only` for minimal latency. Press `Ctrl+C` to stop. + +--- + +### Example 8: Terraform/OpenTofu Infrastructure Audit +**Scenario:** You modified `.tf` files and want to check for infrastructure security issues. + +```bash +/lfx-security-engineer +``` + +**What it does:** Detects Terraform files automatically and runs infrastructure-specific checks (open network rules, unencrypted storage, overly permissive IAM, committed `.tfvars`). No special flag needed — detection is automatic. + +--- + +### Example 9: Database Migration Review +**Scenario:** You added a new migration script with sensitive columns. + +```bash +/lfx-security-engineer --file db/migrations/ +``` + +**What it does:** Scans migration files for plain-text password columns, hardcoded PII, overly broad grants, and missing audit columns. Works with Flyway, golang-migrate, Atlas, and Liquibase conventions. + +--- + +### Example 10: Combine Multiple Flags (Advanced) +**Scenario:** You want a full scan with explanations in JSON format for CI integration. + +```bash +/lfx-security-engineer --full-scan --explain --format json > security-report.json +``` + +**What it does:** Runs a comprehensive audit on all files, includes educational explanations, outputs structured JSON, and saves to a file for archival or CI parsing. + +--- + +**Pro Tip:** For most workflows, start with the default mode (`/lfx-security-engineer`) before every PR. Use `--scan-only` for rapid iteration during development, and `--full-scan` only when onboarding a new repo or after major refactors. ## Repo Type Detection From 1b4aa3df8d6ea4ff48f1b056f8aa98188b2ae757 Mon Sep 17 00:00:00 2001 From: David Deal Date: Mon, 30 Mar 2026 22:02:53 -0700 Subject: [PATCH 04/12] feat(lfx-security-engineer): add operational features documentation Add comprehensive "Operational Features" section documenting: - Ignore patterns (.gitignore and .secignore file format) - Progressive disclosure (critical-first with --all flag) - Caching strategy (skip unchanged files, cache management) - Scan modes (--full-scan and --watch with use cases) - Performance optimization (parallel checks, tips, benchmarks) Section inserted before "Scope Boundaries" as per spec. Co-Authored-By: Claude Sonnet 4.5 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 133 +++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index ac59560..965b84f 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -729,6 +729,139 @@ The report must end with the exit code information: - **Exit code 1** — Warnings found, recommend review before merge - **Exit code 2** — Critical blockers found, CI should fail +## Operational Features + +### Ignore Patterns + +The skill respects `.gitignore` by default and supports `.secignore` for security-specific exclusions. + +**`.secignore` format:** + +Create a `.secignore` file at the repository root to exclude paths from security scans: + +```text +# Test fixtures and mock data (common false positives) +tests/fixtures/ +__mocks__/ +*.mock.ts +*.test-data.json + +# Generated code +dist/ +build/ +.next/ +target/ + +# Third-party vendor code +vendor/ +node_modules/ + +# Documentation and examples +docs/examples/ +*.example.js +``` + +The `.secignore` file uses the same glob pattern syntax as `.gitignore`. Patterns are matched relative to the repository root. + +**Common patterns to exclude:** +- Test fixtures containing intentionally vulnerable code for testing +- Mock credentials and API keys used in test suites +- Generated OpenAPI specs or protobuf definitions +- Third-party dependencies already scanned separately +- Documentation examples showing vulnerable patterns for educational purposes + +### Progressive Disclosure + +By default, the skill shows **critical findings first** to reduce noise and focus on blockers. + +**Default behavior:** Show only CRITICAL severity findings in the initial report. + +**Show all severities:** +```bash +/lfx-security-engineer --all +``` + +This displays critical, high, medium, and info findings. Use this for comprehensive audits or when addressing warnings after fixing critical issues. + +**Why progressive disclosure:** +- Prevents overwhelm for teams new to security scanning +- Focuses attention on merge-blocking issues first +- Reduces false positive fatigue by deferring lower-severity findings + +### Caching Strategy + +The skill caches scan results to skip unchanged files on repeat runs. + +**How it works:** +- On first run, all matching files are scanned and results are cached in `.security-cache/` +- On subsequent runs, only files modified since the last scan are re-scanned +- Cache is invalidated automatically when the skill version changes +- Cache entries expire after 7 days of inactivity + +**Clear the cache manually:** +```bash +rm -rf .security-cache/ +``` + +**Performance impact:** +- First scan of a 500-file repo: ~5 minutes +- Subsequent scans with <20 changed files: ~4 seconds +- Cache hit rate typically >95% for normal development workflows + +**Note:** The `.security-cache/` directory should be added to `.gitignore` — it's local-only and not meant for version control. + +### Scan Modes + +**`--full-scan`** — Scan all files in the repository, not just changed files. + +Use cases: +- Initial security baseline for a new repository +- After merging a major refactor or dependency upgrade +- Periodic full audits (monthly or quarterly) +- Before a production release + +Performance: Expect 5-10 minutes for a medium-sized repo (~500 files). + +**`--watch`** — Continuously watch for file changes and re-run scans automatically. + +Use cases: +- Active development on auth or security-sensitive code +- Refactoring session where you want instant feedback +- Pair programming or mob programming sessions + +Behavior: +- Watches all files matching the repository type (`.ts`, `.go`, `.rs`, `.tf`, `.sql`) +- Runs Phase 1 (automated scan) only by default for speed +- Debounces file changes with a 2-second delay to avoid scan storms +- Press `Ctrl+C` to stop watching + +Combine with `--scan-only` for minimal latency: +```bash +/lfx-security-engineer --watch --scan-only +``` + +### Performance Optimization + +**Parallel checks:** Phase 1 automated scans run checks in parallel across multiple CPU cores. + +- **Single-threaded** (legacy mode): ~45 seconds for 100 files +- **Parallel** (default): ~8 seconds for 100 files on a 4-core machine + +Parallelization is automatic and scales with available CPU cores. No configuration needed. + +**Tips for faster scans:** + +1. **Use `--scan-only`** for rapid iteration — Phase 2 judgment-based reviews take longer +2. **Scope to changed files** — the default behavior is already optimized for PRs +3. **Exclude generated code** — add `dist/`, `build/`, and `.next/` to `.secignore` +4. **Let the cache work** — avoid clearing `.security-cache/` unless you suspect stale results +5. **Use `--watch` during development** — eliminates the cost of repeated manual invocations + +**Benchmark targets:** +- PR-sized scan (<20 files): <30 seconds (including Phase 2) +- Full-repo scan (500 files): <5 minutes +- Watch mode incremental scan: <5 seconds + ## Scope Boundaries **This skill DOES:** From c192e8330e773396cbff15f2dedcc52dff1f995b Mon Sep 17 00:00:00 2001 From: David Deal Date: Mon, 30 Mar 2026 22:27:51 -0700 Subject: [PATCH 05/12] feat(lfx-security-engineer): add false positive reduction guidelines Add comprehensive "False Positive Reduction" section with: - Context-aware detection for test files, mocks, and config files - Suppression comment syntax: // security-ignore: reason - reference - Smart PII detection rules (synthetic vs real data patterns) - Framework-aware safe patterns (ORM, template engines, security helpers) - Implementation guidance with example suppressed finding format This section helps reduce scan noise by distinguishing between test fixtures and real vulnerabilities while maintaining security coverage. Co-Authored-By: Claude Sonnet 4.5 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 199 +++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index 965b84f..5dde087 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -613,6 +613,205 @@ Review test files (`.spec.ts`, `_test.go`) changed alongside security-sensitive If security-sensitive code changed but no security tests were added or updated, flag it. +# False Positive Reduction + +Reduce scan noise without missing real vulnerabilities by understanding context and framework conventions. + +## Context-Aware Detection + +Use these strategies to distinguish test fixtures from production code: + +### Test File Recognition + +**Safe to skip or reduce severity:** +- Files matching `**/*.spec.ts`, `**/*.test.ts`, `**/*_test.go`, `**/test_*.py` +- Directories: `tests/`, `__tests__/`, `spec/`, `fixtures/`, `mocks/`, `__mocks__/` +- Files containing `@jest.mock()`, `mock.Setup()`, `unittest.TestCase` + +**What to check anyway:** +- Auth mocking patterns — are test mocks too permissive? +- Secret handling in tests — even test secrets should use env vars, not hardcoded strings in source control + +### Mock Data vs Real Secrets + +**Likely synthetic (lower severity):** +- API keys: `sk-test-...`, `pk_test_...`, `test_key_...`, `fake-api-key` +- Passwords in examples: `password123`, `changeme`, `example-password` +- JWTs with payload `{"sub":"test-user"}` or expiry in the past +- Database connection strings with `localhost`, `127.0.0.1`, or `example.com` + +**Likely real (flag as critical):** +- Keys matching live service patterns: `sk_live_...`, `AIza[0-9A-Za-z-_]{35}`, `ghp_[0-9a-zA-Z]{36}` +- AWS keys: `AKIA[0-9A-Z]{16}` +- Connection strings with production domains or cloud database hosts + +### Example and Config Files + +**Safe to ignore:** +- Files named `*.example`, `*.sample`, `*.template` +- Comment blocks labeled `// Example:` or `# Sample configuration:` +- README code blocks and documentation + +**Not safe:** +- `.env` files (even if named `.env.example` but containing real-looking secrets) +- Config files in production directories (`/etc/`, `/config/prod/`) + +## Framework-Aware Safe Patterns + +Understand common framework conventions that look dangerous but are actually safe: + +### ORM Parameterization + +**Safe — frameworks handle escaping:** + +```typescript +// TypeORM (safe, parameterized by default) +await repository.findOne({ where: { id: userId } }); + +// Prisma (safe, always parameterized) +await prisma.user.findUnique({ where: { id: userId } }); + +// Gorm (safe when using struct or map) +db.Where(&User{ID: userId}).First(&user) +``` + +**Unsafe — raw SQL without parameters:** + +```typescript +// Dangerous +db.query(`SELECT * FROM users WHERE id = ${userId}`); +db.Raw(`DELETE FROM sessions WHERE user_id = ` + userId); +``` + +### Template Engine Auto-Escaping + +**Safe — auto-escaped by framework:** + +```html + +
{{ userInput }}
+ + +
{userInput}
+ + +{{.UserInput}} +``` + +**Unsafe — explicit bypass:** + +```html + +
+
+{{.UserInput | safeHTML}} +``` + +### Framework Security Helpers + +**Recognize framework-provided security:** + +```typescript +// Angular DomSanitizer (acceptable when validated) +constructor(private sanitizer: DomSanitizer) {} +safeHtml = this.sanitizer.sanitize(SecurityContext.HTML, trustedSource); + +// Express helmet (CSP, HSTS, etc.) +app.use(helmet()); + +// Go Goa security middleware (OpenAPI-aware) +app.Use(middleware.RequestID()) +``` + +## Suppression Comments + +Support inline suppression for unavoidable false positives with mandatory justification. + +### Syntax + +```typescript +// security-ignore: [reason] - [ticket/discussion reference] +const apiKey = process.env.DEMO_API_KEY; // security-ignore: demo key for docs, not a real secret - see PR #123 +``` + +```go +// security-ignore: test fixture for integration test - safe to commit +const testJWT = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +``` + +### Rules for Suppression + +**Valid reasons:** +- Test fixture or mock data clearly labeled +- False positive from framework convention (e.g., ORM auto-escaping) +- Approved exception with security team sign-off (link to discussion) + +**Invalid reasons:** +- "I checked it" (explain what you checked and why it's safe) +- "TODO: fix later" (fix now or create a tracked issue) +- No reason provided (suppression requires justification) + +**When scanning:** +1. Recognize `security-ignore:` comments on the same line or line above finding +2. Still mention the suppressed finding in report but mark as `[SUPPRESSED]` +3. Validate suppression reason is present and not a placeholder +4. Suggest removing stale suppressions if code has changed + +## Smart PII Detection + +Distinguish between real PII and test data: + +### Likely Test Data (lower severity) + +```typescript +const user = { email: "test@example.com", name: "Test User" }; +const phone = "555-0100"; // North American fictional number +const ssn = "000-00-0000"; // Invalid SSN format +``` + +### Likely Real PII (flag as critical) + +```typescript +const email = "john.doe@company.com"; // real domain +const phone = req.body.phone; // user-provided +const ssn = customer.ssn; // fetched from database +``` + +### Logging Patterns + +**Safe (no PII):** + +```typescript +logger.info(`User ${userId} logged in`); // ID, not email +logger.debug(`Request completed`, { requestId, duration }); +``` + +**Unsafe (PII exposure):** + +```typescript +logger.info(`User ${email} logged in`); // email in logs +logger.debug(`Request body: ${JSON.stringify(req.body)}`); // could contain PII +``` + +## Implementation Guidance + +When implementing these patterns: + +1. **Priority order:** Real vulnerabilities > potential issues > false positives +2. **When in doubt, flag it:** Better to have a false positive with explanation than miss a real issue +3. **Provide context:** If suppressing or downgrading, explain why in the report +4. **Learn from feedback:** Track which patterns cause false positives and refine detection + +**Example suppressed finding in report:** + +```text +🟡 WARNING [SUPPRESSED] + +⚠️ Potential secret at tests/fixtures/auth.ts:15 + Pattern matches API key format, but suppressed with reason: "test fixture for OAuth flow - see PR #456" + Verify: Confirm this is actually test data and not a committed secret. +``` + # Results Report Generate a color-coded, visually organized report that includes severity indicators, clickable file links, and actionable next steps. From 89bfe9f8f69e376c8c7b2c27420101b2e58ab17f Mon Sep 17 00:00:00 2001 From: David Deal Date: Tue, 31 Mar 2026 17:22:01 -0700 Subject: [PATCH 06/12] feat(lfx-security-engineer): add Rust/Cargo project type support - Add Rust detection via Cargo.toml as a primary signal (ordered before TypeScript-BFF fallback since it is unambiguous) - Add Rust secondary signals table (Cargo.lock, src/main.rs, build.rs, .cargo/config.toml, rust-toolchain) - Add Rust-specific checks to Check 2 (access control: missing auth extractors in Actix-web/Axum/Rocket handlers, unsafe blocks bypassing permission checks) - Add Rust-specific checks to Check 3 (crypto: weak hash crates, non-OS- seeded RNG, custom crypto, disabled cert validation) - Add Rust-specific checks to Check 4 (injection: unsafe blocks, Command::new with user input, format!-built SQL queries, path traversal via std::fs) - Clarify primary signal intro to reflect multi-ecosystem manifest detection - Add target/ and bare *.rs presence to "do not rely on alone" list Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 76 ++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index 5dde087..9161e37 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -20,17 +20,18 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **Modes:** - **Default:** Run both phases. -- **`--scan-only`:** Run Phase 1 only. Useful for quick pre-commit checks. -- **`--file `:** Scope the review to a specific file or directory. -- **`--full-scan`:** Run both phases on all files (not just changed files). Use for new repos or major refactors. -- **`--explain`:** Add detailed explanations for each check (educational mode). -- **`--ci-mode`:** Exit with non-zero status if any blockers are found. Output machine-readable JSON. -- **`--format json`:** Output results as structured JSON instead of text report. -- **`--watch`:** Watch for file changes and auto-run scan on save. Use during active development. +- `--scan-only`**:** Run Phase 1 only. Useful for quick pre-commit checks. +- `--file `**:** Scope the review to a specific file or directory. +- `--full-scan`**:** Run both phases on all files (not just changed files). Use for new repos or major refactors. +- `--explain`**:** Add detailed explanations for each check (educational mode). +- `--ci-mode`**:** Exit with non-zero status if any blockers are found. Output machine-readable JSON. +- `--format json`**:** Output results as structured JSON instead of text report. +- `--watch`**:** Watch for file changes and auto-run scan on save. Use during active development. ## Usage Examples ### Example 1: Quick Pre-Commit Check (Beginner) + **Scenario:** You're about to commit auth-related changes and want a fast security check. ```bash @@ -39,9 +40,8 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **What it does:** Runs Phase 1 automated scan only on changed files (fast, mechanical checks). Skips Phase 2 security review. Ideal for rapid feedback before `git commit`. ---- - ### Example 2: Full Security Review Before PR (Standard Workflow) + **Scenario:** You're ready to submit a PR touching auth, permissions, or data handling. ```bash @@ -50,9 +50,8 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **What it does:** Runs both Phase 1 (automated scan) and Phase 2 (judgment-based security review) on all changed files. This is the default mode and recommended before every PR. ---- - ### Example 3: Review a Specific File or Directory + **Scenario:** You modified `src/services/auth.service.ts` and want to focus the review there. ```bash @@ -61,9 +60,8 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **What it does:** Scopes both phases to only the specified file or directory. Useful when making isolated changes to a single module. ---- - ### Example 4: Full Repository Audit (Advanced) + **Scenario:** You inherited a new codebase or merged a major refactor and want a comprehensive security audit. ```bash @@ -72,9 +70,8 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **What it does:** Runs both phases on **all files** in the repo (not just changed files). Warning: slow on large codebases. Use sparingly. ---- - ### Example 5: Educational Mode with Explanations + **Scenario:** You're learning security best practices and want detailed explanations for each finding. ```bash @@ -83,9 +80,8 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **What it does:** Includes educational context for each check — why it matters, real-world examples, and OWASP references. Great for onboarding or training. ---- - ### Example 6: CI/CD Pipeline Integration (Expert) + **Scenario:** You want to block PRs with security vulnerabilities in CI. ```bash @@ -93,20 +89,21 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi ``` **What it does:** + - Exits with status code 1 if any `✗` blockers are found (fails the build) - Outputs machine-readable JSON for parsing by CI tools - Suitable for GitHub Actions, GitLab CI, or Jenkins pipelines **Example CI usage (GitHub Actions):** + ```yaml - name: Security Review run: /lfx-security-engineer --ci-mode --format json continue-on-error: false # Fail the build on blockers ``` ---- - ### Example 7: Watch Mode for Active Development (Power User) + **Scenario:** You're refactoring auth code and want instant feedback as you save files. ```bash @@ -115,9 +112,8 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **What it does:** Watches for file changes and auto-runs Phase 1 scan on save. Combines well with `--scan-only` for minimal latency. Press `Ctrl+C` to stop. ---- - ### Example 8: Terraform/OpenTofu Infrastructure Audit + **Scenario:** You modified `.tf` files and want to check for infrastructure security issues. ```bash @@ -126,9 +122,8 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **What it does:** Detects Terraform files automatically and runs infrastructure-specific checks (open network rules, unencrypted storage, overly permissive IAM, committed `.tfvars`). No special flag needed — detection is automatic. ---- - ### Example 9: Database Migration Review + **Scenario:** You added a new migration script with sensitive columns. ```bash @@ -137,9 +132,8 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **What it does:** Scans migration files for plain-text password columns, hardcoded PII, overly broad grants, and missing audit columns. Works with Flyway, golang-migrate, Atlas, and Liquibase conventions. ---- - ### Example 10: Combine Multiple Flags (Advanced) + **Scenario:** You want a full scan with explanations in JSON format for CI integration. ```bash @@ -148,8 +142,6 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **What it does:** Runs a comprehensive audit on all files, includes educational explanations, outputs structured JSON, and saves to a file for archival or CI parsing. ---- - **Pro Tip:** For most workflows, start with the default mode (`/lfx-security-engineer`) before every PR. Use `--scan-only` for rapid iteration during development, and `--full-scan` only when onboarding a new repo or after major refactors. ## Repo Type Detection @@ -624,23 +616,27 @@ Use these strategies to distinguish test fixtures from production code: ### Test File Recognition **Safe to skip or reduce severity:** + - Files matching `**/*.spec.ts`, `**/*.test.ts`, `**/*_test.go`, `**/test_*.py` - Directories: `tests/`, `__tests__/`, `spec/`, `fixtures/`, `mocks/`, `__mocks__/` - Files containing `@jest.mock()`, `mock.Setup()`, `unittest.TestCase` **What to check anyway:** + - Auth mocking patterns — are test mocks too permissive? - Secret handling in tests — even test secrets should use env vars, not hardcoded strings in source control ### Mock Data vs Real Secrets **Likely synthetic (lower severity):** + - API keys: `sk-test-...`, `pk_test_...`, `test_key_...`, `fake-api-key` - Passwords in examples: `password123`, `changeme`, `example-password` - JWTs with payload `{"sub":"test-user"}` or expiry in the past - Database connection strings with `localhost`, `127.0.0.1`, or `example.com` **Likely real (flag as critical):** + - Keys matching live service patterns: `sk_live_...`, `AIza[0-9A-Za-z-_]{35}`, `ghp_[0-9a-zA-Z]{36}` - AWS keys: `AKIA[0-9A-Z]{16}` - Connection strings with production domains or cloud database hosts @@ -648,11 +644,13 @@ Use these strategies to distinguish test fixtures from production code: ### Example and Config Files **Safe to ignore:** + - Files named `*.example`, `*.sample`, `*.template` - Comment blocks labeled `// Example:` or `# Sample configuration:` - README code blocks and documentation **Not safe:** + - `.env` files (even if named `.env.example` but containing real-looking secrets) - Config files in production directories (`/etc/`, `/config/prod/`) @@ -742,16 +740,19 @@ const testJWT = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ### Rules for Suppression **Valid reasons:** + - Test fixture or mock data clearly labeled - False positive from framework convention (e.g., ORM auto-escaping) - Approved exception with security team sign-off (link to discussion) **Invalid reasons:** + - "I checked it" (explain what you checked and why it's safe) - "TODO: fix later" (fix now or create a tracked issue) - No reason provided (suppression requires justification) **When scanning:** + 1. Recognize `security-ignore:` comments on the same line or line above finding 2. Still mention the suppressed finding in report but mark as `[SUPPRESSED]` 3. Validate suppression reason is present and not a placeholder @@ -934,7 +935,7 @@ The report must end with the exit code information: The skill respects `.gitignore` by default and supports `.secignore` for security-specific exclusions. -**`.secignore` format:** +`.secignore`** format:** Create a `.secignore` file at the repository root to exclude paths from security scans: @@ -963,6 +964,7 @@ docs/examples/ The `.secignore` file uses the same glob pattern syntax as `.gitignore`. Patterns are matched relative to the repository root. **Common patterns to exclude:** + - Test fixtures containing intentionally vulnerable code for testing - Mock credentials and API keys used in test suites - Generated OpenAPI specs or protobuf definitions @@ -976,6 +978,7 @@ By default, the skill shows **critical findings first** to reduce noise and focu **Default behavior:** Show only CRITICAL severity findings in the initial report. **Show all severities:** + ```bash /lfx-security-engineer --all ``` @@ -983,6 +986,7 @@ By default, the skill shows **critical findings first** to reduce noise and focu This displays critical, high, medium, and info findings. Use this for comprehensive audits or when addressing warnings after fixing critical issues. **Why progressive disclosure:** + - Prevents overwhelm for teams new to security scanning - Focuses attention on merge-blocking issues first - Reduces false positive fatigue by deferring lower-severity findings @@ -992,17 +996,20 @@ This displays critical, high, medium, and info findings. Use this for comprehens The skill caches scan results to skip unchanged files on repeat runs. **How it works:** + - On first run, all matching files are scanned and results are cached in `.security-cache/` - On subsequent runs, only files modified since the last scan are re-scanned - Cache is invalidated automatically when the skill version changes - Cache entries expire after 7 days of inactivity **Clear the cache manually:** + ```bash rm -rf .security-cache/ ``` **Performance impact:** + - First scan of a 500-file repo: ~5 minutes - Subsequent scans with <20 changed files: ~4 seconds - Cache hit rate typically >95% for normal development workflows @@ -1011,9 +1018,10 @@ rm -rf .security-cache/ ### Scan Modes -**`--full-scan`** — Scan all files in the repository, not just changed files. +`--full-scan` — Scan all files in the repository, not just changed files. Use cases: + - Initial security baseline for a new repository - After merging a major refactor or dependency upgrade - Periodic full audits (monthly or quarterly) @@ -1021,20 +1029,23 @@ Use cases: Performance: Expect 5-10 minutes for a medium-sized repo (~500 files). -**`--watch`** — Continuously watch for file changes and re-run scans automatically. +`--watch` — Continuously watch for file changes and re-run scans automatically. Use cases: + - Active development on auth or security-sensitive code - Refactoring session where you want instant feedback - Pair programming or mob programming sessions Behavior: + - Watches all files matching the repository type (`.ts`, `.go`, `.rs`, `.tf`, `.sql`) - Runs Phase 1 (automated scan) only by default for speed - Debounces file changes with a 2-second delay to avoid scan storms - Press `Ctrl+C` to stop watching Combine with `--scan-only` for minimal latency: + ```bash /lfx-security-engineer --watch --scan-only ``` @@ -1050,13 +1061,14 @@ Parallelization is automatic and scales with available CPU cores. No configurati **Tips for faster scans:** -1. **Use `--scan-only`** for rapid iteration — Phase 2 judgment-based reviews take longer +1. **Use **`--scan-only` for rapid iteration — Phase 2 judgment-based reviews take longer 2. **Scope to changed files** — the default behavior is already optimized for PRs 3. **Exclude generated code** — add `dist/`, `build/`, and `.next/` to `.secignore` 4. **Let the cache work** — avoid clearing `.security-cache/` unless you suspect stale results -5. **Use `--watch` during development** — eliminates the cost of repeated manual invocations +5. **Use **`--watch`** during development** — eliminates the cost of repeated manual invocations **Benchmark targets:** + - PR-sized scan (<20 files): <30 seconds (including Phase 2) - Full-repo scan (500 files): <5 minutes - Watch mode incremental scan: <5 seconds From 6c8eb040f4b79d220466c4b9cfb915d3b3072ef7 Mon Sep 17 00:00:00 2001 From: David Deal Date: Tue, 31 Mar 2026 17:30:08 -0700 Subject: [PATCH 07/12] fix(lfx-security-engineer): resolve CI exit code inconsistency The CI example claimed exit code 1 for blockers, but the exit code section defines exit code 2 for critical blockers and exit code 1 for warnings. Use "non-zero status" in the example to stay consistent with the canonical exit code table without duplicating specifics. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index 9161e37..2df3b1f 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -90,7 +90,7 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **What it does:** -- Exits with status code 1 if any `✗` blockers are found (fails the build) +- Exits with a non-zero status if any `✗` blockers are found (fails the build) - Outputs machine-readable JSON for parsing by CI tools - Suitable for GitHub Actions, GitLab CI, or Jenkins pipelines From d921d755bc630c9cb427bbc7f6ad8c8eff1f1771 Mon Sep 17 00:00:00 2001 From: David Deal Date: Tue, 31 Mar 2026 18:55:31 -0700 Subject: [PATCH 08/12] fix(lfx-security-engineer): clarify TypeScript BFF vs Angular server-side scope Fix typo ("andlogging") and replace the misleading claim that Angular repos are inherently Node.js/TypeScript server environments. The checks target the server-side TypeScript paths in LFX's Angular repo (e.g., its Express-based proxy layer), not browser-only Angular components. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index 2df3b1f..94b218f 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -205,7 +205,7 @@ Rust is detected via `Cargo.toml` before the TypeScript BFF fallback — a`Cargo | Dockerfile exposing a port | Containerized server application | | No index.html, src/app/, or *.vue files | Absence of frontend structure corroborates BFF | -The `typescript-bff` type applies the same access control, injection, auth, andlogging checks as `angular` — both are Node.js/TypeScript server environments. +The `typescript-bff` type applies the same access control, injection, auth, and logging checks as the server-side TypeScript paths in LFX's Angular repo (for example, its Express-based proxy layer); these checks always target Node.js/TypeScript server code, not browser-only Angular components. **Secondary signals — Rust** (use to confirm if primary is ambiguous): From a712df9fb4c2c6fc5f75a947894945ba476514b0 Mon Sep 17 00:00:00 2001 From: David Deal Date: Tue, 31 Mar 2026 19:03:11 -0700 Subject: [PATCH 09/12] fix(lfx-security-engineer): add --all flag to Modes section --all was referenced in the Progressive Disclosure section but absent from the Modes list, making it look like an unsupported option. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index 94b218f..ab03085 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -8,9 +8,16 @@ description: > data handling, infrastructure config, or database schema changes. allowed-tools: Bash, Read, Glob, Grep, AskUserQuestion, WebFetch --- + + + + # LFX Security Engineer -You are conducting a security review of LFX code changes. Identify realvulnerabilities and security anti-patterns — not noisy warnings. Every findingmust include a severity, file location, plain-language explanation, risk, andconcrete fix. +You are conducting a security review of LFX code changes. Identify real +vulnerabilities and security anti-patterns — not noisy warnings. Every finding +must include a severity, file location, plain-language explanation, risk, and +concrete fix. **Two phases:** @@ -20,13 +27,14 @@ You are conducting a security review of LFX code changes. Identify realvulnerabi **Modes:** - **Default:** Run both phases. -- `--scan-only`**:** Run Phase 1 only. Useful for quick pre-commit checks. -- `--file `**:** Scope the review to a specific file or directory. -- `--full-scan`**:** Run both phases on all files (not just changed files). Use for new repos or major refactors. -- `--explain`**:** Add detailed explanations for each check (educational mode). -- `--ci-mode`**:** Exit with non-zero status if any blockers are found. Output machine-readable JSON. -- `--format json`**:** Output results as structured JSON instead of text report. -- `--watch`**:** Watch for file changes and auto-run scan on save. Use during active development. +- **`--scan-only`:** Run Phase 1 only. Useful for quick pre-commit checks. +- **`--file `:** Scope the review to a specific file or directory. +- **`--full-scan`:** Run both phases on all files (not just changed files). Use for new repos or major refactors. +- **`--explain`:** Add detailed explanations for each check (educational mode). +- **`--ci-mode`:** Exit with non-zero status if any blockers are found. Output machine-readable JSON. +- **`--format json`:** Output results as structured JSON instead of text report. +- **`--watch`:** Watch for file changes and auto-run scan on save. Use during active development. +- **`--all`:** Show all severity levels (CRITICAL, HIGH, MEDIUM, INFO). Default shows CRITICAL only. ## Usage Examples @@ -493,12 +501,12 @@ statement { ```hcl # BAD — value visible in plan output and state output "db_password" { - value = aws_db_instance.main.password + value = var.db_password } # GOOD — redacted in output, still accessible programmatically output "db_password" { - value = aws_db_instance.main.password + value = var.db_password sensitive = true } ``` @@ -1093,4 +1101,4 @@ Parallelization is automatic and scales with available CPU cores. No configurati - Audit third-party dependencies (run `npm audit`, `govulncheck ./...`, or `trivy` separately) - Apply or validate Terraform plans against live infrastructure - Make architectural decisions (use `/lfx-product-architect`) -- Auto-fix security findings — all fixes require human review and commit \ No newline at end of file +- Auto-fix security findings — all fixes require human review and commit From b9e54506c0caa1008e5d8036782a09061904444b Mon Sep 17 00:00:00 2001 From: David Deal Date: Tue, 31 Mar 2026 19:10:00 -0700 Subject: [PATCH 10/12] fix(lfx-security-engineer): align Angular detection with lfx-preflight The LFX monorepo does not place @angular/core in the root package.json, so the previous root package.json check would silently fall through to typescript-bff on LFX repos. - Check apps/lfx-one/angular.json and turbo.json first, matching the detection logic used in lfx-preflight/SKILL.md - Keep the root package.json grep as a fallback for non-LFX Angular repos - Add LFX-specific files to the Angular secondary signals table with notes explaining their relationship to the monorepo structure - Update the explanatory text to document the alignment rationale Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 68 ++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index ab03085..cdbb35d 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -154,13 +154,19 @@ concrete fix. ## Repo Type Detection -Use a layered approach — no single file is foolproof, but combining signalsgives high confidence. +Use a layered approach — no single file is foolproof, but combining signals +gives high confidence. -**Primary signal** (highest confidence): check the package manager manifest forframework-specific markers. Each ecosystem has its own manifest file: +**Primary signal** (highest confidence): check the package manager manifest for +framework-specific markers. Each ecosystem has its own manifest file: ```bash # Detect primary application type -if [ -f package.json ] && grep -q '"@angular/core"' package.json; then +# Angular: check LFX monorepo structure first (matches lfx-preflight detection), +# then fall back to a root package.json check for non-LFX Angular repos. +if [ -f apps/lfx-one/angular.json ] || [ -f turbo.json ]; then + echo "REPO_TYPE=angular" +elif [ -f package.json ] && grep -q '"@angular/core"' package.json; then echo "REPO_TYPE=angular" elif [ -f package.json ] && grep -q '"vue"' package.json; then echo "REPO_TYPE=vue" @@ -180,18 +186,20 @@ find . -maxdepth 4 \( -path "*/migrations/*.sql" -o -name "*.up.sql" -o -name "* 2>/dev/null | grep -q . && echo "HAS_MIGRATIONS=true" ``` -Rust is detected via `Cargo.toml` before the TypeScript BFF fallback — a`Cargo.toml` is unambiguous, whereas `package.json` requires content inspection.Terraform and migration checks run whenever those files are detected — even inrepos that also have application code (monorepos). +Angular detection uses the same signals as `lfx-preflight`: `apps/lfx-one/angular.json` and `turbo.json` are checked first because the LFX monorepo does not place `@angular/core` in the root `package.json`. The root `package.json` grep is a fallback for non-LFX Angular repos only. Rust is detected via `Cargo.toml` before the TypeScript BFF fallback because `Cargo.toml` is unambiguous, whereas `package.json` requires content inspection. Terraform and migration checks run whenever those files are detected — even in repos that also have application code (monorepos). **Secondary signals — Angular** (use to confirm if primary is ambiguous): | File / Pattern | What it tells you | | --- | --- | -| angular.json | Angular CLI workspace config — very strong signal | -| ng-package.json | Angular library built with ng-packagr | -| .angular/ directory | Angular CLI cache (v14+) | -| tsconfig.app.json | Angular CLI generates this specifically | -| src/main.ts containing bootstrapApplication or platformBrowserDynamic | Angular bootstrap entrypoint | -| src/app/app.module.ts or src/app/app.config.ts | Standard Angular app structure | +| `apps/lfx-one/angular.json` | LFX monorepo Angular workspace — primary LFX signal (matches lfx-preflight) | +| `turbo.json` | LFX Turborepo config — present in the LFX monorepo alongside Angular workspace | +| `angular.json` at repo root | Angular CLI workspace config for non-LFX Angular repos — very strong signal | +| `ng-package.json` | Angular library built with ng-packagr | +| `.angular/` directory | Angular CLI cache (v14+) | +| `tsconfig.app.json` | Angular CLI generates this specifically | +| `src/main.ts` containing `bootstrapApplication` or `platformBrowserDynamic` | Angular bootstrap entrypoint | +| `src/app/app.module.ts` or `src/app/app.config.ts` | Standard Angular app structure | **Secondary signals — Vue** (use to confirm if primary is ambiguous): @@ -393,10 +401,16 @@ git diff --name-only origin/main...HEAD | grep -E '\.rs$' | \ Look for: -- `unsafe`** blocks** — flag every new `unsafe` block and verify it has a `// SAFETY:` commentexplaining why it cannot cause undefined behavior with attacker-controlled data -- **Command injection** — `Command::new()` or `std::process::Command` with values derivedfrom user input without allowlist validation -- **SQL injection** — `format!()` used to build query strings instead of parameterized queries(sqlx `query!` macro, Diesel typed queries, or sea-orm are safe alternatives) -- **Path traversal** — `std::fs` functions called with paths constructed from user input withoutcanonicalization and a prefix check +- `unsafe`** blocks** — flag every new `unsafe` block and verify it has a `// + SAFETY:` comment explaining why it cannot cause undefined behavior with + attacker-controlled data +- **Command injection** — `Command::new()` or `std::process::Command` with + values derived from user input without allowlist validation +- **SQL injection** — `format!()` used to build query strings instead of + parameterized queries(sqlx `query!` macro, Diesel typed queries, or sea-orm + are safe alternatives) +- **Path traversal** — `std::fs` functions called with paths constructed from + user input without canonicalization and a prefix check **Severity:** CRITICAL for all injection types. @@ -941,11 +955,13 @@ The report must end with the exit code information: ### Ignore Patterns -The skill respects `.gitignore` by default and supports `.secignore` for security-specific exclusions. +The skill respects `.gitignore` by default and supports `.secignore` for +security-specific exclusions. -`.secignore`** format:** +**`.secignore` format:** -Create a `.secignore` file at the repository root to exclude paths from security scans: +Create a `.secignore` file at the repository root to exclude paths from security +scans: ```text # Test fixtures and mock data (common false positives) @@ -969,7 +985,8 @@ docs/examples/ *.example.js ``` -The `.secignore` file uses the same glob pattern syntax as `.gitignore`. Patterns are matched relative to the repository root. +The `.secignore` file uses the same glob pattern syntax as `.gitignore`. +Patterns are matched relative to the repository root. **Common patterns to exclude:** @@ -991,7 +1008,8 @@ By default, the skill shows **critical findings first** to reduce noise and focu /lfx-security-engineer --all ``` -This displays critical, high, medium, and info findings. Use this for comprehensive audits or when addressing warnings after fixing critical issues. +This displays critical, high, medium, and info findings. Use this for +comprehensive audits or when addressing warnings after fixing critical issues. **Why progressive disclosure:** @@ -1022,7 +1040,8 @@ rm -rf .security-cache/ - Subsequent scans with <20 changed files: ~4 seconds - Cache hit rate typically >95% for normal development workflows -**Note:** The `.security-cache/` directory should be added to `.gitignore` — it's local-only and not meant for version control. +**Note:** The `.security-cache/` directory should be added to `.gitignore` — +it's local-only and not meant for version control. ### Scan Modes @@ -1047,7 +1066,8 @@ Use cases: Behavior: -- Watches all files matching the repository type (`.ts`, `.go`, `.rs`, `.tf`, `.sql`) +- Watches all files matching the repository type (`.ts`, `.go`, `.rs`, `.tf`, + `.sql`) - Runs Phase 1 (automated scan) only by default for speed - Debounces file changes with a 2-second delay to avoid scan storms - Press `Ctrl+C` to stop watching @@ -1060,12 +1080,14 @@ Combine with `--scan-only` for minimal latency: ### Performance Optimization -**Parallel checks:** Phase 1 automated scans run checks in parallel across multiple CPU cores. +**Parallel checks:** Phase 1 automated scans run checks in parallel across +multiple CPU cores. - **Single-threaded** (legacy mode): ~45 seconds for 100 files - **Parallel** (default): ~8 seconds for 100 files on a 4-core machine -Parallelization is automatic and scales with available CPU cores. No configuration needed. +Parallelization is automatic and scales with available CPU cores. No +configuration needed. **Tips for faster scans:** From 5f627e386eb9db9b026cd9346f88d89c987f7794 Mon Sep 17 00:00:00 2001 From: David Deal Date: Wed, 1 Apr 2026 07:45:51 -0700 Subject: [PATCH 11/12] style(lfx-security-engineer): fix markdown formatting and table alignment - Align all secondary signal and check tables with consistent column padding - Fix broken inline bold+code formatting (Use --scan-only, --watch) - Restore PII field table lost to linter (was collapsed to a single line) - Fix Phase 2 skip note formatting - Minor whitespace and comment style fixes Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 182 +++++++++++++++++---------------- 1 file changed, 95 insertions(+), 87 deletions(-) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index cdbb35d..843b2ab 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -8,6 +8,7 @@ description: > data handling, infrastructure config, or database schema changes. allowed-tools: Bash, Read, Glob, Grep, AskUserQuestion, WebFetch --- + @@ -107,7 +108,7 @@ concrete fix. ```yaml - name: Security Review run: /lfx-security-engineer --ci-mode --format json - continue-on-error: false # Fail the build on blockers + continue-on-error: false # Fail the build on blockers ``` ### Example 7: Watch Mode for Active Development (Power User) @@ -190,71 +191,71 @@ Angular detection uses the same signals as `lfx-preflight`: `apps/lfx-one/angula **Secondary signals — Angular** (use to confirm if primary is ambiguous): -| File / Pattern | What it tells you | -| --- | --- | -| `apps/lfx-one/angular.json` | LFX monorepo Angular workspace — primary LFX signal (matches lfx-preflight) | -| `turbo.json` | LFX Turborepo config — present in the LFX monorepo alongside Angular workspace | -| `angular.json` at repo root | Angular CLI workspace config for non-LFX Angular repos — very strong signal | -| `ng-package.json` | Angular library built with ng-packagr | -| `.angular/` directory | Angular CLI cache (v14+) | -| `tsconfig.app.json` | Angular CLI generates this specifically | -| `src/main.ts` containing `bootstrapApplication` or `platformBrowserDynamic` | Angular bootstrap entrypoint | -| `src/app/app.module.ts` or `src/app/app.config.ts` | Standard Angular app structure | +| File / Pattern | What it tells you | +| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | +| `apps/lfx-one/angular.json` | LFX monorepo Angular workspace — primary LFX signal (matches lfx-preflight) | +| `turbo.json` | LFX Turborepo config — present in the LFX monorepo alongside Angular workspace | +| `angular.json` at repo root | Angular CLI workspace config for non-LFX Angular repos — very strong signal | +| `ng-package.json` | Angular library built with ng-packagr | +| `.angular/` directory | Angular CLI cache (v14+) | +| `tsconfig.app.json` | Angular CLI generates this specifically | +| `src/main.ts` containing `bootstrapApplication` or `platformBrowserDynamic` | Angular bootstrap entrypoint | +| `src/app/app.module.ts` or `src/app/app.config.ts` | Standard Angular app structure | **Secondary signals — Vue** (use to confirm if primary is ambiguous): -| File / Pattern | What it tells you | -| --- | --- | -| vue.config.js or vue.config.ts | Vue CLI project config — very strong signal | -| vite.config.* containing @vitejs/plugin-vue | Vite-based Vue project | -| src/main.ts or src/main.js containing createApp | Vue 3 bootstrap entrypoint | -| src/App.vue | Standard Vue root component | -| *.vue files present | Single-file components — Vue-specific format | +| File / Pattern | What it tells you | +| ----------------------------------------------- | -------------------------------------------- | +| vue.config.js or vue.config.ts | Vue CLI project config — very strong signal | +| vite.config.\* containing @vitejs/plugin-vue | Vite-based Vue project | +| src/main.ts or src/main.js containing createApp | Vue 3 bootstrap entrypoint | +| src/App.vue | Standard Vue root component | +| \*.vue files present | Single-file components — Vue-specific format | **Secondary signals — TypeScript BFF** (use to confirm if primary is ambiguous): -| File / Pattern | What it tells you | -| --- | --- | -| src/main.ts or server.ts at root | Server entrypoint — strong signal | +| File / Pattern | What it tells you | +| ---------------------------------------------------------- | ------------------------------------------------ | +| src/main.ts or server.ts at root | Server entrypoint — strong signal | | tsconfig.json with "module": "commonjs" or "noEmit": false | Node.js compilation target, not a browser bundle | -| nest-cli.json | NestJS project — very strong signal | -| Dockerfile exposing a port | Containerized server application | -| No index.html, src/app/, or *.vue files | Absence of frontend structure corroborates BFF | +| nest-cli.json | NestJS project — very strong signal | +| Dockerfile exposing a port | Containerized server application | +| No index.html, src/app/, or \*.vue files | Absence of frontend structure corroborates BFF | The `typescript-bff` type applies the same access control, injection, auth, and logging checks as the server-side TypeScript paths in LFX's Angular repo (for example, its Express-based proxy layer); these checks always target Node.js/TypeScript server code, not browser-only Angular components. **Secondary signals — Rust** (use to confirm if primary is ambiguous): -| File / Pattern | What it tells you | -| --- | --- | -| Cargo.toml | Rust package manifest — definitive signal | -| Cargo.lock | Rust dependency lockfile | -| src/main.rs or src/lib.rs | Standard Rust binary or library entrypoint | -| build.rs | Cargo build script — often includes native deps or FFI | -| .cargo/config.toml | Workspace-level Cargo configuration | -| rust-toolchain or rust-toolchain.toml | Pinned Rust toolchain version | +| File / Pattern | What it tells you | +| ------------------------------------- | ------------------------------------------------------ | +| Cargo.toml | Rust package manifest — definitive signal | +| Cargo.lock | Rust dependency lockfile | +| src/main.rs or src/lib.rs | Standard Rust binary or library entrypoint | +| build.rs | Cargo build script — often includes native deps or FFI | +| .cargo/config.toml | Workspace-level Cargo configuration | +| rust-toolchain or rust-toolchain.toml | Pinned Rust toolchain version | **Secondary signals — Terraform/OpenTofu** (use to confirm if primary is ambiguous): -| File / Pattern | What it tells you | -| --- | --- | -| .terraform.lock.hcl | Terraform or OpenTofu dependency lock — very strong signal | -| versions.tf | Explicit provider and Terraform version constraints | -| main.tf, variables.tf, outputs.tf | Standard Terraform module structure | -| .terraform/ directory | Terraform initialized working directory | -| .opentofu/ directory | OpenTofu initialized working directory | -| *.tfvars files | Variable value files — check if committed | +| File / Pattern | What it tells you | +| --------------------------------- | ---------------------------------------------------------- | +| .terraform.lock.hcl | Terraform or OpenTofu dependency lock — very strong signal | +| versions.tf | Explicit provider and Terraform version constraints | +| main.tf, variables.tf, outputs.tf | Standard Terraform module structure | +| .terraform/ directory | Terraform initialized working directory | +| .opentofu/ directory | OpenTofu initialized working directory | +| \*.tfvars files | Variable value files — check if committed | **Secondary signals — Database Migrations** (use to confirm if primary is ambiguous): -| File / Pattern | What it tells you | -| --- | --- | -| migrations/ or db/migrations/ directory | Standard migration directory layout | -| V*.sql files | Flyway versioned migration convention | -| *.up.sql / *.down.sql files | golang-migrate up/down migration convention | -| atlas.hcl or atlas.sum | Atlas schema management tool | -| flyway.conf or flyway.toml | Flyway migration configuration | -| liquibase.properties or changelog.xml | Liquibase migration configuration | +| File / Pattern | What it tells you | +| --------------------------------------- | ------------------------------------------- | +| migrations/ or db/migrations/ directory | Standard migration directory layout | +| V\*.sql files | Flyway versioned migration convention | +| _.up.sql / _.down.sql files | golang-migrate up/down migration convention | +| atlas.hcl or atlas.sum | Atlas schema management tool | +| flyway.conf or flyway.toml | Flyway migration configuration | +| liquibase.properties or changelog.xml | Liquibase migration configuration | **Do not rely on alone (any framework):** @@ -278,12 +279,12 @@ git diff --name-only origin/main...HEAD | xargs grep -nE \ 2>/dev/null ``` -| Pattern | Severity | -| --- | --- | -| Hardcoded API keys or tokens | CRITICAL | -| Hardcoded passwords or connection strings | CRITICAL | +| Pattern | Severity | +| --------------------------------------------------------- | -------- | +| Hardcoded API keys or tokens | CRITICAL | +| Hardcoded passwords or connection strings | CRITICAL | | AWS/GCP/Azure credentials (AKIA..., service account JSON) | CRITICAL | -| Private keys in source (-----BEGIN RSA PRIVATE KEY-----) | CRITICAL | +| Private keys in source (-----BEGIN RSA PRIVATE KEY-----) | CRITICAL | **Safe patterns (do not flag):** @@ -326,22 +327,22 @@ Manually verify each flagged handler has an auth-bearing extractor in its parame Search changed files for weak cryptography: -| Anti-Pattern | Secure Alternative | Severity | -| --- | --- | --- | -| MD5 or SHA1 for passwords | bcrypt, argon2 | CRITICAL | -| Math.random() for tokens or session IDs | crypto.randomBytes() | HIGH | +| Anti-Pattern | Secure Alternative | Severity | +| ----------------------------------------------------- | ------------------------------------- | -------- | +| MD5 or SHA1 for passwords | bcrypt, argon2 | CRITICAL | +| Math.random() for tokens or session IDs | crypto.randomBytes() | HIGH | | JWT with alg: "none" or without algorithm enforcement | Always require and validate algorithm | CRITICAL | -| Non-HTTPS URLs in environment config | HTTPS endpoints only | HIGH | -| Short key or token lengths (< 128-bit) | 256-bit minimum | HIGH | +| Non-HTTPS URLs in environment config | HTTPS endpoints only | HIGH | +| Short key or token lengths (< 128-bit) | 256-bit minimum | HIGH | **Rust-specific patterns** — search changed `.rs` files and `Cargo.toml`: -| Anti-Pattern | Secure Alternative | Severity | -| --- | --- | --- | -| md5 or sha1 crates used for password hashing | argon2, bcrypt, or pbkdf2 crates | CRITICAL | -| rand::random() or rand::thread_rng() for security tokens | rand::rngs::OsRng with fill_bytes | HIGH | -| Custom crypto implementation (hand-rolled AES, RSA, etc.) | Audited crates: ring, rustls, aead | HIGH | -| openssl crate with verify_peer: false or disabled cert check | Always validate peer certificates | HIGH | +| Anti-Pattern | Secure Alternative | Severity | +| ------------------------------------------------------------ | ---------------------------------- | -------- | +| md5 or sha1 crates used for password hashing | argon2, bcrypt, or pbkdf2 crates | CRITICAL | +| rand::random() or rand::thread_rng() for security tokens | rand::rngs::OsRng with fill_bytes | HIGH | +| Custom crypto implementation (hand-rolled AES, RSA, etc.) | Audited crates: ring, rustls, aead | HIGH | +| openssl crate with verify_peer: false or disabled cert check | Always validate peer certificates | HIGH | ```bash # Flag use of weak hash crates for passwords @@ -401,8 +402,8 @@ git diff --name-only origin/main...HEAD | grep -E '\.rs$' | \ Look for: -- `unsafe`** blocks** — flag every new `unsafe` block and verify it has a `// - SAFETY:` comment explaining why it cannot cause undefined behavior with +- `unsafe`** blocks** — flag every new `unsafe` block and verify it has a + `// SAFETY:` comment explaining why it cannot cause undefined behavior with attacker-controlled data - **Command injection** — `Command::new()` or `std::process::Command` with values derived from user input without allowlist validation @@ -458,14 +459,21 @@ try { Search changed files for PII or sensitive data risks: -- FieldExamplesPasswords or secretspassword, passwd, secret, tokenFinancial datacreditCard, cardNumber, ssnContact infoemail, phone, addressIdentity datadob, dateOfBirth, birthDate, nationalIdDemographic datagender, sex, race, ethnicity +| Field Category | Examples | +| :------------------- | :-------------------------------------- | +| Passwords or secrets | password, passwd, secret, token | +| Financial data | creditCard, cardNumber, ssn | +| Contact info | email, phone, address | +| Identity data | dob, dateOfBirth, birthDate, nationalId | +| Demographic data | gender, sex, race, ethnicity | + - **Stack traces in API responses** — `res.json({ error: err.stack })` exposes internals - **Secrets or PII in URLs** — tokens, emails, or dates of birth in query strings appear in server logs and browser history - **Over-returning data** — endpoints returning entire DB rows (including`email`, `dob`, `gender`, `race`, or other PII fields) when only a subset isneeded by the caller ## Check 8: Terraform/OpenTofu — Infrastructure Security -**Skip if **`HAS_TERRAFORM`** is not set.** +**Skip if `HAS_TERRAFORM` is not set.** Search changed `.tf` and `.tfvars` files: @@ -501,12 +509,12 @@ statement { **Unencrypted storage:** -| Anti-Pattern | Fix | Severity | -| --- | --- | --- | -| S3 bucket without server_side_encryption_configuration | Add aws_s3_bucket_server_side_encryption_configuration resource | HIGH | -| RDS instance with storage_encrypted = false or missing | Set storage_encrypted = true | HIGH | -| aws_s3_bucket with acl = "public-read" | Remove public ACL; use bucket policies for intentional public access | HIGH | -| S3 block_public_acls = false or block_public_policy = false | Set all four block_public_* attributes to true | HIGH | +| Anti-Pattern | Fix | Severity | +| ----------------------------------------------------------- | -------------------------------------------------------------------- | -------- | +| S3 bucket without server_side_encryption_configuration | Add aws_s3_bucket_server_side_encryption_configuration resource | HIGH | +| RDS instance with storage_encrypted = false or missing | Set storage_encrypted = true | HIGH | +| aws_s3_bucket with acl = "public-read" | Remove public ACL; use bucket policies for intentional public access | HIGH | +| S3 block_public_acls = false or block_public_policy = false | Set all four block*public*\* attributes to true | HIGH | **Sensitive outputs:** @@ -534,7 +542,7 @@ output "db_password" { ## Check 9: Database Migrations — Schema Security -**Skip if **`HAS_MIGRATIONS`** is not set.** +**Skip if `HAS_MIGRATIONS` is not set.** Search changed migration files (`.sql`, `.up.sql`, `.down.sql`): @@ -554,13 +562,13 @@ INSERT INTO users (email, dob) VALUES ('test-user-1@example.invalid', '2000-01-0 - Flag new columns whose names suggest sensitive data stored without encryption or hashing: -| Column name pattern | Concern | -| --- | --- | -| password, passwd | Should be a hash — never plain text | -| ssn, tax_id, national_id | Should be encrypted at rest | -| credit_card, card_number, cvv | PCI DSS — should not be stored at all, or encrypted | -| dob, date_of_birth, birth_date | PII — consider column-level encryption | -| gender, race, ethnicity | Sensitive demographic — verify storage is intentional and documented | +| Column name pattern | Concern | +| ------------------------------ | -------------------------------------------------------------------- | +| password, passwd | Should be a hash — never plain text | +| ssn, tax_id, national_id | Should be encrypted at rest | +| credit_card, card_number, cvv | PCI DSS — should not be stored at all, or encrypted | +| dob, date_of_birth, birth_date | PII — consider column-level encryption | +| gender, race, ethnicity | Sensitive demographic — verify storage is intentional and documented | **Dynamic SQL in migration scripts:** @@ -583,7 +591,7 @@ INSERT INTO users (email, dob) VALUES ('test-user-1@example.invalid', '2000-01-0 # Phase 2: Security Review -**Skip if **`--scan-only`** was passed.** +**Skip if `--scan-only`** was passed.** Judgment-based analysis requiring code reading. Scope to changed files only. @@ -723,7 +731,7 @@ db.Raw(`DELETE FROM sessions WHERE user_id = ` + userId); ```html
-
+
{{.UserInput | safeHTML}} ``` @@ -1091,11 +1099,11 @@ configuration needed. **Tips for faster scans:** -1. **Use **`--scan-only` for rapid iteration — Phase 2 judgment-based reviews take longer +1. **Use `--scan-only` for rapid iteration** — Phase 2 judgment-based reviews take longer 2. **Scope to changed files** — the default behavior is already optimized for PRs 3. **Exclude generated code** — add `dist/`, `build/`, and `.next/` to `.secignore` 4. **Let the cache work** — avoid clearing `.security-cache/` unless you suspect stale results -5. **Use **`--watch`** during development** — eliminates the cost of repeated manual invocations +5. **Use `--watch` during development** — eliminates the cost of repeated manual invocations **Benchmark targets:** From a4f24ea9269a58a15d71e68409073f268c3f5166 Mon Sep 17 00:00:00 2001 From: David Deal Date: Thu, 2 Apr 2026 12:34:22 -0700 Subject: [PATCH 12/12] Added specific OWASP website lines for referencing in the final report Signed-off-by: David Deal --- lfx-security-engineer/SKILL.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lfx-security-engineer/SKILL.md b/lfx-security-engineer/SKILL.md index 843b2ab..44dde8c 100644 --- a/lfx-security-engineer/SKILL.md +++ b/lfx-security-engineer/SKILL.md @@ -294,6 +294,9 @@ git diff --name-only origin/main...HEAD | xargs grep -nE \ ## Check 2: OWASP A01 — Broken Access Control +Include [a direct link](https://owasp.org/Top10/2025/A01_2025-Broken_Access_Control/) +to the OWASP A01 website documentation in the report. + **Angular repos** — search changed route and controller files: - **Missing auth middleware** — Express routes that don't use `authMiddleware` or equivalent @@ -325,6 +328,9 @@ Manually verify each flagged handler has an auth-bearing extractor in its parame ## Check 3: OWASP A02 — Cryptographic Failures +Include [a direct link](https://owasp.org/Top10/2025/A02_2025-Security_Misconfiguration/) +to the OWASP A02 website documentation in the report. + Search changed files for weak cryptography: | Anti-Pattern | Secure Alternative | Severity | @@ -356,6 +362,9 @@ git diff --name-only origin/main...HEAD | grep -E '\.rs$' | \ ## Check 4: OWASP A03 — Injection +Include [a direct link](https://owasp.org/Top10/2025/A03_2025-Software_Supply_Chain_Failures/) +to the OWASP A03 website documentation in the report. + **Angular repos** — search changed TypeScript files: ```bash @@ -417,6 +426,9 @@ Look for: ## Check 5: OWASP A07 — Authentication Failures +Include [a direct link](https://owasp.org/Top10/2025/A07_2025-Authentication_Failures/) +to the OWASP A07 website documentation in the report. + Search changed authentication-related files (`auth`, `middleware`, `jwt`, `session`, `oauth`): - **Weak JWT validation** — signature not verified, or expired tokens accepted @@ -427,6 +439,9 @@ Search changed authentication-related files (`auth`, `middleware`, `jwt`, `sessi ## Check 6: OWASP A09 — Security Logging Failures +Include [a direct link](https://owasp.org/Top10/2025/A09_2025-Security_Logging_and_Alerting_Failures/) +to the OWASP A09 website documentation in the report. + Verify security-relevant events are logged in changed files. Look for: - **Silent auth failures** — token verification errors swallowed without logging @@ -1115,7 +1130,7 @@ configuration needed. **This skill DOES:** -- Scan changed files for OWASP Top 10 vulnerability patterns +- Scan changed files for [OWASP Top 10 vulnerability patterns](https://owasp.org/Top10/2025/) - Review authentication and authorization implementations - Flag hardcoded secrets, tokens, and credentials - Flag PII exposure risks (email, date of birth, demographic data, financial data)