Skip to content
Back to skills

Audit Orchestration

ASecurity

Four-phase security-audit orchestrator: (1) detect available scanners and mark coverage gaps; (2) run each scanner scoped by stack-profile.json; (3) normalise findings into .claude/pilot/audit/findings.json (severity P0-P3, cwe, owasp, file, line, evidence, proposedFix); (4) generate AUDIT-REPORT.md and print the P0 table. Claude semantic pass strictly limited to IDOR/missing authorization, tenant isolation, authN/authZ logic, and secrets in config — every finding must cite file:line evidence...

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 6, 2026
developmenttypescriptgoc#bashsqlangularawsazuregitapi

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned September 6, 2026

npx -y skills add AgenticPawan/FullStack-Pilot --skill audit-orchestration --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Audit Orchestration?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Audit Orchestration
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/agenticpawan-audit-orchestration/badge)](https://www.skillsdirectory.com/skills/agenticpawan-audit-orchestration)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
user-invocable: false
name: audit-orchestration
description: "Four-phase security-audit orchestrator: (1) detect available scanners and mark coverage gaps; (2) run each scanner scoped by stack-profile.json; (3) normalise findings into .claude/pilot/audit/findings.json (severity P0-P3, cwe, owasp, file, line, evidence, proposedFix); (4) generate AUDIT-REPORT.md and print the P0 table. Claude semantic pass strictly limited to IDOR/missing authorization, tenant isolation, authN/authZ logic, and secrets in config — every finding must cite file:line evidence or is discarded."
when_to_use: Invoke via /fsp-audit. Use when the user requests a security audit, vulnerability scan, OWASP review, dependency check, or tenant-isolation review on the current project.
disable-model-invocation: true
---

<!-- ARCHITECTURE RULE: scanners detect; Claude triages. Claude alone misses and hallucinates; scanners alone drown in noise. Never present a Claude-only scan as complete. -->
<!-- EVIDENCE RULE: every semantic finding MUST include file:line and a quoted code snippet. Discard any finding that cannot cite evidence. -->
<!-- SCOPE: PROJECT_ROOT is the user's project directory (not this plugin repo). -->
<!-- PLUGIN EXTENSIONS: pilot-sql adds Checks E (migration safety). pilot-azure adds Check F (Bicep security baseline). Both use the same findings.json schema. -->
<!-- POLICY LAYER: dependency-vulnerability findings from Steps 2a/2c (dotnet/npm) feed into the dependency-supply-chain skill's severity-to-patch-cadence SLA — that skill governs triage response, this one only detects. -->

## Step 0 — Load stack profile

Read `PROJECT_ROOT/.claude/pilot/stack-profile.json`. If absent, tell the user to run `/fsp-init` first and stop.

Extract scope directories:
- `dotnetDirs`: directories containing each project listed in `dotnet.projects[*].path` (parent dirs)
- `angularRoot`: `PROJECT_ROOT` if `angular` is non-null
- `bicepFiles`: `azure.bicepFiles` array

---

## Step 1 — Tool detection

Check each tool's availability. Use the Bash tool with `--version` or equivalent dry-run flags. **Never install anything — only detect.**

| Tool | Detection command | Covers |
|------|-------------------|--------|
| dotnet CLI | `dotnet --version` | NuGet vulnerability advisories, Roslyn build |
| npm | `npm --version` | npm audit |
| semgrep | `semgrep --version` | SAST (C#, TypeScript, security rulesets) |
| eslint | `npx eslint --version` (only if `angular.eslint` is true in profile) | TS/HTML security rules |
| bicep CLI | `az bicep version` or `bicep --version` | Bicep lint |
| PSRule | `pwsh -c "Get-Module PSRule.Rules.Azure -ListAvailable"` | Azure IaC rules |

Build two lists:
- **available**: tools that responded without error
- **missing**: tools that were not found, each with the install command

Print a coverage table at the start of the report and log coverage gaps as `source: "coverage-gap"` entries in findings.json.

---

## Step 2 — Run scanners

Run each available scanner. Capture output. **Do not abort on scanner errors** — log the error as a coverage gap and continue.

### 2a. dotnet vulnerability advisory scan

```
dotnet list <solution-or-project> package --vulnerable --include-transitive
```

Run once per solution file found in `dotnet.solutions`. If no solution, run per project. Parse output for lines matching `> <PackageName> <InstalledVersion>` with a severity label.

### 2b. Roslyn build warnings

```
dotnet build <solution> -warnaserror:false -p:TreatWarningsAsErrors=false 2>&1
```

Capture all `warning CS` lines. Include only these Roslyn analyzer IDs in findings (others are noise):
- `CA2100` — SQL command injection
- `CA1416` — Platform compatibility  
- `CA2012` — ValueTask misuse
- `SA1*` / `SX*` — only if they surface CWE-related patterns

### 2c. npm audit

```
npm audit --json
```

Run from `angularRoot` if `angular` is non-null. Parse JSON response. Include only `moderate`, `high`, `critical` advisories.

### 2d. Semgrep (if available)

```
semgrep scan --config p/csharp --config p/typescript --config p/security-audit \
  --json --no-git-ignore <dotnetDir> <angularRoot>
```

Parse the `results` array from JSON output.

### 2e. ESLint security (if available and `angular.eslint` is true)

```
npx eslint --ext .ts,.html --format json <angularRoot>/src
```

Parse output for rules matching `security/`, `@angular-eslint/no-` patterns.

### 2f. Bicep lint (if available)

```
az bicep lint --file <bicepFile>
```

Run per file in `azure.bicepFiles`. Parse output for errors and warnings.

---

## Step 3 — Claude semantic pass

**Strictly limited to four check types. Do not expand scope.**

Read source files in `dotnetDirs` and `angularRoot/src`. Budget: **≤ 60 files total**. Prioritise controllers, repositories, DbContext, service files, and component templates.

### Check A — IDOR / missing authorization on endpoints

For each HTTP endpoint method in controllers:
1. Does the method lack `[Authorize]` or equivalent policy? → finding if the endpoint is not intentionally public (check for `[AllowAnonymous]`)
2. Does the method fetch a resource by ID without verifying `resource.OwnerId == currentUserId` (or equivalent claim check)? → IDOR finding

Evidence required: file path, line number, and the method signature + the missing check.

### Check B — Tenant-isolation gaps

For each `DbContext.OnModelCreating`:
1. Does it define a global query filter for a `TenantId` or `OrganisationId` property? If the domain has multi-tenant markers (any entity with `TenantId`/`OrgId` field) but no `HasQueryFilter` for those entities → tenant-isolation finding.
2. Does any repository method call `IgnoreQueryFilters()` without a justification comment? → tenant-bypass finding.

### Check C — AuthN/authZ logic flaws

1. JWT validation: is `ValidateIssuerSigningKey` or `ValidateAudience` explicitly set to `false`? → critical finding
2. Role checks: any `.ToLower()`/`.ToUpper()` comparison on role strings (case-sensitive auth bypass)?
3. Cookie auth: `CookieSecurePolicy.Never` or `HttpOnly = false` set explicitly?

### Check D — Secrets in config

1. Scan `appsettings*.json` and `*.env*` files for patterns: `Password=`, `AccountKey=`, `ConnectionString` with embedded credentials, `ApiKey`, `Secret` assigned a non-placeholder string value.
2. Scan C# source for string literals matching: `Password=`, `AccountKey=`, bearer token patterns, base64 blobs > 40 chars in auth contexts.
3. Skip placeholders: `<value>`, `#{...}#`, `${...}`, `__REPLACE__`, `your-*-here`.

**Discard finding if you cannot quote the exact string from the file.**

### Check E — EF Core migration safety (pilot-sql)

Run this check only if `dotnet` is non-null in the stack profile and migration files exist.

Glob `**/Migrations/*.cs` (exclude `*Designer.cs`, `*Snapshot.cs`). For each migration:

1. **MIG-001/002 (P1):** does `Up()` call `DropColumn(` or `DropTable(`? → finding
2. **MIG-003 (P1):** does `AlterColumn` narrow a type (smaller `maxLength`, or wider→narrower CLR type)?
3. **MIG-004 (P1):** does `AddColumn` set `nullable: false` with no `defaultValue`?
4. **MIG-006 (P2):** is `Down()` empty or absent when `Up()` contains any destructive call?

Evidence must quote the specific `migrationBuilder.` call and its line number.
All migration findings use `batchable: false`.

### Check F — Azure/Bicep security baseline (pilot-azure)

Run this check only if `azure.bicepFiles` is non-empty in the stack profile.

For each `.bicep` file listed in `azure.bicepFiles`:

1. **ASB-NS-1 (P0):** any `allowBlobPublicAccess: true` or `publicAccess: 'Blob'`/`'Container'`? → finding
2. **ASB-IM-1 (P0):** any `listKeys()` call in outputs or app-settings values? → finding
3. **WAF-OPS-001 (P2):** scan `azure.githubActionsFiles` — does the workflow lack a `what-if` step before the deployment step?
4. **WAF-COST-001 (P2):** does any resource declaration lack a `tags:` property?

Evidence must quote the exact Bicep line. OWASP mapping: ASB-NS-1 → A05:2021, ASB-IM-1 → A02:2021.

---

## Step 4 — Normalise to findings.json

Write `PROJECT_ROOT/.claude/pilot/audit/findings.json` with this schema:

```json
[
  {
    "id": "VULN-001",
    "source": "scanner | semantic | coverage-gap",
    "severity": "P0 | P1 | P2 | P3",
    "cwe": "CWE-89",
    "owasp": "A03:2021",
    "wcag": null,
    "file": "src/Api/Controllers/UsersController.cs",
    "line": 22,
    "title": "SQL injection via string concatenation",
    "evidence": "var sql = $\"SELECT * FROM Users WHERE name='{name}'\";",
    "proposedFix": "Replace with EF Core LINQ or FromSqlInterpolated",
    "batchable": true,
    "confidence": "high | medium | low"
  }
]
```

### Severity policy

| Severity | Criteria |
|----------|----------|
| P0 | Exploitable now: injection, auth bypass, exposed secret, tenant data leak |
| P1 | Exploitable with conditions; vulnerable direct dependency in reachable path |
| P2 | Hardening gaps; vulnerable transitive dependency |
| P3 | Hygiene (informational, style, dead code) |

### CVSS alignment

- CVSS ≥ 9.0 (Critical) → P0
- CVSS 7.0–8.9 (High) → P1
- CVSS 4.0–6.9 (Medium) → P2
- CVSS < 4.0 (Low) → P3

### ID scheme

Sequential: `VULN-001`, `VULN-002`, … sorted by severity (P0 first).

### Coverage gaps

Add one entry per missing scanner:
```json
{
  "id": "GAP-001",
  "source": "coverage-gap",
  "severity": "P3",
  "title": "semgrep not installed — SAST coverage absent",
  "evidence": "semgrep not found in PATH",
  "proposedFix": "pip install semgrep",
  "batchable": false,
  "confidence": "n/a"
}
```

---

## Step 5 — Generate AUDIT-REPORT.md

Write `PROJECT_ROOT/.claude/pilot/audit/AUDIT-REPORT.md`:

```markdown
# Security Audit Report

**Generated:** <ISO date>  
**Project:** <basename of PROJECT_ROOT>  
**Scanners run:** <comma-separated list>  
**Coverage gaps:** <list or "none">

## Executive Summary

| Severity | Count |
|----------|-------|
| P0 (Critical) | N |
| P1 (High)     | N |
| P2 (Medium)   | N |
| P3 (Low)      | N |
| **Total**     | **N** |

## P0 Findings

<one sub-section per P0 finding: ### VULN-NNN — <title>, evidence block, proposed fix>

## P1 Findings

...

## P2 Findings

...

## P3 / Coverage Gaps

...
```

After writing the file, **print the P0 table inline in chat** so the user sees it immediately without opening the file.

---

## Step 6 — Final output

Print in chat:

```
## Audit complete

findings.json  → .claude/pilot/audit/findings.json  (<N> findings)
AUDIT-REPORT   → .claude/pilot/audit/AUDIT-REPORT.md

Coverage: <scanners used> | Gaps: <missing scanners or "none">

<P0 table here>

Run /fsp-fix --batch P0 to begin remediation on P0 findings.
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…