All skills
sergiodxa avatar

/owasp-security-check

@40e21b4

Security audit guidelines for web applications and REST APIs based on OWASP Top 10 and web security best practices. Use when checking code for vulnerabilities, reviewing auth/authz, auditing APIs, or before production deployment.

Use this Skill: https://skilld.dev/gh/sergiodxa/agent-skills/owasp-security-check

This session only. Nothing lands on disk.

rulesauthentication-failures.md

≈1.2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Authentication Failures

Check for weak authentication mechanisms, missing MFA, session management issues, and credential handling vulnerabilities.

Related: Session security in session-security.md. Rate limiting in rate-limiting.md.

Why

  • Account takeover: Attackers gain unauthorized access to user accounts
  • Credential stuffing: Weak auth enables automated attacks
  • Session hijacking: Improper session management allows theft
  • Brute force attacks: Weak passwords and no rate limiting enable guessing

What to Check

  • Weak password requirements (length < 12, no complexity)
  • No multi-factor authentication option
  • Passwords stored in plaintext or with weak hashing (MD5, SHA1)
  • Missing account lockout after failed attempts
  • Session tokens predictable or not securely generated
  • No session expiration or timeout
  • Session not regenerated after login
  • Credentials exposed in URLs or logs

Bad Patterns

// Bad: Weak password hashing (SHA-256 too fast)
const hash = crypto.createHash("sha256").update(password).digest("hex");

// Bad: No password requirements
async function signup(req: Request): Promise<Response> {
  let { email, password } = await req.json();
  // Accepts "123" as valid password!
  await db.users.create({
    data: { email, password: await bcrypt(password, 10) },
  });
}

// Bad: Timing attack reveals if email exists
const user = await db.users.findUnique({ where: { email } });
if (!user) return new Response("Invalid", { status: 401 }); // Early return!
if (!(await bcrypt.compare(password, user.password))) {
  return new Response("Invalid", { status: 401 });
}

// Bad: No rate limiting or account lockout
async function login(req: Request): Promise<Response> {
  // Unlimited attempts allowed!
  let user = await authenticate(email, password);
}

Good Patterns

// Good: bcrypt with proper cost factor
const hash = await bcrypt(password, 12); // Cost factor 12+

// Good: Strong password validation
function validatePassword(password: string): string | null {
  if (password.length < 12) return "Password must be ≥12 characters";
  if (!/[A-Z]/.test(password)) return "Must include uppercase";
  if (!/[a-z]/.test(password)) return "Must include lowercase";
  if (!/[0-9]/.test(password)) return "Must include number";
  return null;
}

async function signup(req: Request): Promise<Response> {
  let { email, password } = await req.json();

  let error = validatePassword(password);
  if (error) return new Response(error, { status: 400 });

  await db.users.create({
    data: { email, password: await bcrypt(password, 12) },
  });
}

// Good: Constant-time comparison
async function login(req: Request): Promise<Response> {
  let { email, password } = await req.json();
  let user = await db.users.findUnique({ where: { email } });

  // Always compare (constant time)
  let hash = user?.password || "$2b$12$fakehash...";
  let valid = await bcrypt.compare(password, hash);

  if (!user || !valid) {
    return new Response("Invalid credentials", { status: 401 });
  }

  return createSession(user);
}

// Good: Account lockout after failed attempts
async function loginWithLockout(req: Request): Promise<Response> {
  let { email, password } = await req.json();
  let user = await db.users.findUnique({ where: { email } });

  if (user?.lockedUntil && user.lockedUntil > new Date()) {
    return new Response("Account locked", { status: 423 });
  }

  let valid = user && (await bcrypt.compare(password, user.password));

  if (!user || !valid) {
    let attempts = (user?.failedAttempts || 0) + 1;
    await db.users.update({
      where: { email },
      data: {
        failedAttempts: attempts,
        lockedUntil:
          attempts >= 5 ? new Date(Date.now() + 30 * 60 * 1000) : null,
      },
    });
    return new Response("Invalid credentials", { status: 401 });
  }

  // Reset on success
  await db.users.update({
    where: { id: user.id },
    data: { failedAttempts: 0, lockedUntil: null },
  });

  return createSession(user);
}

Rules

  1. Require strong passwords - Minimum 12 characters with complexity
  2. Hash passwords properly - Use bcrypt, argon2, or scrypt (never MD5/SHA1)
  3. Implement rate limiting - Limit authentication attempts per IP/account
  4. Use secure session tokens - Cryptographically random tokens
  5. Set session expiration - Both absolute and idle timeout
  6. Regenerate session on login - Prevent session fixation attacks
  7. Implement account lockout - Temporarily lock after multiple failures
  8. Support MFA - Especially for privileged accounts
  9. Never log credentials - Don't log passwords, tokens, or reset links

Source: SKILL.md on GitHub

2 warnings15d5 checks · Risk SAFE
  • Gen Agent Trust Hub15d

    The skill is a comprehensive security audit guide based on OWASP standards. It provides examples of vulnerable and secure code patterns for pedagogical use. The only identified risk is the inherent surface for indirect prompt injection when the agent processes untrusted user-provided code, although the skill lacks dangerous autonomous capabilities.

  • Socket15d

    No alerts

  • Snyk15d

    Risk: LOW · No issues

  • Runlayer7mo

    21/21 files flagged

  • ZeroLeaks5mo

    3 findings · Score: 69/100

Signed by skilld at 40e21b4. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Dormantupdated 8 months ago

README badge

README badge for sergiodxa/agent-skills/owasp-security-check