Security and Hardening
- Validate all external input at the system boundary (API routes, form handlers)
Category: development Source: addyosmani/agent-skillsWhat Is This
The "Security and Hardening" skill is a foundational capability for developers who build, maintain, or extend web applications. Its primary function is to minimize vulnerabilities by enforcing rigorous security practices at every interaction point where external data enters a system. This skill covers validation, authentication, secure data handling, and safe integration with third-party services. It is especially critical when developing features that accept user input, manage user sessions, store sensitive data, or interact with APIs. Security and Hardening ensures that applications are resilient against common threats such as SQL injection, cross-site scripting (XSS), credential theft, and data leakage.
Why Use It
Modern web applications are frequent targets for attacks due to their exposure and the value of user data they manage. Failing to secure the system boundaries and internal logic can result in severe breaches, financial losses, and reputational damage. By adopting the Security and Hardening skill, developers:
- Reduce risk of exploitation through user input, APIs, or third-party integrations
- Comply with industry standards and regulations (such as GDPR or PCI DSS)
- Build user trust by preventing unauthorized data access or leaks
- Ensure long-term maintainability by embedding security into the development lifecycle
Security is not a one-time consideration. It must be a continuous, integral aspect of every feature and interaction in the application.
How to Use It
Security and Hardening is best understood as a set of strict, actionable rules applied at the boundaries and critical paths of the application. Below are the essential practices, along with code examples:
1. Validate All External Input
All data entering the application from users, APIs, webhooks, or other external sources must be validated. This includes query parameters, form fields, and request bodies.
Example (Express.js API route validation using joi):
const Joi = require('joi');
const userSchema = Joi.object({
email: Joi.string().email().required(),
password: Joi.string().min(8).required()
});
app.post('/register', (req, res) => {
const { error } = userSchema.validate(req.body);
if (error) {
return res.status(400).send('Invalid input');
}
// Proceed with registration logic
});
2. Parameterize All Database Queries
Never insert user input directly into SQL queries. Always use parameterized statements or ORM query builders to prevent SQL injection.
Example (Node.js with PostgreSQL):
const text = 'SELECT * FROM users WHERE email = $1';
const values = [userInput.email];
const result = await db.query(text, values);
3. Encode Output (Prevent XSS)
Always encode data before rendering it in HTML to prevent execution of malicious scripts.
Example (React - auto-escapes by default):
<div>{userInput.comment}</div>
Avoid using dangerouslySetInnerHTML unless absolutely necessary and safe.
4. Use HTTPS for All Communication
All external communication, including APIs and resource loading, must use HTTPS to prevent interception and tampering.
Example (Express.js redirect to HTTPS):
app.use((req, res, next) => {
if (req.protocol !== 'https') {
return res.redirect('https://' + req.headers.host + req.url);
}
next();
});
5. Hash Passwords Securely
Passwords must never be stored in plaintext. Use strong, adaptive hashing algorithms like bcrypt, scrypt, or argon2.
Example (bcrypt):
const bcrypt = require('bcrypt');
const hashed = await bcrypt.hash(plainPassword, 12);
// Store 'hashed' in database
6. Set Security Headers
Set HTTP security headers such as Content Security Policy (CSP), HTTP Strict Transport Security (HSTS), and X-Frame-Options.
Example (Helmet middleware for Express.js):
const helmet = require('helmet');
app.use(helmet());
7. Secure Session Cookies
Set cookies with httpOnly, secure, and sameSite flags to prevent theft via JavaScript or cross-site request forgery.
Example:
res.cookie('sessionId', sessionId, {
httpOnly: true,
secure: true,
sameSite: 'Strict'
});
8. Run Security Audits
Regularly scan dependencies for vulnerabilities using tools like npm audit.
npm audit
When to Use It
Apply Security and Hardening practices whenever you:
- Accept or process user input (forms, query parameters, uploads)
- Implement authentication or authorization
- Store or transmit sensitive or personal data
- Integrate with external APIs, payment gateways, or webhooks
- Add features that handle PII, financial data, or business-critical information
In short, any time untrusted data or critical functionality is involved, these practices are mandatory.
Important Notes
- Security and Hardening is not optional. All input must be treated as untrusted until proven otherwise.
- Do not bypass framework security features such as output encoding or CSRF protection.
- Regularly review and update dependencies to avoid known vulnerabilities.
- Security is a shared responsibility across the development team-enforce code reviews and automated testing for security.
- Document any exceptions or custom logic that deviates from standard practices, and justify them with risk assessments.
By integrating these techniques as standard operating procedures, you significantly reduce the attack surface of your application, protect your users, and build more robust, trustworthy systems.