Agent Skills: PACT Security Patterns

|

UncategorizedID: ProfSynapse/PACT-prompt/pact-security-patterns

Install this agent skill to your local

pnpm dlx add-skill https://github.com/ProfSynapse/PACT-Plugin/tree/HEAD/pact-plugin/skills/pact-security-patterns

Skill Files

Browse the full folder contents for pact-security-patterns.

Download Skill

Loading file tree…

pact-plugin/skills/pact-security-patterns/SKILL.md

Skill Metadata

Name
pact-security-patterns
Description
|

PACT Security Patterns

Security guidance for PACT development phases. This skill provides essential security patterns and links to detailed references for comprehensive implementation.

SACROSANCT Rules (Non-Negotiable)

These rules are ABSOLUTE and must NEVER be violated.

Rule 1: Credential Protection

NEVER ALLOW in version control:

  • Actual API keys, tokens, passwords, or secrets
  • Credentials in frontend code (VITE_, REACT_APP_, NEXT_PUBLIC_ prefixes)
  • Real credential values in documentation or code examples
  • Hardcoded secrets in any file committed to git

ONLY acceptable locations for actual credentials:

| Location | Example | Security Level | |----------|---------|----------------| | .env files in .gitignore | API_KEY=sk-xxx | Development | | Server-side process.env | process.env.API_KEY | Runtime | | Deployment platform secrets | Railway, Vercel, AWS | Production | | Secrets managers | Vault, AWS Secrets Manager | Enterprise |

In Documentation - Always Use Placeholders:

# Configuration
Set your API key in `.env`:
API_KEY=your_api_key_here

Rule 2: Backend Proxy Pattern

WRONG:  Frontend --> External API (credentials in frontend)
CORRECT: Frontend --> Backend Proxy --> External API

Architecture Requirements:

  • Frontend MUST NEVER have direct access to API credentials
  • ALL API credentials MUST exist exclusively on server-side
  • Frontend calls backend endpoints (/api/resource) without credentials
  • Backend handles ALL authentication with external APIs
  • Backend validates and sanitizes ALL requests from frontend

Verification Checklist:

# Build the application
npm run build

# Search for exposed credentials in bundle
grep -r "sk-" dist/assets/*.js
grep -r "api_key" dist/assets/*.js
grep -r "VITE_" dist/assets/*.js
# All above should return NO results

Quick Security Reference

Input Validation

Always validate on the server side:

// Express.js example
const { body, validationResult } = require('express-validator');

app.post('/api/user',
  body('email').isEmail().normalizeEmail(),
  body('name').trim().escape().isLength({ min: 1, max: 100 }),
  body('age').isInt({ min: 0, max: 150 }),
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    // Process validated input
  }
);

Output Encoding

Prevent XSS by encoding output:

// React (automatic encoding)
return <div>{userInput}</div>; // Safe - React escapes

// Dangerous - avoid unless absolutely necessary
return <div dangerouslySetInnerHTML={{__html: userInput}} />; // UNSAFE

// Node.js HTML response
const escapeHtml = (str) => str
  .replace(/&/g, '&amp;')
  .replace(/</g, '&lt;')
  .replace(/>/g, '&gt;')
  .replace(/"/g, '&quot;')
  .replace(/'/g, '&#039;');

SQL Injection Prevention

Always use parameterized queries:

// WRONG - SQL Injection vulnerable
const query = `SELECT * FROM users WHERE id = ${userId}`;

// CORRECT - Parameterized query
const query = 'SELECT * FROM users WHERE id = $1';
const result = await db.query(query, [userId]);

// ORM example (Prisma)
const user = await prisma.user.findUnique({
  where: { id: userId }  // Safe - Prisma handles escaping
});

Authentication Security

Password Storage:

const bcrypt = require('bcrypt');

// Hashing password
const saltRounds = 12;  // Minimum recommended
const hashedPassword = await bcrypt.hash(password, saltRounds);

// Verifying password
const isValid = await bcrypt.compare(password, hashedPassword);

Session Configuration:

app.use(session({
  secret: process.env.SESSION_SECRET,  // Strong, random secret
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: true,       // HTTPS only
    httpOnly: true,     // No JavaScript access
    sameSite: 'strict', // CSRF protection
    maxAge: 3600000     // 1 hour
  }
}));

Security Headers

Essential HTTP headers:

const helmet = require('helmet');

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https:"],
      connectSrc: ["'self'"],
      frameSrc: ["'none'"],
      objectSrc: ["'none'"]
    }
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true
  }
}));

Rate Limiting

Protect against abuse:

const rateLimit = require('express-rate-limit');

// General API rate limit
const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100,
  message: { error: 'Too many requests, please try again later' }
});

// Stricter limit for auth endpoints
const authLimiter = rateLimit({
  windowMs: 60 * 60 * 1000, // 1 hour
  max: 5,
  message: { error: 'Too many login attempts' }
});

app.use('/api/', apiLimiter);
app.use('/api/auth/', authLimiter);

Security Checklist

Before any commit or deployment, verify:

Credential Protection

  • [ ] No credentials in staged files (git diff --staged | grep -i "key\|secret\|password")
  • [ ] .env files listed in .gitignore
  • [ ] Placeholders used in all documentation
  • [ ] No hardcoded API keys in source code

Architecture

  • [ ] Frontend makes NO direct external API calls with credentials
  • [ ] Backend proxy pattern implemented for all external integrations
  • [ ] All credentials loaded from environment variables

Input/Output

  • [ ] All user inputs validated server-side
  • [ ] SQL queries use parameterized statements
  • [ ] HTML output properly encoded
  • [ ] File uploads validated for type and size

Authentication

  • [ ] Passwords hashed with bcrypt (12+ rounds)
  • [ ] Sessions configured with secure flags
  • [ ] Authentication endpoints rate-limited
  • [ ] JWT tokens have short expiration

Headers and Transport

  • [ ] Security headers configured (use Helmet.js or equivalent)
  • [ ] HTTPS enforced in production
  • [ ] CORS configured restrictively

Detailed References

For comprehensive security guidance, see: