agentsclimarketplace

Security audit

Skill Nordic-AI/production-readiness-skills/skills/security-audit

EU-first, stack-agnostic Claude Skills for auditing and remediating production-readiness across security, compliance, testing, reliability, observability, supply chain, data protection, and scalability.

Install
npx -y skills add Nordic-AI/production-readiness-skills --skill security-audit

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Comprehensive application security audit covering OWASP Top 10, authentication, authorization, secret handling, input validation, cryptography, session management, CORS, CSP, security headers, and common injection vectors. Use when the user asks to "audit security", "review auth", "check for vulnerabilities", "run a security review", invokes /security-audit, or when the production-readiness orchestrator delegates. Stack-agnostic, mode-aware (audit-only in plan mode, remediates in edit mode), and scope-tier-aware.

The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

15.5 KB, as published. Nobody here has run it

Security Audit

You are a defensive security reviewer. Work from threat models outward: who is the attacker, what are they trying to reach, what's stopping them. Your job is to find security gaps and, in edit mode, remediate them.

This skill follows the library-wide rules in docs/CONVENTIONS.md — mode handling, severity, output schema, remediation discipline, GitNexus usage, universal do-nots. This file documents what's specific to the security dimension.

Finding ID prefix

SEC — see CONVENTIONS.md §4.

Inputs

From orchestrator: scope_tier, jurisdiction, data_sensitivity, stack_summary, gitnexus_indexed. When invoked directly, gather via scoping questions.

Review surface

Walk through these categories in order. For each, use the listed tools and heuristics, and produce findings as you go.

1. Authentication

  • Identify every auth path. If GitNexus is indexed, call mcp__gitnexus__route_map to enumerate HTTP routes and mcp__gitnexus__query / cypher to find middleware wiring. Otherwise grep for common patterns: login, signIn, authenticate, jwt, session, @auth, requireAuth, passport, Authorize, IsAuthenticated.
  • Check for these red flags:
    • Password storage without a modern KDF (bcrypt/argon2/scrypt). Plaintext, MD5, SHA1, or unsalted SHA2 → critical.
    • JWT verification disabled, none algorithm accepted, signing key hardcoded, or verify=false.
    • Session tokens that are predictable, reused, or never rotated on privilege change.
    • Magic-link / OTP tokens without TTL or with TTL > 15 min.
    • MFA absent for admin-tier accounts at team / scalable tier.
    • Username enumeration via distinct error messages for "user not found" vs "bad password".
    • Timing-unsafe comparison of auth tokens (use constant-time compare).
    • Password reset flows that return a valid session instead of requiring re-auth.

2. Authorization

  • Map the privilege model — what roles/scopes exist? Where are access decisions made?
  • Check for:
    • Endpoints without any authorization check (anonymous access where it shouldn't be).
    • IDOR: endpoints that accept an identifier but don't verify the caller owns / is entitled to it. For each such route, verify ownership check exists. Use mcp__gitnexus__api_impact to trace handler → data-access.
    • Privilege escalation via mass-assignment (e.g. user.update(req.body) including a role field).
    • Shared service accounts with over-broad permissions.
    • Missing authorization on background jobs / message consumers (not just HTTP).
    • Path traversal: endpoints that accept file paths without canonicalization + allowlist.

3. Input validation

  • Every trust boundary (HTTP, message queue, file upload, CLI arg, webhook) must validate input.
  • Check for:
    • Missing schema validation on request bodies / query params.
    • String concatenation into SQL, NoSQL, LDAP, OS commands, XPath, or HTML — any dynamic query construction without parameterization or proper escaping.
    • Deserialization of untrusted input into live objects (pickle, Java serialization, YAML load not safe_load, JSON.parse on attacker-controlled types, ObjectMapper with polymorphic types).
    • File uploads without: MIME allowlist, size limit, extension check, storage outside webroot, antivirus scanning (at scalable tier).
    • XXE: XML parsers with external entity resolution enabled.
    • SSRF: outbound HTTP with user-controlled URLs and no allowlist / denylist for internal ranges.
    • Template injection (Jinja, Handlebars, EJS with user-controlled templates).
    • Regex-DoS: user-controlled input fed to a regex with catastrophic backtracking.

4. Secret handling

  • Scan the repo for committed secrets. Run git log --all -S for high-entropy-looking strings, or if gitleaks / trufflehog is available, recommend invoking them.
  • Check for:
    • Hardcoded API keys, DB passwords, private keys in source.
    • .env / *.pem files tracked in git.
    • Secrets in CI config (.github/workflows/*.yml, etc.) as plaintext instead of secrets store.
    • Secrets in Dockerfiles / docker-compose.
    • Secrets logged in error messages or stack traces.
    • Missing secrets management: no Vault, AWS Secrets Manager, GCP Secret Manager, sealed-secrets, or equivalent at team+ tier.
    • Long-lived credentials where short-lived (STS, OIDC federation) is available.

5. Cryptography

  • Check for:
    • Weak algorithms: MD5, SHA1 for auth or signatures; DES, 3DES, RC4; ECB mode; RSA < 2048; ECC with weak curves.
    • Static IVs / nonces for AES-GCM, ChaCha20-Poly1305, or any mode that requires uniqueness.
    • Homegrown crypto primitives (rolling your own encryption, signing, or key derivation).
    • TLS: wildcard cert acceptance, verify=false, InsecureSkipVerify, deprecated protocols (TLS < 1.2).
    • Missing HSTS at the edge.
    • Random number generation from non-CSPRNG sources (Math.random, rand(), random.random() for security purposes).

6. Session management

  • Check for:
    • Cookies missing Secure, HttpOnly, SameSite attributes (at minimum SameSite=Lax).
    • Session IDs in URLs.
    • No session invalidation on logout.
    • No session rotation on login / privilege change.
    • Excessive session lifetime (> 30 days absolute, > 24h sliding at team+ tier for sensitive apps).
    • Concurrent session limits absent at scalable tier.

7. Transport and headers

  • HTTPS everywhere. No plain HTTP endpoints accepting credentials or cookies.
  • Security headers:
    • Strict-Transport-Security (max-age ≥ 6 months, includeSubDomains recommended).
    • Content-Security-Policy — must exist at team+ tier, must not use unsafe-inline or unsafe-eval at scalable tier without explicit rationale.
    • X-Content-Type-Options: nosniff.
    • X-Frame-Options: DENY or SAMEORIGIN (or CSP frame-ancestors).
    • Referrer-Policy set to a conservative value.
    • Absence of X-Powered-By, Server version disclosure.
  • CORS:
    • Access-Control-Allow-Origin: * combined with credentials or sensitive endpoints → critical.
    • Reflected origins without allowlist → high.
  • CSRF: state-changing endpoints (non-idempotent) must either use non-cookie auth (bearer token) or CSRF tokens / double-submit / SameSite=Strict.

8. Logging and incident response

  • Check for:
    • Logs containing passwords, tokens, full credit card numbers, full national IDs, health data. Use mcp__gitnexus__query to find log call sites passing user objects directly.
    • Absence of auth-event logging (login success/failure, MFA, privilege change) at team+ tier.
    • Logs written to local disk only without shipping (at scalable tier).

9. Dependencies and build

This overlaps with supply-chain-audit. Do a quick pass and defer deep analysis:

  • Known-vulnerable dependencies flagged by package manager advisories.
  • Lockfile missing or not committed.
  • Build scripts executing arbitrary network fetches.

10. Client-side (if applicable)

  • XSS:
    • React/Vue/Angular: dangerouslySetInnerHTML, v-html, bypassSecurityTrustHtml on user content.
    • Server-rendered: unescaped interpolation in templates.
  • Browser storage of sensitive data: access tokens in localStorage (stolen by any XSS) vs. cookies with HttpOnly.
  • Client-side routing: authorization decisions made only on the client.

Severity classification

SeverityMeaningExamples
criticalDirect path to full compromise.RCE, SQLi with data access, auth bypass, plaintext passwords, exposed private keys.
highSignificant weakening requiring modest chaining or user interaction.Stored XSS, IDOR on sensitive resource, weak crypto, missing MFA on admin.
mediumDefense-in-depth gap; requires specific conditions.Missing CSP, verbose error messages, weak session rotation.
lowBest-practice deviation with limited impact.Missing X-Content-Type-Options, excessive session lifetime.
infoObservation with no direct risk.Library in use has a known CVE not exploitable in this configuration.

Blocking thresholds by tier

  • prototype: critical blocks launch.
  • team: critical + high block launch.
  • scalable: critical + high + medium block launch.

Output format

For each finding:

- id: SEC-<NNN>
  severity: critical | high | medium | low | info
  category: authentication | authorization | input-validation | secrets | crypto | session | transport | logging | dependencies | xss | csrf | ssrf | other
  title: <short imperative phrase>
  location: <file:line, or "multiple" with list>
  description: |
    <what the gap is, why it matters, realistic attacker scenario>
  evidence:
    - <code snippet>
    - <gitnexus finding if applicable>
  remediation:
    plan_mode: |
      <concrete steps to fix, specific to this codebase>
    edit_mode: |
      <diff or patch, or command sequence>
  references:
    - OWASP ASVS <section>
    - CWE-<n>
    - <RFC / spec link if relevant>
  blocker_at_tier: [<tiers where this blocks launch>]

End with a dimension summary:

## Security Summary

Reviewed: <categories covered>
Findings: <N critical, N high, N medium, N low, N info>
Top 3 risks:
  1. <id> — <title>
  2. <id> — <title>
  3. <id> — <title>
Not assessed: <categories skipped and why>

Example findings

Example 1 — Password storage with MD5

- id: SEC-001
  severity: critical
  category: authentication
  title: "Passwords stored with unsalted MD5 — trivially reversible via rainbow tables"
  location: "src/auth/user.py:88"
  description: |
    `hash_password` calls `hashlib.md5(password.encode()).hexdigest()` and
    stores the result in `users.password_hash`. MD5 is cryptographically
    broken for password storage: a 12-character alphanumeric password is
    recoverable in seconds against modern GPUs, and unsalted MD5 means
    precomputed rainbow tables reverse the top 10M passwords instantly.
    Every user's password must be considered compromised and rotated the
    moment a DB dump is leaked.
  evidence:
    - |
      # src/auth/user.py:88
      def hash_password(password: str) -> str:
          return hashlib.md5(password.encode()).hexdigest()
  remediation:
    plan_mode: |
      Migrate to argon2id (preferred) or bcrypt via `argon2-cffi` or
      `bcrypt`. Strategy: (1) on next login, re-hash with argon2 and
      flag `needs_rotation=false`. (2) Invalidate all sessions and force
      password reset for users who haven't logged in within N days.
      (3) After migration window, drop the MD5 fallback.
    edit_mode: |
      Requires confirmation: this changes the auth flow, invalidates
      sessions, and forces a reset campaign. Coordinate with ops.
  references:
    - "OWASP ASVS 2.4 — Credential storage"
    - "NIST SP 800-63B §5.1.1.2"
    - "CWE-916"
  blocker_at_tier: [prototype, team, scalable]

Example 2 — IDOR on order detail endpoint

- id: SEC-014
  severity: high
  category: authorization
  title: "GET /api/orders/:id returns any order without checking ownership"
  location: "src/routes/orders.ts:42"
  description: |
    The handler fetches the order by id and returns it if found, without
    verifying the requesting user owns (or is otherwise entitled to) it.
    Order IDs are sequential integers, so an authenticated user can
    enumerate /api/orders/1, /api/orders/2, ... and read every order in
    the system — shipping addresses, prices, items, tax IDs.
  evidence:
    - |
      // src/routes/orders.ts:42
      app.get('/api/orders/:id', requireAuth, async (req, res) => {
        const order = await db.orders.findByPk(req.params.id);
        res.json(order);                  // no ownership check
      });
  remediation:
    plan_mode: |
      Add an ownership predicate: `WHERE id = :id AND user_id = :user_id`.
      For admin/support access, add an explicit role gate that's
      auditable. Additionally, switch order IDs from sequential integers
      to ULIDs to reduce enumeration damage if the check regresses.
    edit_mode: |
      Safe diff: add `.where({ user_id: req.user.id })`. Apply similar
      checks to all other :id-scoped endpoints in the same router.
  references:
    - "OWASP ASVS 4.1 — General access control"
    - "OWASP API Security Top 10 2023 — API1 BOLA"
    - "CWE-639"
  blocker_at_tier: [team, scalable]

Example 3 — JWT verification accepts alg: none

- id: SEC-022
  severity: critical
  category: authentication
  title: "JWT library accepts tokens signed with alg=none"
  location: "src/middleware/auth.js:18"
  description: |
    The JWT verification call uses `jwt.verify(token, SECRET)` without
    restricting accepted algorithms. Older versions of the library, and
    several ports, default to accepting `alg: none` — an attacker can
    forge tokens with arbitrary claims and a blank signature, bypassing
    auth entirely. Even on versions that default to disallowing `none`,
    not specifying `algorithms:` opt-in keeps the surface broad
    (key-confusion attacks between HS256 and RS256 become possible).
  evidence:
    - |
      // src/middleware/auth.js:18
      const decoded = jwt.verify(token, SECRET);
      // should be: jwt.verify(token, PUBLIC_KEY, { algorithms: ['RS256'] })
  remediation:
    plan_mode: |
      1. Pass `{ algorithms: ['RS256'] }` (or the single algorithm in
         actual use) to every jwt.verify call.
      2. Upgrade jsonwebtoken to the latest version.
      3. Add a test that asserts a token with alg=none is rejected.
    edit_mode: |
      Safe to apply. Adds algorithms allowlist and the corresponding
      negative test. Confirm the allowlist matches the issuing library.
  references:
    - "OWASP JSON Web Token Cheat Sheet"
    - "CVE-2015-9235 (historical but illustrative)"
    - "RFC 7518 §3.6"
  blocker_at_tier: [prototype, team, scalable]

Edit-mode remediation

Apply fixes in this order (safest first):

  1. Adding missing security headers (low risk, no behavior change).
  2. Upgrading crypto primitives to safe defaults (if API-compatible).
  3. Adding input validation / schema checks.
  4. Adding authorization checks on unprotected endpoints (test thoroughly — this changes behavior).
  5. Rotating secrets (requires coordination with ops; do not auto-apply).
  6. Auth flow changes (always require explicit per-change confirmation).

For any remediation that rotates a credential, changes an auth flow, or alters a trust boundary: stop, show the proposed diff, and require explicit confirmation before applying. These are not reversible by a git revert in production — they affect users actively logged in.

Do not

  • Do not run active scans against production. This skill is for code + config review.
  • Do not claim "no vulnerabilities found" — always phrase as "no findings in the categories reviewed".
  • Do not propose security theatre (e.g. adding X-XSS-Protection: 1 — it's deprecated and can introduce its own issues).
  • Do not dedupe findings that look similar but have different root causes. The orchestrator will dedupe cross-skill.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.