SuperAPI AI Directory

verify-quality-security

Security & auditing

View repository

Updated 10-16 09:30

About this skill

Security — security hardening

Entry/Exit

  • Entry: involves user input, authentication and authorization, sensitive data, or /review and /ship before
  • Exit: hardened code + security review passed
  • Points to: after security issues are fixed, re-enter /review
  • Preload: CANON.md
  • Output path: security review conclusion → verify-workflow-review (merged into the review report) or build-workflow-execute (when security issues need to be sent back for fixing)

When not to use

  • The change does not touch input, permissions, sensitive data, network boundaries, or deployment configuration at all
  • Only explaining security concepts, not reviewing or modifying a specific implementation
  • The current output is purely visual/copy, and there is no external data or permission boundary

Iron Law

Three-level boundary system

Level Rule Example
Always Do Validate input before submission, parameterized queries, hashed passwords, HTTPS only cookies Input sanitization, bcrypt, helmet
Ask First Leaking user data, changing the permission model, introducing authentication dependencies, encryption algorithm selection New OAuth provider, encryption library selection
Never Do Committing secrets, trusting client-side validation,eval() user input, innerHTML with user data, exposing stack traces to users .env in the repository,dangerouslySetInnerHTML

OWASP Top 10 defenses

1. Injection (SQL/NoSQL/Command)

// Bad: SQL 拼接
const task = await db.query(`SELECT * FROM tasks WHERE id = '${req.params.id}'`);

// Good: 参数化查询
const task = await db.tasks.findById(req.params.id);

// 命令行参数必须通过 exec/spawn 的参数数组,不拼接字符串

2. Cross-site scripting (XSS)

// Bad: 直接插入用户内容
<div>{user.bio}</div>  // 如果 bio 包含 <script>...

// Good: 框架自动转义 + DOMPurify for rich text
<div>{user.bio}</div>  // React 默认转义
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(richBio) }} />

3. Sensitive data exposure

// Bad: 错误暴露内部信息
catch (err) {
  res.status(500).json({ error: err.message, stack: err.stack });
}

// Good: 用户可见错误不含内部信息
catch (err) {
  logger.error('Task creation failed', { taskId, error: err.message });
  res.status(500).json({ error: { code: 'INTERNAL_ERROR', message: '处理请求时发生错误' } });
}

4. Broken access control

// Bad: 任何登录用户都能删任何任务
app.delete('/tasks/:id', auth, async (req, res) => {
  await db.tasks.delete(req.params.id);
});

// Good: 验证所有权
app.delete('/tasks/:id', auth, async (req, res) => {
  const task = await db.tasks.findById(req.params.id);
  if (!task) return res.status(404).end();
  if (task.ownerId !== req.user.id) return res.status(403).end();
  await db.tasks.delete(req.params.id);
});

5. Security misconfiguration

// 必须: helmet、CORS 白名单、HTTPS 重定向、安全 cookies
app.use(helmet());
app.use(cors({ origin: ALLOWED_ORIGINS }));
app.use(session({ cookie: { secure: true, httpOnly: true, sameSite: 'strict' } }));

6. Vulnerable dependencies

npm audit          # 检查已知 CVE
npm audit fix      # 自动修复兼容补丁

Classification:

  • Critical/High → must fix (fix or replace the dependency)
  • Moderate → assess actual exploitability (may only be exploitable under specific conditions)
  • Low → schedule but do not block release

Input validation

import { z } from 'zod';

const CreateTaskSchema = z.object({
  title: z.string().min(1).max(200),
  description: z.string().max(5000).optional(),
  priority: z.enum(['low', 'medium', 'high']),
  assigneeId: z.string().uuid().optional(),
});

Rule: All external input is validated at the boundary (API handler). After validation, trust internally.

Secrets management

项目结构:
├── .env.example          # 模板(可提交)
├── .env                  # 真实密钥(在 .gitignore,绝不提交)
└── src/config.ts         # 从环境变量读取

.gitignore 必须包含:
.env
.env.local
*.pem
*.key
credentials.json

Check whether accidentally committed:

git log --all --full-history -- '*.env' '*.pem' 'credentials.*'

Good and bad examples

Good — OWASP checklist verified item by item

A01 Injection: all SQL parameterized ✓ → A02 XSS: framework auto-escaping + DOMPurify ✓ → A04 Access control: every write endpoint verifies ownership ✓ → A06 Dependencies: npm audit has no high/critical ✓ → Input validation: all external input validated with Zod ✓. Each item has a pass/fail determination.

Bad — "we have no user input" so no check is done

"This is just an internal tool, user input was validated on the frontend" — the backend has no input validation, a single line of curl can bypass the frontend. SQL concatenation, non-parameterized queries, no permission checks. After the intranet is compromised, lateral movement is unimpeded.

Output template

Security review conclusion (merged into the Security axis block of 04-review.md ):

## Security 审查

### OWASP Top 10 检查
| 类目 | 状态 | 发现 |
|------|------|------|
| A01 注入 | PASS / FAIL | 具体发现描述 |
| A02 XSS | PASS / FAIL | ... |
| A03 敏感数据暴露 | PASS / FAIL | ... |
| A04 访问控制缺失 | PASS / FAIL | ... |
| A05 安全配置错误 | PASS / FAIL | ... |
| A06 依赖漏洞 | PASS / FAIL | npm audit 结果摘要 |

### 输入验证覆盖
- 已验证的输入端: <列出>
- 未验证的输入端: <列出> (如有则为 Blocking)

### 密钥管理
- 密钥存储方式: 环境变量 / 配置文件 / 硬编码 (如有硬编码则为 Blocking)
- 误提交检查: git log 结果 (如有误提交则为 Blocking)

### 结论
- 审查结果: PASS / FAIL
- Blocking 问题: <列出> (如有)
- 建议: <列出>

Verification evidence

The output or record must include:

  • Input/source: the spec, plan, code, feedback, or release context that was read.
  • Actions performed: The checks, generation, fixes, exports, or release steps actually completed.
  • Verification results: Commands, review conclusions, artifact paths, screenshots, or manual confirmation.
  • Blockers/rollback: Failed items, rollback paths, or issues requiring a human partner's decision.

Common excuses

Excuse Reality Consequence
"It's only used internally, not exposed externally" The intranet is not a trust boundary. Dependency confusion, internal lateral movement—internal applications still need security hardening. After the intranet is breached, lateral movement faces no obstacles; one compromised intranet machine = the entire intranet compromised. The Target data breach infiltrated through an air-conditioning supplier's intranet.
"Everything npm audit reports is low risk" Low risks can combine into high risk. At least read the audit report once. Attack chains exploiting combinations of low-risk CVEs have occurred many times (Log4j was a "low-risk" logging library); ignoring audit = gambling.
"User input has already been validated on the frontend" Frontend validation is UX optimization, not security. An attacker can send curl and bypass it directly. One line of curl -X POST can bypass all frontend validation. Input not validated on the backend = a direct entry point for SQL injection / XSS.
"This is a simple internal tool" A simple tool exposed with one unvalidated input can be used as an intranet pivot. After an internal tool is breached through phishing or a supply chain attack, it becomes an intranet pivot, expanding the scope of damage from 1 tool to the entire infrastructure.
"We'll strengthen security later" Security debt is different from technical debt—security debt can lead to data breaches. It cannot be patched later. Data breach compensation + reputational damage + user churn. The cost of remediation after a security incident is 10-50x the cost of prevention (IBM security report).

Violating the letter of the rules is violating the spirit. There is no gray area.

Verification failure handling

Failure scenario Handling method
SQL/command injection discovered (OWASP A01) Blocking — immediately send back to build for fixing; after fixing, resubmit for security review; cannot go live
XSS / innerHTML user data discovered (OWASP A02) Blocking — immediately send back to build for fixing; must use parameterization or DOMPurify
Secret or token hardcoded/mistakenly committed Blocking — immediately remove the secret, rotate the leaked secret value, add to .gitignore, resubmit
Missing access control (OWASP A04) Blocking — add ownership verification or permission checks, re-review after fixing
npm audit has Critical/High CVE Blocking — can only go live after fixing or replacing the dependency; Low can be scheduled but not ignored
An unvalidated input point exists Blocking — all external input must be validated at the boundary; an omission = a potential injection entry point

Red flag — STOP

  • User input reaches SQL/Shell/HTML without parameterization/escaping
  • A secret or token appears in code or logs
  • Authorization: Bearer <token> over a connection without HTTPS
  • Using < or > String comparison for permission checks (bypassable)
  • Authentication endpoint without rate limiting (brute force)
  • innerHTML、dangerouslySetInnerHTML、eval() Contains user data
  • Stack traces returned by the API contain file paths or internal library names

Verification checklist

  • All user input validated at the boundary (Zod / Yup / Joi)
  • SQL queries use parameterization (no string concatenation)
  • User content in HTML is escaped
  • Error responses do not contain stack traces or internal paths
  • Resource ownership is verified for every write endpoint
  • Secrets are not in the code repository
  • npm audit(or equivalent) no critical/high
  • Security headers set (helmet, CORS allowlist, secure cookies)