AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL unreviewed MIT Self-run

Security Checklist

skill-sabahattink-antigravity-fullstack-hq-security-checklist · by sabahattink

OWASP Top 10, input validation, SQL injection prevention, rate limiting, CORS. Use when reviewing code for security issues, setting up a new API, or doing a pre-deploy security audit.

No reviews yet
0 installs
6 views
0.0% view→install

Install

$ agentstack add skill-sabahattink-antigravity-fullstack-hq-security-checklist

Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.

Security review

⚠ Flagged

1 finding(s); flagged for manual review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures
  • high Dangerous shell/eval execution.

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution Used

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Reliability & compatibility

Not yet reviewed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Security Checklist? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Security Checklist

OWASP Top 10 — Quick Reference

| # | Risk | Mitigation | |---|------|-----------| | A01 | Broken Access Control | Always authorize, not just authenticate | | A02 | Cryptographic Failures | TLS everywhere, bcrypt passwords, no MD5/SHA1 | | A03 | Injection | Parameterized queries, ORM, input validation | | A04 | Insecure Design | Threat model, rate limiting, abuse cases | | A05 | Security Misconfiguration | Disable defaults, review headers | | A06 | Vulnerable Components | npm audit, pnpm audit, Dependabot | | A07 | Auth Failures | MFA, account lockout, secure sessions | | A08 | Integrity Failures | Verify build artifacts, signed commits | | A09 | Logging Failures | Log auth events, anomaly detection | | A10 | SSRF | Validate URLs, block internal IPs |

Input Validation

// ALWAYS validate at every system boundary using Zod or class-validator

// NestJS — enable globally
app.useGlobalPipes(
  new ValidationPipe({
    whitelist:            true,    // strip unknown properties
    forbidNonWhitelisted: true,    // throw on unknown props
    transform:            true,    // auto-coerce types
    transformOptions: {
      enableImplicitConversion: false,
    },
  })
)

// Zod at service boundaries
const CreateOrderSchema = z.object({
  userId:   z.string().uuid(),
  items:    z.array(z.object({
    productId: z.string().uuid(),
    quantity:  z.number().int().min(1).max(100),
  })).min(1).max(50),
  couponCode: z.string().max(20).optional(),
})

type CreateOrderInput = z.infer

// Parse — throws ZodError on invalid input
const input = CreateOrderSchema.parse(rawBody)

SQL Injection Prevention

// ALWAYS use parameterized queries / ORM — never string concatenate

// Bad — SQL injection possible
const result = await db.query(
  `SELECT * FROM users WHERE email = '${email}'`
)

// Good — TypeORM parameterized
const user = await this.repo.findOne({ where: { email } })

// Good — raw query with parameters
const users = await this.dataSource.query(
  'SELECT * FROM users WHERE email = $1 AND status = $2',
  [email, 'active']
)

// Good — QueryBuilder with parameters
const users = await this.repo
  .createQueryBuilder('user')
  .where('user.email = :email', { email })
  .andWhere('user.status = :status', { status: 'active' })
  .getMany()

XSS Prevention

// Sanitize HTML when you MUST accept user HTML (e.g., rich text editors)
// Install: npm i dompurify jsdom; npm i -D @types/dompurify

import createDOMPurify from 'dompurify'
import { JSDOM } from 'jsdom'

const { window } = new JSDOM('')
const DOMPurify  = createDOMPurify(window as unknown as Window)

const allowedTags  = ['b', 'i', 'em', 'strong', 'a', 'p', 'ul', 'ol', 'li']
const allowedAttrs = { a: ['href', 'title', 'target'] }

export function sanitizeHtml(dirty: string): string {
  return DOMPurify.sanitize(dirty, {
    ALLOWED_TAGS:  allowedTags,
    ALLOWED_ATTR:  allowedAttrs,
  })
}

// In React: NEVER use dangerouslySetInnerHTML with unsanitized content
// Good:

// Bad:

Security Headers

// main.ts — use helmet
import helmet from 'helmet'

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc:  ["'self'", "'nonce-{NONCE}'"],
      styleSrc:   ["'self'", "'unsafe-inline'"],
      imgSrc:     ["'self'", 'data:', 'https:'],
      connectSrc: ["'self'", 'https://api.example.com'],
    },
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true,
    preload: true,
  },
}))

// CORS — explicit origins only
app.enableCors({
  origin:      process.env.CORS_ORIGINS?.split(',') ?? [],
  methods:     ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'],
  credentials: true,
  maxAge:      86400,
})

Rate Limiting

// Per-endpoint limits for sensitive operations
@Controller('auth')
export class AuthController {
  // Very strict: login attempts
  @Post('login')
  @Throttle({ default: { ttl: 900_000, limit: 5 } })   // 5 per 15 min
  login() {}

  // Strict: password reset
  @Post('forgot-password')
  @Throttle({ default: { ttl: 3600_000, limit: 3 } })  // 3 per hour
  forgotPassword() {}

  // Standard: general API
  @Get('profile')
  @Throttle({ default: { ttl: 60_000, limit: 60 } })   // 60 per min
  profile() {}
}

CSRF Protection

// Use csurf for session-based apps
// For JWT-based SPAs: double-submit cookie pattern is unnecessary
// because CORS already protects — just validate the Origin header

// main.ts — validate origin on state-changing requests
app.use((req, res, next) => {
  if (['POST', 'PATCH', 'PUT', 'DELETE'].includes(req.method)) {
    const origin = req.headers.origin
    const allowed = process.env.CORS_ORIGINS?.split(',') ?? []
    if (origin && !allowed.includes(origin)) {
      return res.status(403).json({ error: 'Forbidden' })
    }
  }
  next()
})

Secrets Management

// Validate all required secrets at startup — fail fast
function validateSecrets() {
  const required = [
    'DATABASE_URL',
    'JWT_SECRET',
    'JWT_REFRESH_SECRET',
  ]

  const missing = required.filter(key => !process.env[key])
  if (missing.length > 0) {
    throw new Error(`Missing required environment variables: ${missing.join(', ')}`)
  }

  if ((process.env.JWT_SECRET?.length ?? 0)  {
    if (!ALLOWED_MIMES.has(file.mimetype)) {
      return cb(new Error(`File type ${file.mimetype} not allowed`))
    }
    cb(null, true)
  },
})

// Store files with random names — never use original filename
async function saveUpload(buffer: Buffer, originalName: string): Promise {
  const ext      = path.extname(originalName).toLowerCase()
  const safeName = `${crypto.randomUUID()}${ext}`
  // Upload to S3/R2, not to local filesystem
  return s3.upload(buffer, safeName)
}

Dependency Security

# Run on every CI build
pnpm audit --audit-level=high

# Fix automatically (carefully — may break things)
pnpm audit --fix

# Check for known vulnerabilities
npx better-npm-audit audit

# Setup Dependabot
# .github/dependabot.yml
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule: { interval: weekly }
    ignore:
      - dependency-name: "*"
        update-types: ["version-update:semver-patch"]
    open-pull-requests-limit: 10

Audit Logging

// Log all security-relevant events
@Injectable()
export class AuditService {
  private readonly logger = new Logger('AUDIT')

  logAuth(event: 'login' | 'logout' | 'login_failed' | 'token_refresh', data: {
    userId?: string
    email?: string
    ip: string
    userAgent?: string
  }) {
    this.logger.log({
      event,
      ...data,
      email: data.email ? this.maskEmail(data.email) : undefined,
      timestamp: new Date().toISOString(),
    })
  }

  private maskEmail(email: string): string {
    const [local, domain] = email.split('@')
    return `${local[0]}***@${domain}`
  }
}

Pre-Deploy Security Checklist

□ No secrets in source code (run: git log -p | grep -i "password\|secret\|api_key")
□ npm audit passes (no high/critical vulnerabilities)
□ All endpoints require authentication (check controller decorators)
□ Admin endpoints have role checks
□ Rate limiting on auth endpoints
□ CORS origins are explicit (no wildcards)
□ Helmet security headers enabled
□ Input validation with whitelist mode
□ Parameterized queries only (no string concatenation with user input)
□ File uploads validate MIME type and size
□ Error messages don't leak stack traces to client
□ Logging masks PII
□ HTTPS enforced (no HTTP in production)

Forbidden Patterns

  • Never log passwords, full tokens, or unmasked emails
  • Never use MD5 or SHA1 for password hashing — use bcrypt with cost >= 12
  • Never trust Content-Type header alone for file type validation — check magic bytes
  • Never store secrets in env vars committed to git (.env should be in .gitignore)
  • Never disable HTTPS in production
  • Never use eval() or new Function() with user input
  • Never reflect user input directly into error messages without sanitizing

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.