# Secure Code Review

> >

- **Type:** Skill
- **Install:** `agentstack add skill-unitoneai-securityskills-secure-code-review`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [UnitOneAI](https://agentstack.voostack.com/s/unitoneai)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [UnitOneAI](https://github.com/UnitOneAI)
- **Source:** https://github.com/UnitOneAI/SecuritySkills/tree/main/skills/appsec/secure-code-review
- **Website:** https://www.unitone.ai

## Install

```sh
agentstack add skill-unitoneai-securityskills-secure-code-review
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Secure Code Review

A structured, repeatable process for performing security-focused code review grounded in OWASP Application Security Verification Standard (ASVS) 4.0.3 and the CWE Top 25 Most Dangerous Software Weaknesses (2024 edition). This skill produces findings with traceable control IDs, severity ratings, and actionable remediation guidance.

---

## Step 1: Scope and Language Identification

If a target is provided via arguments, focus the review on: $ARGUMENTS

Before examining any code, establish the review boundary.

1. **Identify the languages and frameworks** present in the changeset (Python, JavaScript/TypeScript, Go, Java, etc.).
2. **Catalog the modules under review** -- list every file path and its primary responsibility (route handler, data model, utility, middleware, configuration).
3. **Determine trust boundaries** -- mark where user-controlled data enters the system (HTTP parameters, headers, file uploads, message queues, environment variables).
4. **Note dependencies** -- third-party libraries that handle security-sensitive operations (auth libraries, ORM layers, crypto packages, templating engines).
5. **Map ASVS sections to scope** -- based on what the code does, select which ASVS chapters (V1 through V14) are applicable to this review.

> **Gate:** Do not proceed until the language, trust boundaries, and applicable ASVS sections are documented. This prevents scope creep and ensures coverage.

---

## Step 2: Input Validation and Injection Review

**ASVS Reference:** V5 -- Validation, Sanitization and Encoding
**CWE Coverage:** CWE-79 (XSS), CWE-89 (SQL Injection), CWE-78 (OS Command Injection), CWE-22 (Path Traversal), CWE-77 (Command Injection), CWE-20 (Improper Input Validation)

### 2.1 Controls to Verify

| ASVS Control | Description |
|---|---|
| V5.1.1 | Input validation is applied on a trusted service layer, not solely client-side |
| V5.1.3 | All input is validated against an allowlist of permitted characters or patterns |
| V5.2.1 | All HTML form output is properly encoded to prevent reflected XSS |
| V5.2.2 | Unstructured data is sanitized to enforce safety and allowed characters |
| V5.3.1 | Output encoding is relevant for the interpreter context (HTML, JS, URL, CSS, SQL) |
| V5.3.4 | Data selection or database queries use parameterized queries or ORM |
| V5.3.7 | The application protects against LDAP injection |
| V5.3.8 | The application protects against OS command injection |
| V5.5.1 | Serialized objects use integrity checks or encryption to prevent hostile object creation |

### 2.2 Vulnerable Patterns by Language

**Python -- SQL Injection (CWE-89)**
```python
# VULNERABLE: string formatting in SQL query
def get_user(username):
    query = f"SELECT * FROM users WHERE name = '{username}'"
    cursor.execute(query)
```
Remediation: Use parameterized queries -- `cursor.execute("SELECT * FROM users WHERE name = %s", (username,))`.

**JavaScript -- Cross-site Scripting (CWE-79)**
```javascript
// VULNERABLE: inserting unsanitized user input into DOM
app.get('/search', (req, res) => {
  res.send(`Results for: ${req.query.q}`);
});
```
Remediation: Use a templating engine with auto-escaping enabled, or explicitly escape with a library such as `he` or `DOMPurify`.

**Go -- OS Command Injection (CWE-78)**
```go
// VULNERABLE: user input passed directly to shell execution
func handler(w http.ResponseWriter, r *http.Request) {
    filename := r.URL.Query().Get("file")
    cmd := exec.Command("sh", "-c", "cat "+filename)
    output, _ := cmd.Output()
    w.Write(output)
}
```
Remediation: Avoid shell invocations. Use `exec.Command("cat", filename)` with an allowlist of permitted filenames.

**Java -- Path Traversal (CWE-22)**
```java
// VULNERABLE: user-controlled path with no canonicalization
String filename = request.getParameter("file");
File f = new File("/uploads/" + filename);
FileInputStream fis = new FileInputStream(f);
```
Remediation: Canonicalize the resolved path and verify it remains within the expected base directory.

### 2.3 Review Checklist

- [ ] Every point where user input enters the system is identified.
- [ ] All SQL queries use parameterized statements or a query builder -- no string concatenation.
- [ ] HTML output is encoded contextually (HTML body, attribute, JavaScript, URL).
- [ ] OS commands, if unavoidable, use allowlisted arguments and avoid shell interpretation.
- [ ] File path operations validate and canonicalize against a base directory.
- [ ] Regular expressions used for validation are anchored (`^...$`) and tested for ReDoS.

---

## Step 3: Authentication and Session Review

**ASVS Reference:** V2 -- Authentication, V3 -- Session Management
**CWE Coverage:** CWE-287 (Improper Authentication), CWE-306 (Missing Authentication for Critical Function), CWE-798 (Use of Hard-coded Credentials)

### 3.1 Controls to Verify

| ASVS Control | Description |
|---|---|
| V2.1.1 | User-set passwords are at least 12 characters in length |
| V2.1.7 | Passwords are checked against a set of breached passwords (e.g., haveibeenpwned) |
| V2.2.1 | Anti-automation controls are effective against credential stuffing and brute-force |
| V2.5.1 | A system-generated initial activation or recovery secret is not sent in cleartext |
| V2.8.1 | Time-based OTP (TOTP) tokens have a defined validity period |
| V2.10.1 | No hard-coded credentials exist in the source code |
| V2.10.2 | No shared or default accounts are present |
| V3.1.1 | Session tokens are generated using a cryptographically secure random number generator |
| V3.2.1 | Session tokens are invalidated on user logout |
| V3.3.1 | Session idle timeout is enforced |
| V3.4.1 | Cookie-based session tokens have the Secure attribute set |
| V3.4.2 | Cookie-based session tokens have the HttpOnly attribute set |
| V3.4.3 | Cookie-based session tokens have the SameSite attribute set |

### 3.2 Vulnerable Patterns by Language

**Python -- Hard-coded Credentials (CWE-798)**
```python
# VULNERABLE: credentials embedded in source code
DB_PASSWORD = "s3cretPassw0rd!"
conn = psycopg2.connect(host="db.internal", password=DB_PASSWORD)
```
Remediation: Load credentials from environment variables or a secrets manager. Never commit secrets to version control.

**JavaScript -- Missing Authentication (CWE-306)**
```javascript
// VULNERABLE: admin endpoint with no authentication middleware
app.post('/admin/delete-user', (req, res) => {
  db.deleteUser(req.body.userId);
  res.json({ success: true });
});
```
Remediation: Apply authentication middleware to all sensitive endpoints -- `app.post('/admin/delete-user', requireAuth, requireAdmin, handler)`.

**Java -- Weak Session Management (CWE-287)**
```java
// VULNERABLE: predictable session identifier
String sessionId = "session-" + System.currentTimeMillis();
response.addCookie(new Cookie("SESSIONID", sessionId));
```
Remediation: Use the framework's built-in session management (e.g., `HttpSession`) which generates cryptographically random tokens.

### 3.3 Review Checklist

- [ ] No hard-coded passwords, API keys, or tokens anywhere in source or config files.
- [ ] All sensitive endpoints require authentication.
- [ ] Session tokens are cryptographically random, sufficiently long, and invalidated on logout.
- [ ] Session cookies set `Secure`, `HttpOnly`, and `SameSite` attributes.
- [ ] Brute-force protections (rate limiting, account lockout, CAPTCHA) are in place for login.
- [ ] Password storage uses a memory-hard hash (bcrypt, scrypt, or Argon2id).

---

## Step 4: Authorization Review

**ASVS Reference:** V4 -- Access Control
**CWE Coverage:** CWE-862 (Missing Authorization), CWE-352 (Cross-Site Request Forgery)

### 4.1 Controls to Verify

| ASVS Control | Description |
|---|---|
| V4.1.1 | Access control is enforced at a trusted service layer, not only at the UI |
| V4.1.2 | All user and data attributes used by access controls cannot be manipulated by end users |
| V4.1.3 | The principle of least privilege is applied -- users only access functions and data they need |
| V4.2.1 | Sensitive data and APIs are protected against Insecure Direct Object Reference (IDOR) attacks |
| V4.2.2 | The application enforces a strong anti-CSRF mechanism |
| V4.3.1 | Administrative interfaces use appropriate multi-factor or role-based access control |

### 4.2 Vulnerable Patterns by Language

**Python -- Missing Authorization (CWE-862)**
```python
# VULNERABLE: no ownership check -- any authenticated user can view any profile
@app.route('/api/profile/')
@login_required
def get_profile(user_id):
    return jsonify(db.get_profile(user_id))
```
Remediation: Verify `current_user.id == user_id` or that the requester holds an explicit role granting access.

**Go -- CSRF on State-Changing Operations (CWE-352)**
```go
// VULNERABLE: state-changing operation via GET with no CSRF token
http.HandleFunc("/transfer", func(w http.ResponseWriter, r *http.Request) {
    amount := r.URL.Query().Get("amount")
    to := r.URL.Query().Get("to")
    doTransfer(r.Context(), to, amount)
})
```
Remediation: Require POST with a validated CSRF token. Use a CSRF middleware library (e.g., `gorilla/csrf`).

### 4.3 Review Checklist

- [ ] Every API endpoint and data-access path enforces authorization server-side.
- [ ] Object references (IDs) cannot be tampered with to access other users' data.
- [ ] State-changing operations use anti-CSRF tokens or SameSite cookies.
- [ ] Role/permission checks are centralized, not scattered across handlers.
- [ ] Deny-by-default: all routes are denied unless explicitly permitted.

---

## Step 5: Cryptography Review

**ASVS Reference:** V6 -- Stored Cryptography
**CWE Coverage:** CWE-798 (Hard-coded Credentials -- cryptographic keys)

### 5.1 Controls to Verify

| ASVS Control | Description |
|---|---|
| V6.1.1 | Regulated private data is stored encrypted at rest |
| V6.2.1 | All cryptographic modules fail in a secure manner and errors are handled properly |
| V6.2.2 | Industry-proven or government-approved cryptographic algorithms and modes are used |
| V6.2.3 | Encryption initialization vectors, cipher configurations, and block modes are configured securely |
| V6.2.5 | Known insecure block modes (ECB), padding modes, and weak algorithms (DES, RC4) are not used |
| V6.3.1 | All random numbers and strings are generated using a cryptographically secure PRNG |
| V6.4.1 | A key management solution is in place to create, distribute, rotate, and revoke keys |

### 5.2 Vulnerable Patterns by Language

**Python -- Weak Cryptography**
```python
# VULNERABLE: using ECB mode (does not provide semantic security)
from Crypto.Cipher import AES
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(data, AES.block_size))
```
Remediation: Use AES-GCM or AES-CBC with HMAC. Prefer high-level libraries like `cryptography.fernet`.

**JavaScript -- Insecure Randomness**
```javascript
// VULNERABLE: Math.random() is not cryptographically secure
function generateToken() {
  return Math.random().toString(36).substring(2);
}
```
Remediation: Use `crypto.randomBytes(32).toString('hex')` (Node.js) or `crypto.getRandomValues()` (browser).

### 5.3 Review Checklist

- [ ] No use of deprecated algorithms: MD5, SHA-1 (for security purposes), DES, RC4, ECB mode.
- [ ] Passwords hashed with Argon2id, bcrypt, or scrypt -- never SHA-256 alone.
- [ ] All random values used for security purposes come from a CSPRNG.
- [ ] Cryptographic keys are not hard-coded -- loaded from a key management system.
- [ ] TLS certificates and configurations are not bypassed or weakened in code.

---

## Step 6: Error Handling and Logging

**ASVS Reference:** V7 -- Error Handling and Logging

### 6.1 Controls to Verify

| ASVS Control | Description |
|---|---|
| V7.1.1 | The application does not log credentials or payment details |
| V7.1.2 | The application does not log other sensitive data as defined by local privacy laws |
| V7.2.1 | All authentication decisions are logged |
| V7.2.2 | All access control decisions are logged |
| V7.3.1 | Logging mechanisms are protected from injection attacks |
| V7.4.1 | A generic error message is shown to users; detailed errors are only logged server-side |
| V7.4.3 | Error handling logic denies access by default |

### 6.2 Vulnerable Patterns by Language

**Java -- Verbose Error Disclosure**
```java
// VULNERABLE: stack trace exposed to the end user
catch (SQLException e) {
    response.getWriter().println("Error: " + e.getMessage());
    e.printStackTrace(response.getWriter());
}
```
Remediation: Log the exception server-side with a correlation ID. Return a generic message -- `"An internal error occurred. Reference: "`.

**Python -- Sensitive Data in Logs**
```python
# VULNERABLE: logging user credentials
logger.info(f"Login attempt for {username} with password {password}")
```
Remediation: Never log secrets. Log only the username and the outcome -- `logger.info(f"Login attempt for {username}: {'success' if ok else 'failure'}")`.

### 6.3 Review Checklist

- [ ] Stack traces and internal error details are never returned in HTTP responses.
- [ ] Credentials, tokens, PII, and payment data are never written to logs.
- [ ] All authentication and authorization events are logged with timestamp, user ID, and outcome.
- [ ] Log entries are structured (JSON) and resistant to log injection (newline, CRLF).
- [ ] Error handlers default to a deny / safe state.

---

## Step 7: Data Protection

**ASVS Reference:** V8 -- Data Protection

### 7.1 Controls to Verify

| ASVS Control | Description |
|---|---|
| V8.1.1 | The application protects sensitive data from being cached in server components |
| V8.2.1 | The application sets sufficient anti-caching headers for sensitive responses |
| V8.3.1 | Sensitive data is sent to the server in the HTTP message body or headers, not via URL parameters |
| V8.3.4 | Sensitive information in autocomplete fields is disabled |
| V8.3.6 | Sensitive information in memory is overwritten as soon as it is no longer needed |

### 7.2 Review Checklist

- [ ] Sensitive data (tokens, PII) is not passed in URL query strings.
- [ ] Cache-Control headers prevent caching of authenticated or sensitive responses.
- [ ] Sensitive fields in HTML forms disable autocomplete where appropriate.
- [ ] Server responses do not leak unnecessary headers (Server, X-Powered-By).
- [ ] Data classification is consistent: PII, secrets, and payment data receive elevated protections.

---

## Step 8: Deserialization and File Handling

**ASVS Reference:** V12 -- Files and Resources
**CWE Coverage:** CWE-502 (Deserialization of Untrusted Data), CWE-434 (Unrestricted Upload of File with Dangerous Type), CWE-918 (Server-Side Request Forgery)

### 8.1 Controls to Verify

| ASVS Control | Description |
|---|---|
| V12.1.1 | The application will not accept large files that could fill up storage or cause a denial of service |
| V12.1.2 | Compressed files are checked for decompression bombs |
| V12.3.1 | User-submitted filenames are validated and metadata from user uploads is not used directly by the system |
| V12.3.2 | User-submitted filenames are sanitized to prevent directory traversal |
| V12.4.1 | Files obtained from untrusted sources are stored outside the webroot |
| V12.4.2 | Files obtained from untrusted sources are scanned by antivirus or verified by content type |
| V12.6.1 | The web server only processes requests to specified and permitted file types |

### 8.2 Vulnerable Patterns by Language

**Python -- Unsafe Deserialization (CWE-502)**
```python
# VULNERABLE: deserializing untrusted data with pickle
import pickle
data = pickle.loads(request.data)
```
Remediation: Never use `pickle` on untrusted input. Use JSON or a schema-validated format. If object serialization is required, use a safe library with type restrictions.

**Java -- Unsafe Deserialization (CWE-502)**
```java
// VULNERABLE: deserializing arbitrary objects from user input
ObjectInputStream ois = new ObjectInputStream

…

## Source & license

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

- **Author:** [UnitOneAI](https://github.com/UnitOneAI)
- **Source:** [UnitOneAI/SecuritySkills](https://github.com/UnitOneAI/SecuritySkills)
- **License:** MIT
- **Homepage:** https://www.unitone.ai

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

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-unitoneai-securityskills-secure-code-review
- Seller: https://agentstack.voostack.com/s/unitoneai
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
