Security Baseline Skill
When to use this skill
Use this skill when a task touches any security-relevant behavior:
- API endpoints, controllers, route handlers, middleware, guards, or request parsing
- authentication, authorization, roles, permissions, tenant or organization boundaries
- secrets, environment variables, API keys, tokens, sessions, cookies, or client/server config
- input validation, parsing, sanitization, file upload, webhooks, or third-party payloads
- database queries, raw SQL, user-provided URLs, network calls, SSRF-sensitive features
- logging, observability, error responses, PII handling, audit events, or external error tracking
- dependency changes, generated code, AI-generated code, scripts, CI checks, or pre-commit hooks
- AI application features such as tool calls, RAG, memory, model output parsing, or guardrails
This skill is a baseline. If a project has stricter domain, legal, compliance, customer, or regulatory requirements, follow the stricter rule.
Goal
Make every TypeScript project secure by default without forcing unnecessary enterprise complexity into small projects. Security must be part of code design, not a last-minute review layer.
Core principle:
secure by default, explicit by exception, fail closed, never trust external input
Baseline rules
- Treat all external input as untrusted.
- Validate external input at system boundaries with Zod or an approved runtime validation layer.
- Authenticate centrally through guards, middleware, or provider adapters.
- Authorize server-side in use-cases, policies, or application services.
- Do not treat client-side permission checks as security controls.
- Enforce tenant and organization boundaries in data access and use-case logic.
- Keep secrets out of source code, logs, client bundles, examples, screenshots, and test fixtures.
- Read
process.env only inside config/environment modules.
- Do not expose stack traces, raw database errors, provider errors, or internal exception details to clients.
- Do not log raw request bodies, raw provider responses, tokens, passwords, cookies, authorization headers, API keys, or sensitive personal data.
- Do not build SQL, shell commands, HTML, JSON queries, or URLs with unsafe untrusted string concatenation.
- Require explicit review and written justification for raw SQL.
- Use allowlists for production CORS, external URL fetching, file types, webhook providers, and privileged operations.
- Add tests for security-sensitive behavior.
- Treat AI-generated code as untrusted until manually reviewed, tested, and security-checked.
Security coding workflow
When implementing or modifying code:
- Identify all external inputs.
- Validate body, query, path params, headers, cookies, webhooks, file metadata, third-party responses, and AI output at the boundary.
- Identify whether the operation is public, authenticated, authorized, tenant-scoped, destructive, expensive, or side-effect-producing.
- Add authentication and authorization checks before business-sensitive actions.
- Enforce tenant boundaries in repository/query methods, not only in the UI.
- Decide whether rate limiting, idempotency, webhook signature verification, or audit logging is required.
- Ensure secrets and sensitive data cannot be logged, returned, stored unsafely, or exposed to the client.
- Add or update tests for the security boundary.
- Update docs, OpenAPI, env examples, or ADRs when behavior or architecture changes.
External input rules
External input includes:
- HTTP request body, query params, path params, headers, cookies, and form data
- browser storage, uploaded files, and user-provided filenames
- webhooks and signed provider events
- third-party API responses and SDK responses
- database records when crossing trust boundaries
- AI model output, tool-call arguments, memory, RAG documents, and structured model responses
- environment variables and runtime configuration
Rules:
- Public API input schemas use strict object validation by default.
- Unknown fields are rejected unless a documented protocol requires passthrough.
- Query, path, and env values may use controlled coercion.
- JSON request bodies should not silently coerce types by default.
- Zod errors are normalized into the standard API error envelope; raw validation errors are not returned directly.
Authentication rules
- Authentication must be centralized in guards, middleware, or provider adapters.
- Use a normalized
AuthContext; do not pass raw tokens, raw cookies, or provider-specific session objects into use-cases.
- Provider SDKs such as Supabase Auth, Auth.js, Firebase Auth, or custom JWT libraries stay behind adapters.
- Missing or invalid authentication returns
401.
- API keys must be hashed at rest and shown only once when created.
- Raw API keys, tokens, session IDs, refresh tokens, and cookies must never be logged.
Example shape:
export type AuthContext = {
userId: string;
organizationId?: string;
roles: string[];
permissions: string[];
authType: "session" | "bearer-token" | "api-key";
};
Authorization rules
Authentication answers “who is this?” Authorization answers “can they do this?” Keep them separate.
- Enforce authorization server-side.
- Prefer permission-based authorization for business behavior.
- Permission format:
resource:action.
- Roles may map to permissions, but business logic should check permissions or policies.
- Use-case/application layer must enforce authorization before sensitive mutations or reads.
- Return
403 when the actor is authenticated but lacks permission.
- Return
404 for cross-tenant or enumeration-sensitive resource access when hiding existence is safer.
Example:
await PERMISSIONS.require(authContext, "project:update", {
organizationId: project.organizationId,
});
Tenant and organization boundary rules
- Tenant-scoped data must include
organizationId or tenantId in the access path.
- Avoid generic
findById for tenant-scoped resources.
- Prefer methods such as
findByIdForOrganization(id, organizationId).
- Cross-tenant access must not reveal resource existence unless explicitly intended.
- Add tests proving users cannot read, update, delete, or infer resources from another organization.
Bad:
const project = await PROJECT_REPOSITORY.findById(projectId);
Good:
const project = await PROJECT_REPOSITORY.findByIdForOrganization(
projectId,
authContext.organizationId,
);
Secret and config rules
- Any value ending in or containing
SECRET, TOKEN, KEY, PASSWORD, or PRIVATE is sensitive by default.
process.env is allowed only inside config/environment modules.
- Server env and client env must be separated.
- Service role keys are server-only.
- Public client keys must still rely on server-side checks or provider security rules.
.env.example documents required variables but contains no real secret.
- Secret leaks require rotation; removing the commit is not enough.
Bad:
const apiKey = process.env.OPENAI_API_KEY;
Good:
const openAiAdapter = new OpenAiAdapter(OPENAI_CONFIG.API_KEY);
HTTP security headers
Enable secure defaults for backend APIs and web apps.
Minimum considerations:
X-Content-Type-Options: nosniff
Referrer-Policy
X-Frame-Options or CSP frame-ancestors
Content-Security-Policy for web/frontends when applicable
Strict-Transport-Security in production HTTPS environments
API-only services may not need a full CSP, but browser-facing apps should define one intentionally.
CORS rules
- Production CORS must be allowlist-based.
- Do not use
origin: "*" with credentials: true.
- Localhost origins may be allowed in development.
- CORS origins should be parsed from typed config, not hardcoded throughout the app.
- CORS is not authentication or authorization.
Bad:
origin: "*",
credentials: true,
Good:
origin: HTTP_CONFIG.CORS_ORIGINS,
credentials: true,
Rate limiting rules
Rate limiting must be available for public, auth-sensitive, and expensive endpoints.
Apply or consider it for:
- login, signup, OTP send/verify, password reset
- AI generation, file processing, search, scraping, import/export
- public APIs and unauthenticated endpoints
- webhook endpoints when provider behavior and retry patterns allow it
Return 429 Too Many Requests with the standard error envelope. Include Retry-After where useful.
Injection prevention rules
Never build executable or interpreted strings with untrusted input.
- SQL: use ORM/query builder parameters or parameterized SQL.
- Shell: use
spawn/argument arrays; never concatenate user input into shell strings.
- HTML: avoid unsafe HTML injection; review
dangerouslySetInnerHTML explicitly.
- NoSQL/query objects: do not pass raw client objects as query operators.
- URLs: validate and allowlist before fetching or redirecting.
Bad SQL:
const query = `SELECT * FROM users WHERE email = '${email}'`;
Good SQL:
const rows = await db.execute(sql`
SELECT * FROM users
WHERE email = ${email}
`);
Raw SQL review gate
Raw SQL is allowed only with written justification and explicit review.
Every raw SQL block must explain:
- why ORM/query builder is insufficient
- how user input is parameterized
- how tenant/organization filtering is enforced
- whether transaction boundaries are required
- expected indexes/performance impact
- what tests cover behavior and security filters
Use this comment pattern:
/**
* Raw SQL justification:
* - Reason: The query builder cannot express this recursive CTE clearly.
* - Safety: All user inputs are parameterized.
* - Tenant boundary: organization_id is included in WHERE clauses.
* - Review: Requires persistence/security review.
*/
SSRF and user-provided URL rules
User-provided URLs must not be fetched without a guard.
Before fetching user-controlled URLs:
- allow only required protocols, usually
https:
- block localhost, loopback, private, link-local, and metadata IP ranges
- validate after DNS resolution when possible
- validate every redirect target
- set timeouts and max response size
- use an allowlist when the target domain set is known
- do not forward internal credentials or cookies
Risky features include URL import, image fetchers, PDF downloaders, webhook testers, OG preview, proxy endpoints, and crawl jobs.
File upload rules
File uploads are untrusted.
Minimum controls:
- max file size
- allowed MIME types and extensions
- server-generated file names
- path traversal prevention
- private/public storage decision
- optional malware scanning for higher-risk projects
- metadata validation before processing
Bad:
const path = `/uploads/${originalFileName}`;
Good:
const path = `/uploads/${randomUUID()}.pdf`;
Webhook security rules
Webhook payloads must be verified before processing.
Required controls:
- signature verification
- raw body handling when provider requires it
- timestamp tolerance where supported
- replay protection
- idempotency using provider event ID
- safe failure responses that do not reveal secrets
Do not parse, store, or act on webhook payloads before signature verification.
Error handling security rules
- Client error responses use the standard error envelope.
- Do not return stack traces, SQL errors, provider raw errors, SDK internals, or secret-related details.
- Normalize internal failures to safe error codes and messages.
- Log detailed debug context only after redaction/allowlisting.
- For enumeration-sensitive resources, prefer
404 over 403 when appropriate.
Logging and PII rules
Log by allowlist, not by dumping objects.
Never log:
- passwords, tokens, API keys, private keys, secrets
- authorization headers, cookies, session IDs, refresh tokens
- raw request bodies, raw provider responses, full webhook payloads
- payment data or card data
- sensitive personal data unless explicitly approved and masked
Potential PII includes email, phone, address, national ID, IP address, location, VIN, and customer identifiers. Mask, hash, or omit unless the log has a documented need.
Dependency and supply-chain rules
- Keep lockfiles committed.
- Audit dependency changes.
- Avoid adding dependencies for trivial utilities.
- Review new runtime dependencies for maintenance, security, license, and transitive risk.
- Run dependency audit in CI according to the CI/CD skill.
- Document accepted high/critical vulnerability exceptions with owner, mitigation, and review date.
AI-generated code security rules
Treat AI-generated code as untrusted until reviewed.
Checklist:
- no hardcoded secrets
- no auth bypass
- no raw SQL without justification
- no unsafe
eval, new Function, or shell execution with user input
- no unvalidated model output or tool-call arguments
- no destructive tool calls without explicit authorization and human review when required
- tests added or updated for security-sensitive behavior
AI application security profile
When the project includes LLM or agent features, also check:
- prompt injection mitigation
- tool permission checks
- model output validation with Zod or equivalent
- PII masking before model calls when required
- retrieval source filtering
- cost/rate limits
- audit trail for tool calls
- human-in-the-loop for destructive or irreversible actions
- no blind trust in memory, retrieved documents, or model-generated JSON
Required tests
Add or update tests when the feature includes:
- authentication or authorization
- tenant boundary or object-level access control
- webhook verification
- rate limiting
- file upload validation
- SSRF-sensitive URL fetching
- raw SQL or custom query logic
- sensitive error handling
- AI output/tool-call validation
- CORS/security header behavior where applicable
Minimum examples:
- unauthenticated request returns
401
- missing permission returns
403
- cross-tenant resource access returns
404 or the project’s chosen safe response
- unknown input fields are rejected
- invalid webhook signatures are rejected
- raw stack trace is not exposed to client
- sensitive values are not included in log context
AI coding checklist
Before writing code:
- What external inputs does this feature accept?
- Does it require authentication?
- Does it require permission or policy checks?
- Is the resource tenant-scoped?
- Does it perform a side effect or destructive action?
- Does it call an external provider or fetch user-provided URLs?
- Does it store, transmit, log, or expose sensitive data?
- Does it need rate limiting, idempotency, audit logging, or webhook verification?
While writing code:
- Validate input at the boundary.
- Keep controllers/routes thin.
- Keep security decisions server-side.
- Use typed config instead of
process.env.
- Use serializers for API responses.
- Use repositories/adapters for persistence and external systems.
- Add tests for the security boundary.
AI review checklist
Reject or request changes if:
- authorization exists only in UI/client code
- raw token/session/provider object reaches use-case logic
- tenant-scoped query lacks
organizationId or tenantId
- raw SQL lacks written justification or parameterization
- CORS uses wildcard with credentials
- secrets or PII are logged or returned
- client receives stack traces or raw provider/DB errors
- webhook payload is processed before signature verification
- user-provided URL is fetched without SSRF guard
- file uploads trust original filenames or lack size/type checks
- AI output is used without validation
- tests are missing for a security-sensitive change
Common anti-patterns
if (user.role === "admin") scattered across controllers instead of centralized policy/permission checks
findById(id) for tenant-scoped resources
console.log(request.body) or LOGGER.info({ body })
Boolean(process.env.FEATURE_ENABLED) for boolean env parsing
origin: "*" with cookies or credentials
- raw SQL with string interpolation
- webhook handlers that parse and process before verifying signatures
- client-side-only authorization
- service role keys exposed to frontend code
- storing API keys in plaintext
- treating LLM output as trusted JSON
Output expectations
When this skill is applied, the agent should produce or review code that:
- is secure by default
- validates external input
- enforces server-side authorization
- preserves tenant boundaries
- avoids secret/PII leakage
- avoids unsafe injection/SSRF/file/webhook patterns
- includes tests for security-sensitive behavior
- documents exceptions such as raw SQL, destructive migrations, or accepted dependency risks
1---2name: security-baseline3description: Enforce the project's secure-by-default TypeScript/Node.js security baseline. Use when creating or reviewing authentication, authorization, API endpoints, input handling, CORS, rate limits, secrets, logging, webhooks, file uploads, SSRF-sensitive URL fetching, dependency/security checks, or AI-generated code.4license: Proprietary5---67# Security Baseline Skill89## When to use this skill1011Use this skill when a task touches any security-relevant behavior:1213- API endpoints, controllers, route handlers, middleware, guards, or request parsing14- authentication, authorization, roles, permissions, tenant or organization boundaries15- secrets, environment variables, API keys, tokens, sessions, cookies, or client/server config16- input validation, parsing, sanitization, file upload, webhooks, or third-party payloads17- database queries, raw SQL, user-provided URLs, network calls, SSRF-sensitive features18- logging, observability, error responses, PII handling, audit events, or external error tracking19- dependency changes, generated code, AI-generated code, scripts, CI checks, or pre-commit hooks20- AI application features such as tool calls, RAG, memory, model output parsing, or guardrails2122This skill is a baseline. If a project has stricter domain, legal, compliance, customer, or regulatory requirements, follow the stricter rule.2324## Goal2526Make every TypeScript project secure by default without forcing unnecessary enterprise complexity into small projects. Security must be part of code design, not a last-minute review layer.2728Core principle:2930```txt31secure by default, explicit by exception, fail closed, never trust external input32```3334## Baseline rules3536- Treat all external input as untrusted.37- Validate external input at system boundaries with Zod or an approved runtime validation layer.38- Authenticate centrally through guards, middleware, or provider adapters.39- Authorize server-side in use-cases, policies, or application services.40- Do not treat client-side permission checks as security controls.41- Enforce tenant and organization boundaries in data access and use-case logic.42- Keep secrets out of source code, logs, client bundles, examples, screenshots, and test fixtures.43- Read `process.env` only inside config/environment modules.44- Do not expose stack traces, raw database errors, provider errors, or internal exception details to clients.45- Do not log raw request bodies, raw provider responses, tokens, passwords, cookies, authorization headers, API keys, or sensitive personal data.46- Do not build SQL, shell commands, HTML, JSON queries, or URLs with unsafe untrusted string concatenation.47- Require explicit review and written justification for raw SQL.48- Use allowlists for production CORS, external URL fetching, file types, webhook providers, and privileged operations.49- Add tests for security-sensitive behavior.50- Treat AI-generated code as untrusted until manually reviewed, tested, and security-checked.5152## Security coding workflow5354When implementing or modifying code:55561. Identify all external inputs.572. Validate body, query, path params, headers, cookies, webhooks, file metadata, third-party responses, and AI output at the boundary.583. Identify whether the operation is public, authenticated, authorized, tenant-scoped, destructive, expensive, or side-effect-producing.594. Add authentication and authorization checks before business-sensitive actions.605. Enforce tenant boundaries in repository/query methods, not only in the UI.616. Decide whether rate limiting, idempotency, webhook signature verification, or audit logging is required.627. Ensure secrets and sensitive data cannot be logged, returned, stored unsafely, or exposed to the client.638. Add or update tests for the security boundary.649. Update docs, OpenAPI, env examples, or ADRs when behavior or architecture changes.6566## External input rules6768External input includes:6970- HTTP request body, query params, path params, headers, cookies, and form data71- browser storage, uploaded files, and user-provided filenames72- webhooks and signed provider events73- third-party API responses and SDK responses74- database records when crossing trust boundaries75- AI model output, tool-call arguments, memory, RAG documents, and structured model responses76- environment variables and runtime configuration7778Rules:7980- Public API input schemas use strict object validation by default.81- Unknown fields are rejected unless a documented protocol requires passthrough.82- Query, path, and env values may use controlled coercion.83- JSON request bodies should not silently coerce types by default.84- Zod errors are normalized into the standard API error envelope; raw validation errors are not returned directly.8586## Authentication rules8788- Authentication must be centralized in guards, middleware, or provider adapters.89- Use a normalized `AuthContext`; do not pass raw tokens, raw cookies, or provider-specific session objects into use-cases.90- Provider SDKs such as Supabase Auth, Auth.js, Firebase Auth, or custom JWT libraries stay behind adapters.91- Missing or invalid authentication returns `401`.92- API keys must be hashed at rest and shown only once when created.93- Raw API keys, tokens, session IDs, refresh tokens, and cookies must never be logged.9495Example shape:9697```ts98export type AuthContext = {99 userId: string;100 organizationId?: string;101 roles: string[];102 permissions: string[];103 authType: "session" | "bearer-token" | "api-key";104};105```106107## Authorization rules108109Authentication answers “who is this?” Authorization answers “can they do this?” Keep them separate.110111- Enforce authorization server-side.112- Prefer permission-based authorization for business behavior.113- Permission format: `resource:action`.114- Roles may map to permissions, but business logic should check permissions or policies.115- Use-case/application layer must enforce authorization before sensitive mutations or reads.116- Return `403` when the actor is authenticated but lacks permission.117- Return `404` for cross-tenant or enumeration-sensitive resource access when hiding existence is safer.118119Example:120121```ts122await PERMISSIONS.require(authContext, "project:update", {123 organizationId: project.organizationId,124});125```126127## Tenant and organization boundary rules128129- Tenant-scoped data must include `organizationId` or `tenantId` in the access path.130- Avoid generic `findById` for tenant-scoped resources.131- Prefer methods such as `findByIdForOrganization(id, organizationId)`.132- Cross-tenant access must not reveal resource existence unless explicitly intended.133- Add tests proving users cannot read, update, delete, or infer resources from another organization.134135Bad:136137```ts138const project = await PROJECT_REPOSITORY.findById(projectId);139```140141Good:142143```ts144const project = await PROJECT_REPOSITORY.findByIdForOrganization(145 projectId,146 authContext.organizationId,147);148```149150## Secret and config rules151152- Any value ending in or containing `SECRET`, `TOKEN`, `KEY`, `PASSWORD`, or `PRIVATE` is sensitive by default.153- `process.env` is allowed only inside config/environment modules.154- Server env and client env must be separated.155- Service role keys are server-only.156- Public client keys must still rely on server-side checks or provider security rules.157- `.env.example` documents required variables but contains no real secret.158- Secret leaks require rotation; removing the commit is not enough.159160Bad:161162```ts163const apiKey = process.env.OPENAI_API_KEY;164```165166Good:167168```ts169const openAiAdapter = new OpenAiAdapter(OPENAI_CONFIG.API_KEY);170```171172## HTTP security headers173174Enable secure defaults for backend APIs and web apps.175176Minimum considerations:177178- `X-Content-Type-Options: nosniff`179- `Referrer-Policy`180- `X-Frame-Options` or CSP `frame-ancestors`181- `Content-Security-Policy` for web/frontends when applicable182- `Strict-Transport-Security` in production HTTPS environments183184API-only services may not need a full CSP, but browser-facing apps should define one intentionally.185186## CORS rules187188- Production CORS must be allowlist-based.189- Do not use `origin: "*"` with `credentials: true`.190- Localhost origins may be allowed in development.191- CORS origins should be parsed from typed config, not hardcoded throughout the app.192- CORS is not authentication or authorization.193194Bad:195196```ts197origin: "*",198credentials: true,199```200201Good:202203```ts204origin: HTTP_CONFIG.CORS_ORIGINS,205credentials: true,206```207208## Rate limiting rules209210Rate limiting must be available for public, auth-sensitive, and expensive endpoints.211212Apply or consider it for:213214- login, signup, OTP send/verify, password reset215- AI generation, file processing, search, scraping, import/export216- public APIs and unauthenticated endpoints217- webhook endpoints when provider behavior and retry patterns allow it218219Return `429 Too Many Requests` with the standard error envelope. Include `Retry-After` where useful.220221## Injection prevention rules222223Never build executable or interpreted strings with untrusted input.224225- SQL: use ORM/query builder parameters or parameterized SQL.226- Shell: use `spawn`/argument arrays; never concatenate user input into shell strings.227- HTML: avoid unsafe HTML injection; review `dangerouslySetInnerHTML` explicitly.228- NoSQL/query objects: do not pass raw client objects as query operators.229- URLs: validate and allowlist before fetching or redirecting.230231Bad SQL:232233```ts234const query = `SELECT * FROM users WHERE email = '${email}'`;235```236237Good SQL:238239```ts240const rows = await db.execute(sql`241 SELECT * FROM users242 WHERE email = ${email}243`);244```245246## Raw SQL review gate247248Raw SQL is allowed only with written justification and explicit review.249250Every raw SQL block must explain:251252- why ORM/query builder is insufficient253- how user input is parameterized254- how tenant/organization filtering is enforced255- whether transaction boundaries are required256- expected indexes/performance impact257- what tests cover behavior and security filters258259Use this comment pattern:260261```ts262/**263 * Raw SQL justification:264 * - Reason: The query builder cannot express this recursive CTE clearly.265 * - Safety: All user inputs are parameterized.266 * - Tenant boundary: organization_id is included in WHERE clauses.267 * - Review: Requires persistence/security review.268 */269```270271## SSRF and user-provided URL rules272273User-provided URLs must not be fetched without a guard.274275Before fetching user-controlled URLs:276277- allow only required protocols, usually `https:`278- block localhost, loopback, private, link-local, and metadata IP ranges279- validate after DNS resolution when possible280- validate every redirect target281- set timeouts and max response size282- use an allowlist when the target domain set is known283- do not forward internal credentials or cookies284285Risky features include URL import, image fetchers, PDF downloaders, webhook testers, OG preview, proxy endpoints, and crawl jobs.286287## File upload rules288289File uploads are untrusted.290291Minimum controls:292293- max file size294- allowed MIME types and extensions295- server-generated file names296- path traversal prevention297- private/public storage decision298- optional malware scanning for higher-risk projects299- metadata validation before processing300301Bad:302303```ts304const path = `/uploads/${originalFileName}`;305```306307Good:308309```ts310const path = `/uploads/${randomUUID()}.pdf`;311```312313## Webhook security rules314315Webhook payloads must be verified before processing.316317Required controls:318319- signature verification320- raw body handling when provider requires it321- timestamp tolerance where supported322- replay protection323- idempotency using provider event ID324- safe failure responses that do not reveal secrets325326Do not parse, store, or act on webhook payloads before signature verification.327328## Error handling security rules329330- Client error responses use the standard error envelope.331- Do not return stack traces, SQL errors, provider raw errors, SDK internals, or secret-related details.332- Normalize internal failures to safe error codes and messages.333- Log detailed debug context only after redaction/allowlisting.334- For enumeration-sensitive resources, prefer `404` over `403` when appropriate.335336## Logging and PII rules337338Log by allowlist, not by dumping objects.339340Never log:341342- passwords, tokens, API keys, private keys, secrets343- authorization headers, cookies, session IDs, refresh tokens344- raw request bodies, raw provider responses, full webhook payloads345- payment data or card data346- sensitive personal data unless explicitly approved and masked347348Potential PII includes email, phone, address, national ID, IP address, location, VIN, and customer identifiers. Mask, hash, or omit unless the log has a documented need.349350## Dependency and supply-chain rules351352- Keep lockfiles committed.353- Audit dependency changes.354- Avoid adding dependencies for trivial utilities.355- Review new runtime dependencies for maintenance, security, license, and transitive risk.356- Run dependency audit in CI according to the CI/CD skill.357- Document accepted high/critical vulnerability exceptions with owner, mitigation, and review date.358359## AI-generated code security rules360361Treat AI-generated code as untrusted until reviewed.362363Checklist:364365- no hardcoded secrets366- no auth bypass367- no raw SQL without justification368- no unsafe `eval`, `new Function`, or shell execution with user input369- no unvalidated model output or tool-call arguments370- no destructive tool calls without explicit authorization and human review when required371- tests added or updated for security-sensitive behavior372373## AI application security profile374375When the project includes LLM or agent features, also check:376377- prompt injection mitigation378- tool permission checks379- model output validation with Zod or equivalent380- PII masking before model calls when required381- retrieval source filtering382- cost/rate limits383- audit trail for tool calls384- human-in-the-loop for destructive or irreversible actions385- no blind trust in memory, retrieved documents, or model-generated JSON386387## Required tests388389Add or update tests when the feature includes:390391- authentication or authorization392- tenant boundary or object-level access control393- webhook verification394- rate limiting395- file upload validation396- SSRF-sensitive URL fetching397- raw SQL or custom query logic398- sensitive error handling399- AI output/tool-call validation400- CORS/security header behavior where applicable401402Minimum examples:403404- unauthenticated request returns `401`405- missing permission returns `403`406- cross-tenant resource access returns `404` or the project’s chosen safe response407- unknown input fields are rejected408- invalid webhook signatures are rejected409- raw stack trace is not exposed to client410- sensitive values are not included in log context411412## AI coding checklist413414Before writing code:415416- What external inputs does this feature accept?417- Does it require authentication?418- Does it require permission or policy checks?419- Is the resource tenant-scoped?420- Does it perform a side effect or destructive action?421- Does it call an external provider or fetch user-provided URLs?422- Does it store, transmit, log, or expose sensitive data?423- Does it need rate limiting, idempotency, audit logging, or webhook verification?424425While writing code:426427- Validate input at the boundary.428- Keep controllers/routes thin.429- Keep security decisions server-side.430- Use typed config instead of `process.env`.431- Use serializers for API responses.432- Use repositories/adapters for persistence and external systems.433- Add tests for the security boundary.434435## AI review checklist436437Reject or request changes if:438439- authorization exists only in UI/client code440- raw token/session/provider object reaches use-case logic441- tenant-scoped query lacks `organizationId` or `tenantId`442- raw SQL lacks written justification or parameterization443- CORS uses wildcard with credentials444- secrets or PII are logged or returned445- client receives stack traces or raw provider/DB errors446- webhook payload is processed before signature verification447- user-provided URL is fetched without SSRF guard448- file uploads trust original filenames or lack size/type checks449- AI output is used without validation450- tests are missing for a security-sensitive change451452## Common anti-patterns453454- `if (user.role === "admin")` scattered across controllers instead of centralized policy/permission checks455- `findById(id)` for tenant-scoped resources456- `console.log(request.body)` or `LOGGER.info({ body })`457- `Boolean(process.env.FEATURE_ENABLED)` for boolean env parsing458- `origin: "*"` with cookies or credentials459- raw SQL with string interpolation460- webhook handlers that parse and process before verifying signatures461- client-side-only authorization462- service role keys exposed to frontend code463- storing API keys in plaintext464- treating LLM output as trusted JSON465466## Output expectations467468When this skill is applied, the agent should produce or review code that:469470- is secure by default471- validates external input472- enforces server-side authorization473- preserves tenant boundaries474- avoids secret/PII leakage475- avoids unsafe injection/SSRF/file/webhook patterns476- includes tests for security-sensitive behavior477- documents exceptions such as raw SQL, destructive migrations, or accepted dependency risks