| name | security-practices |
| description | OWASP Top 10, authentication, and secure coding practices |
| domain | software-engineering |
| version | 1.0.0 |
| tags | ["security","owasp","authentication","authorization","encryption","xss","csrf"] |
| triggers | {"keywords":{"primary":["security","owasp","authentication","authorization","encryption","vulnerability"],"secondary":["xss","csrf","sql injection","jwt","oauth","cors","sanitize","validate"]},"context_boost":["secure","protect","attack","hack"],"context_penalty":["design","ui","ux"],"priority":"high"} |
Security Practices
Overview
Essential security practices for application development. Covers OWASP Top 10 and secure coding guidelines.
OWASP Top 10
1. Injection (SQL, NoSQL, Command)
const query = `SELECT * FROM users WHERE email = '${email}'`;
const result = await db.query(
'SELECT * FROM users WHERE email = $1',
[email]
);
const user = await prisma.user.findUnique({
where: { email }
});
exec(`ping ${userInput}`);
execFile('ping', ['-c', '4', hostname]);
2. Broken Authentication
const passwordSchema = z.string()
.min(12)
.regex(/[A-Z]/, 'Must contain uppercase')
.regex(/[a-z]/, 'Must contain lowercase')
.regex(/[0-9]/, 'Must contain number')
.regex(/[^A-Za-z0-9]/, 'Must contain special character');
import argon2 from 'argon2';
async function hashPassword(password: string): Promise<string> {
return argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 65536,
timeCost: 3,
parallelism: 4
});
}
async function verifyPassword(hash: string, password: string): Promise<boolean> {
return argon2.verify(hash, password);
}
loginLimiter = ({
: * * ,
: ,
:
});
app.(, loginLimiter, handleLogin);
3. Cross-Site Scripting (XSS)
element.innerHTML = userInput;
element.textContent = userInput;
function UserName({ name }: { name: string }) {
return <span>{name}</span>;
}
import DOMPurify from 'dompurify';
function RichContent({ html }: { html: string }) {
const sanitized = DOMPurify.sanitize(html, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p'],
ALLOWED_ATTR: ['href']
});
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
}
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',
+
+
+
);
();
});
4. Insecure Direct Object References
app.get('/api/documents/:id', async (req, res) => {
const doc = await db.documents.findById(req.params.id);
res.json(doc);
});
app.get('/api/documents/:id', auth, async (req, res) => {
const doc = await db.documents.findById(req.params.id);
if (!doc) {
return res.status(404).json({ error: 'Not found' });
}
if (doc.ownerId !== req.user.id && !req.user.isAdmin) {
return res.status(403).json({ error: 'Forbidden' });
}
res.json(doc);
});
const docId = crypto.randomUUID();
5. Cross-Site Request Forgery (CSRF)
import csrf from 'csurf';
const csrfProtection = csrf({ cookie: true });
app.get('/form', csrfProtection, (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
app.post('/submit', csrfProtection, (req, res) => {
});
<form action="/submit" method="POST">
<input type="hidden" name="_csrf" value="{{csrfToken}}" />
</form>
res.cookie('sessionId', token, {
httpOnly: true,
secure: true,
sameSite: 'strict'
});
Authentication
JWT Best Practices
import jwt from 'jsonwebtoken';
function generateAccessToken(user: User): string {
return jwt.sign(
{ sub: user.id, role: user.role },
process.env.JWT_SECRET!,
{ expiresIn: '15m' }
);
}
function generateRefreshToken(user: User): string {
const token = jwt.sign(
{ sub: user.id, type: 'refresh' },
process.env.JWT_REFRESH_SECRET!,
{ expiresIn: '7d' }
);
db.refreshTokens.create({
userId: user.id,
token: hashToken(token),
expiresAt: new Date(Date.now() + 7 * 24 * 60 * * )
});
token;
}
() {
payload = jwt.(refreshToken, process..!);
storedToken = db..({
: payload.,
: (refreshToken)
});
(!storedToken) {
();
}
user = db..(payload.);
(user);
}
OAuth 2.0 / OIDC
import { OAuth2Client } from 'google-auth-library';
const client = new OAuth2Client(
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET,
'https://myapp.com/auth/google/callback'
);
app.get('/auth/google', (req, res) => {
const url = client.generateAuthUrl({
scope: ['openid', 'email', 'profile'],
state: generateState(req.session.id)
});
res.redirect(url);
});
app.get('/auth/google/callback', async (req, res) => {
const { code, state } = req.query;
if (!verifyState(state, req.session.id)) {
return res.status(400).send('Invalid state');
}
const { tokens } = await client.getToken(code);
ticket = client.({
: tokens.,
: process..
});
payload = ticket.();
user = ({
: payload.,
: payload.,
: payload.
});
req.. = user.;
res.();
});
Authorization
Role-Based Access Control (RBAC)
const PERMISSIONS = {
admin: ['read', 'write', 'delete', 'admin'],
editor: ['read', 'write'],
viewer: ['read']
} as const;
function requirePermission(permission: string) {
return (req: Request, res: Response, next: NextFunction) => {
const userPermissions = PERMISSIONS[req.user.role] || [];
if (!userPermissions.includes(permission)) {
return res.status(403).json({ error: 'Forbidden' });
}
next();
};
}
app.delete('/api/posts/:id', auth, requirePermission('delete'), deletePost);
Attribute-Based Access Control (ABAC)
interface Policy {
effect: 'allow' | 'deny';
resource: string;
action: string;
condition?: (context: Context) => boolean;
}
const policies: Policy[] = [
{
effect: 'allow',
resource: 'document',
action: 'read',
condition: (ctx) => ctx.resource.isPublic || ctx.user.id === ctx.resource.ownerId
},
{
effect: 'allow',
resource: 'document',
action: 'write',
condition: (ctx) => ctx.user.id === ctx.resource.ownerId
},
{
effect: 'allow',
resource: '*',
action: '*',
condition: (ctx) => ctx.user. ===
}
];
(): {
context = { user, resource };
( policy policies) {
(
(policy. === || policy. === resource.) &&
(policy. === || policy. === action)
) {
(!policy. || policy.(context)) {
policy. === ;
}
}
}
;
}
Secrets Management
const apiKey = 'sk_live_1234567890';
const apiKey = process.env.API_KEY;
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
const client = new SecretManagerServiceClient();
async function getSecret(name: string): Promise<string> {
const [version] = await client.accessSecretVersion({
name: `projects/my-project/secrets/${name}/versions/latest`
});
return version.payload.data.toString();
}
Input Validation
import { z } from 'zod';
const createUserSchema = z.object({
email: z.string().email().max(255),
name: z.string().min(1).max(100).regex(/^[\w\s-]+$/),
age: z.number().int().min(0).max(150).optional()
});
app.post('/api/users', async (req, res) => {
const result = createUserSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
error: 'Validation failed',
details: result.error.flatten()
});
}
const user = await createUser(result.data);
res.json(user);
});
= * * ;
= [, , ];
() {
(file. > ) {
();
}
(!.(file.)) {
();
}
fileType = (file.);
(!fileType || !.(fileType.)) {
();
}
}
Security Headers
import helmet from 'helmet';
app.use(helmet());
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'", "https://api.example.com"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
frameAncestors: ["'none'"]
}
}));
app.use(helmet.hsts({
maxAge: 31536000,
includeSubDomains: true,
preload: true
}));
Related Skills
- [[authentication]] - Auth patterns
- [[api-design]] - API security
- [[devops-cicd]] - Security in pipelines