skillstore-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/README.md +95 -0
  2. package/data/bundles/devflow-complete.json +19 -0
  3. package/data/free-skills/devflow-agile/manifest.json +19 -0
  4. package/data/free-skills/devflow-agile/plugin/commands/agile/retro.md +23 -0
  5. package/data/free-skills/devflow-agile/plugin/commands/agile/review.md +21 -0
  6. package/data/free-skills/devflow-agile/plugin/commands/agile/sprint.md +30 -0
  7. package/data/free-skills/devflow-agile/plugin/commands/agile/standup.md +20 -0
  8. package/data/free-skills/devflow-agile/plugin/commands/agile.md +35 -0
  9. package/data/free-skills/devflow-agile/plugin/commands/devflow.md +42 -0
  10. package/data/free-skills/devflow-agile/plugin/skills/developer/SKILL.md +93 -0
  11. package/data/free-skills/devflow-agile/plugin/skills/developer/assets/sample-output.md +182 -0
  12. package/data/free-skills/devflow-agile/plugin/skills/developer/references/clean-architecture.md +361 -0
  13. package/data/free-skills/devflow-agile/plugin/skills/developer/references/clean-code-guide.md +207 -0
  14. package/data/free-skills/devflow-agile/plugin/skills/developer/references/debugging-methodology.md +191 -0
  15. package/data/free-skills/devflow-agile/template/agents/agile-coach.md +76 -0
  16. package/data/free-skills/devflow-agile/template/workflows/agile-sprint-workflow.md +81 -0
  17. package/data/free-skills/devflow-bootstrap/manifest.json +8 -0
  18. package/data/free-skills/devflow-bootstrap/plugin/commands/bootstrap/auto.md +31 -0
  19. package/data/free-skills/devflow-bootstrap/plugin/commands/bootstrap.md +38 -0
  20. package/data/free-skills/devflow-bootstrap/plugin/commands/devflow.md +20 -0
  21. package/data/free-skills/devflow-bootstrap/plugin/skills/project-scaffold/SKILL.md +56 -0
  22. package/data/free-skills/devflow-bootstrap/plugin/skills/project-scaffold/assets/sample-output.md +216 -0
  23. package/data/free-skills/devflow-bootstrap/plugin/skills/project-scaffold/references/architecture-decisions.md +254 -0
  24. package/data/free-skills/devflow-bootstrap/plugin/skills/project-scaffold/references/stack-templates.md +400 -0
  25. package/data/free-skills/devflow-bootstrap/template/agents/bootstrap-specialist.md +56 -0
  26. package/data/free-skills/devflow-bootstrap/template/workflows/bootstrap-workflow.md +70 -0
  27. package/data/free-skills/devflow-docs/manifest.json +8 -0
  28. package/data/free-skills/devflow-docs/plugin/commands/devflow.md +20 -0
  29. package/data/free-skills/devflow-docs/plugin/commands/docs/generate.md +17 -0
  30. package/data/free-skills/devflow-docs/plugin/commands/docs/parse.md +19 -0
  31. package/data/free-skills/devflow-docs/plugin/commands/docs.md +26 -0
  32. package/data/free-skills/devflow-docs/plugin/skills/pdf-processor/SKILL.md +59 -0
  33. package/data/free-skills/devflow-docs/plugin/skills/pdf-processor/assets/sample-output.md +114 -0
  34. package/data/free-skills/devflow-docs/plugin/skills/pdf-processor/references/extraction-techniques.md +115 -0
  35. package/data/free-skills/devflow-docs/plugin/skills/pdf-processor/references/ocr-strategies.md +167 -0
  36. package/data/free-skills/devflow-docs/template/agents/docs-specialist.md +35 -0
  37. package/data/free-skills/devflow-docs/template/workflows/docs-workflow.md +70 -0
  38. package/data/free-skills/devflow-postproject/manifest.json +13 -0
  39. package/data/free-skills/devflow-postproject/plugin/commands/devflow.md +34 -0
  40. package/data/free-skills/devflow-postproject/plugin/commands/postproject/handover.md +21 -0
  41. package/data/free-skills/devflow-postproject/plugin/commands/postproject/retro.md +21 -0
  42. package/data/free-skills/devflow-postproject/plugin/commands/postproject/support.md +21 -0
  43. package/data/free-skills/devflow-postproject/plugin/commands/postproject.md +32 -0
  44. package/data/free-skills/devflow-postproject/plugin/skills/retrospective/SKILL.md +70 -0
  45. package/data/free-skills/devflow-postproject/plugin/skills/retrospective/assets/sample-output.md +79 -0
  46. package/data/free-skills/devflow-postproject/plugin/skills/retrospective/references/facilitation-techniques.md +178 -0
  47. package/data/free-skills/devflow-postproject/plugin/skills/retrospective/references/lessons-learned-template.md +118 -0
  48. package/data/free-skills/devflow-postproject/plugin/skills/retrospective/references/retro-techniques.md +100 -0
  49. package/data/free-skills/devflow-postproject/template/agents/transition-manager.md +71 -0
  50. package/data/free-skills/devflow-postproject/template/workflows/transition-workflow.md +72 -0
  51. package/data/free-skills/devflow-presale/manifest.json +15 -0
  52. package/data/free-skills/devflow-presale/plugin/commands/devflow.md +47 -0
  53. package/data/free-skills/devflow-presale/plugin/commands/presale/analyze.md +30 -0
  54. package/data/free-skills/devflow-presale/plugin/commands/presale/estimate.md +30 -0
  55. package/data/free-skills/devflow-presale/plugin/commands/presale/price.md +30 -0
  56. package/data/free-skills/devflow-presale/plugin/commands/presale/propose.md +30 -0
  57. package/data/free-skills/devflow-presale/plugin/commands/presale.md +42 -0
  58. package/data/free-skills/devflow-presale/plugin/skills/requirement-analysis/SKILL.md +63 -0
  59. package/data/free-skills/devflow-presale/plugin/skills/requirement-analysis/assets/sample-output.md +129 -0
  60. package/data/free-skills/devflow-presale/plugin/skills/requirement-analysis/references/extraction-framework.md +140 -0
  61. package/data/free-skills/devflow-presale/plugin/skills/requirement-analysis/references/output-template.md +132 -0
  62. package/data/free-skills/devflow-presale/template/agents/presale-lead.md +83 -0
  63. package/data/free-skills/devflow-presale/template/agents/proposal-reviewer.md +63 -0
  64. package/data/free-skills/devflow-presale/template/workflows/presale-workflow.md +70 -0
  65. package/data/registry/categories.json +7 -0
  66. package/data/registry/packages.json +184 -0
  67. package/data/shared/framework/agents/brainstormer.md +74 -0
  68. package/data/shared/framework/agents/code-reviewer.md +87 -0
  69. package/data/shared/framework/agents/debugger.md +84 -0
  70. package/data/shared/framework/agents/docs-manager.md +55 -0
  71. package/data/shared/framework/agents/git-manager.md +59 -0
  72. package/data/shared/framework/agents/planner.md +68 -0
  73. package/data/shared/framework/agents/researcher.md +66 -0
  74. package/data/shared/framework/agents/tester.md +65 -0
  75. package/data/shared/framework/commands/cook/auto.md +27 -0
  76. package/data/shared/framework/commands/cook.md +45 -0
  77. package/data/shared/framework/commands/fix/ci.md +21 -0
  78. package/data/shared/framework/commands/fix/test.md +26 -0
  79. package/data/shared/framework/commands/fix/types.md +29 -0
  80. package/data/shared/framework/commands/fix.md +26 -0
  81. package/data/shared/framework/commands/git/cm.md +37 -0
  82. package/data/shared/framework/commands/git/pr.md +40 -0
  83. package/data/shared/framework/config/CLAUDE.md.template +26 -0
  84. package/data/shared/framework/config/settings.json +41 -0
  85. package/data/shared/framework/config/skillstore.config.json +29 -0
  86. package/data/shared/framework/hooks/discord-notify.sh +85 -0
  87. package/data/shared/framework/hooks/docs-sync.sh +53 -0
  88. package/data/shared/framework/hooks/modularization-hook.js +103 -0
  89. package/data/shared/framework/hooks/notification.js +94 -0
  90. package/data/shared/framework/hooks/quality-gate.js +109 -0
  91. package/data/shared/framework/hooks/scout-block.js +77 -0
  92. package/data/shared/framework/hooks/telegram-notify.sh +77 -0
  93. package/data/shared/framework/protocols/error-recovery.md +80 -0
  94. package/data/shared/framework/protocols/orchestration-protocol.md +112 -0
  95. package/data/shared/framework/quality/review-protocol.md +76 -0
  96. package/data/shared/framework/quality/verification-protocol.md +66 -0
  97. package/data/shared/framework/rules/development-rules.md +75 -0
  98. package/data/shared/framework/skills/backend-development/SKILL.md +77 -0
  99. package/data/shared/framework/skills/backend-development/assets/sample-output.md +175 -0
  100. package/data/shared/framework/skills/backend-development/references/advanced-patterns.md +180 -0
  101. package/data/shared/framework/skills/backend-development/references/api-design-guide.md +160 -0
  102. package/data/shared/framework/skills/backend-development/references/architecture-patterns.md +183 -0
  103. package/data/shared/framework/skills/backend-development/references/observability-resilience.md +155 -0
  104. package/data/shared/framework/skills/backend-development/references/troubleshooting.md +199 -0
  105. package/data/shared/framework/skills/codebase-analysis/SKILL.md +72 -0
  106. package/data/shared/framework/skills/codebase-analysis/assets/sample-output.md +263 -0
  107. package/data/shared/framework/skills/codebase-analysis/references/analysis-techniques.md +241 -0
  108. package/data/shared/framework/skills/codebase-analysis/references/dependency-mapping.md +280 -0
  109. package/data/shared/framework/skills/codebase-analysis/references/tech-debt-assessment.md +208 -0
  110. package/data/shared/framework/skills/databases/SKILL.md +72 -0
  111. package/data/shared/framework/skills/databases/assets/sample-output.md +212 -0
  112. package/data/shared/framework/skills/databases/references/advanced-data-patterns.md +259 -0
  113. package/data/shared/framework/skills/databases/references/query-optimization.md +214 -0
  114. package/data/shared/framework/skills/databases/references/schema-design.md +159 -0
  115. package/data/shared/framework/skills/databases/references/troubleshooting.md +214 -0
  116. package/data/shared/framework/skills/debugging-investigation/SKILL.md +84 -0
  117. package/data/shared/framework/skills/debugging-investigation/assets/sample-output.md +314 -0
  118. package/data/shared/framework/skills/debugging-investigation/references/systematic-debugging.md +197 -0
  119. package/data/shared/framework/skills/debugging-investigation/references/tool-specific-guides.md +202 -0
  120. package/data/shared/framework/skills/debugging-investigation/references/troubleshooting-patterns.md +196 -0
  121. package/data/shared/framework/skills/frontend-development/SKILL.md +67 -0
  122. package/data/shared/framework/skills/frontend-development/assets/sample-output.md +110 -0
  123. package/data/shared/framework/skills/frontend-development/references/component-patterns.md +112 -0
  124. package/data/shared/framework/skills/frontend-development/references/performance-guide.md +169 -0
  125. package/data/shared/framework/skills/frontend-development/references/routing-forms-realtime.md +374 -0
  126. package/data/shared/framework/skills/frontend-development/references/ssr-rsc-patterns.md +284 -0
  127. package/data/shared/framework/skills/frontend-development/references/troubleshooting.md +154 -0
  128. package/data/shared/framework/skills/mobile-development/SKILL.md +67 -0
  129. package/data/shared/framework/skills/mobile-development/assets/sample-output.md +382 -0
  130. package/data/shared/framework/skills/mobile-development/references/mobile-patterns.md +681 -0
  131. package/data/shared/framework/skills/mobile-development/references/mobile-performance.md +524 -0
  132. package/data/shared/framework/skills/mobile-development/references/troubleshooting.md +158 -0
  133. package/data/shared/framework/skills/security-audit/SKILL.md +83 -0
  134. package/data/shared/framework/skills/security-audit/assets/sample-output.md +451 -0
  135. package/data/shared/framework/skills/security-audit/references/owasp-checklist.md +580 -0
  136. package/data/shared/framework/skills/security-audit/references/secure-coding-patterns.md +433 -0
  137. package/data/shared/framework/skills/security-audit/references/vulnerability-remediation.md +331 -0
  138. package/data/shared/framework/skills/ui-generation/SKILL.md +70 -0
  139. package/data/shared/framework/skills/ui-generation/assets/sample-output.md +139 -0
  140. package/data/shared/framework/skills/ui-generation/references/accessibility-responsive.md +127 -0
  141. package/data/shared/framework/skills/ui-generation/references/compound-components.md +252 -0
  142. package/data/shared/framework/skills/ui-generation/references/generation-patterns.md +110 -0
  143. package/data/shared/framework/skills/ui-generation/references/storybook-design-system.md +278 -0
  144. package/data/shared/framework/skills/ui-generation/references/troubleshooting.md +198 -0
  145. package/data/shared/framework/workflows/documentation-management.md +58 -0
  146. package/data/shared/framework/workflows/primary-workflow.md +88 -0
  147. package/dist/commands/activate.d.ts +3 -0
  148. package/dist/commands/activate.d.ts.map +1 -0
  149. package/dist/commands/activate.js +34 -0
  150. package/dist/commands/activate.js.map +1 -0
  151. package/dist/commands/bundle.d.ts +3 -0
  152. package/dist/commands/bundle.d.ts.map +1 -0
  153. package/dist/commands/bundle.js +64 -0
  154. package/dist/commands/bundle.js.map +1 -0
  155. package/dist/commands/install.d.ts +3 -0
  156. package/dist/commands/install.d.ts.map +1 -0
  157. package/dist/commands/install.js +99 -0
  158. package/dist/commands/install.js.map +1 -0
  159. package/dist/commands/list.d.ts +3 -0
  160. package/dist/commands/list.d.ts.map +1 -0
  161. package/dist/commands/list.js +37 -0
  162. package/dist/commands/list.js.map +1 -0
  163. package/dist/commands/search.d.ts +3 -0
  164. package/dist/commands/search.d.ts.map +1 -0
  165. package/dist/commands/search.js +30 -0
  166. package/dist/commands/search.js.map +1 -0
  167. package/dist/commands/status.d.ts +3 -0
  168. package/dist/commands/status.d.ts.map +1 -0
  169. package/dist/commands/status.js +35 -0
  170. package/dist/commands/status.js.map +1 -0
  171. package/dist/commands/update.d.ts +3 -0
  172. package/dist/commands/update.d.ts.map +1 -0
  173. package/dist/commands/update.js +68 -0
  174. package/dist/commands/update.js.map +1 -0
  175. package/dist/download/cache.d.ts +3 -0
  176. package/dist/download/cache.d.ts.map +1 -0
  177. package/dist/download/cache.js +18 -0
  178. package/dist/download/cache.js.map +1 -0
  179. package/dist/download/client.d.ts +2 -0
  180. package/dist/download/client.d.ts.map +1 -0
  181. package/dist/download/client.js +58 -0
  182. package/dist/download/client.js.map +1 -0
  183. package/dist/index.d.ts +3 -0
  184. package/dist/index.d.ts.map +1 -0
  185. package/dist/index.js +23 -0
  186. package/dist/index.js.map +1 -0
  187. package/dist/installer/file-copier.d.ts +6 -0
  188. package/dist/installer/file-copier.d.ts.map +1 -0
  189. package/dist/installer/file-copier.js +32 -0
  190. package/dist/installer/file-copier.js.map +1 -0
  191. package/dist/installer/plugin-installer.d.ts +12 -0
  192. package/dist/installer/plugin-installer.d.ts.map +1 -0
  193. package/dist/installer/plugin-installer.js +33 -0
  194. package/dist/installer/plugin-installer.js.map +1 -0
  195. package/dist/installer/template-installer.d.ts +12 -0
  196. package/dist/installer/template-installer.d.ts.map +1 -0
  197. package/dist/installer/template-installer.js +45 -0
  198. package/dist/installer/template-installer.js.map +1 -0
  199. package/dist/license/crypto.d.ts +16 -0
  200. package/dist/license/crypto.d.ts.map +1 -0
  201. package/dist/license/crypto.js +50 -0
  202. package/dist/license/crypto.js.map +1 -0
  203. package/dist/license/license-store.d.ts +19 -0
  204. package/dist/license/license-store.d.ts.map +1 -0
  205. package/dist/license/license-store.js +99 -0
  206. package/dist/license/license-store.js.map +1 -0
  207. package/dist/license/validator.d.ts +32 -0
  208. package/dist/license/validator.d.ts.map +1 -0
  209. package/dist/license/validator.js +81 -0
  210. package/dist/license/validator.js.map +1 -0
  211. package/dist/registry/loader.d.ts +30 -0
  212. package/dist/registry/loader.d.ts.map +1 -0
  213. package/dist/registry/loader.js +22 -0
  214. package/dist/registry/loader.js.map +1 -0
  215. package/dist/registry/search-engine.d.ts +9 -0
  216. package/dist/registry/search-engine.d.ts.map +1 -0
  217. package/dist/registry/search-engine.js +30 -0
  218. package/dist/registry/search-engine.js.map +1 -0
  219. package/dist/utils/config.d.ts +14 -0
  220. package/dist/utils/config.d.ts.map +1 -0
  221. package/dist/utils/config.js +28 -0
  222. package/dist/utils/config.js.map +1 -0
  223. package/dist/utils/logger.d.ts +9 -0
  224. package/dist/utils/logger.d.ts.map +1 -0
  225. package/dist/utils/logger.js +22 -0
  226. package/dist/utils/logger.js.map +1 -0
  227. package/dist/utils/paths.d.ts +20 -0
  228. package/dist/utils/paths.d.ts.map +1 -0
  229. package/dist/utils/paths.js +79 -0
  230. package/dist/utils/paths.js.map +1 -0
  231. package/package.json +54 -0
@@ -0,0 +1,433 @@
1
+ # Secure Coding Patterns
2
+
3
+ Reusable security patterns for common development scenarios. Each pattern includes rationale, implementation code, and common mistakes to avoid.
4
+
5
+ ---
6
+
7
+ ## Input Validation
8
+
9
+ ### Allowlist Approach
10
+ Always validate against what is expected, not what is forbidden. Denylists are inherently incomplete.
11
+
12
+ ```javascript
13
+ // GOOD: Allowlist — only accept known-valid values
14
+ const VALID_SORT_FIELDS = ['name', 'created_at', 'price', 'rating'];
15
+ const VALID_SORT_ORDERS = ['asc', 'desc'];
16
+
17
+ function validateSortParams(field, order) {
18
+ if (!VALID_SORT_FIELDS.includes(field)) throw new Error('Invalid sort field');
19
+ if (!VALID_SORT_ORDERS.includes(order)) throw new Error('Invalid sort order');
20
+ return { field, order };
21
+ }
22
+
23
+ // BAD: Denylist — will always miss something
24
+ function validateSortField(field) {
25
+ if (field.includes(';') || field.includes('--')) throw new Error('Invalid');
26
+ return field; // Still injectable via many other vectors
27
+ }
28
+ ```
29
+
30
+ ### Schema Validation (Zod)
31
+ ```typescript
32
+ import { z } from 'zod';
33
+
34
+ const CreateUserSchema = z.object({
35
+ email: z.string().email().max(254),
36
+ password: z.string().min(12).max(128),
37
+ name: z.string().min(1).max(100).regex(/^[\p{L}\p{N}\s'-]+$/u),
38
+ role: z.enum(['user', 'editor']), // Never allow 'admin' via API
39
+ age: z.number().int().min(13).max(150).optional(),
40
+ });
41
+
42
+ // In route handler
43
+ app.post('/api/users', async (req, res) => {
44
+ const result = CreateUserSchema.safeParse(req.body);
45
+ if (!result.success) {
46
+ return res.status(400).json({ errors: result.error.flatten().fieldErrors });
47
+ }
48
+ const validatedData = result.data;
49
+ // Proceed with validated data only
50
+ });
51
+ ```
52
+
53
+ ### Sanitization vs. Validation
54
+ - **Validation:** Reject invalid input entirely (preferred)
55
+ - **Sanitization:** Transform input to a safe form (use only when you must accept rich content)
56
+ - Rule: Validate first, sanitize only as a secondary measure for specific fields (e.g., HTML content)
57
+
58
+ ---
59
+
60
+ ## Output Encoding
61
+
62
+ Context-specific encoding is critical. There is no universal "escape" function.
63
+
64
+ ### Encoding by Context
65
+
66
+ | Context | Encoding | Example |
67
+ |---|---|---|
68
+ | HTML body | HTML entity encode | `<` → `&lt;` |
69
+ | HTML attribute | HTML entity encode + quote | `"` → `&quot;` |
70
+ | JavaScript string | JavaScript Unicode escape | `'` → `\u0027` |
71
+ | URL parameter | Percent encode | ` ` → `%20` |
72
+ | CSS value | CSS hex escape | `(` → `\28` |
73
+
74
+ ```javascript
75
+ // React/JSX: Auto-escapes by default — safe
76
+ const UserGreeting = ({ name }) => <h1>Hello, {name}</h1>;
77
+
78
+ // Dangerous: Bypasses React's auto-escaping
79
+ const UnsafeContent = ({ html }) => (
80
+ <div dangerouslySetInnerHTML={{ __html: html }} /> // XSS if html is untrusted
81
+ );
82
+
83
+ // Safe: Sanitize before rendering raw HTML
84
+ import DOMPurify from 'dompurify';
85
+ const SafeContent = ({ html }) => (
86
+ <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(html, {
87
+ ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br', 'ul', 'ol', 'li'],
88
+ ALLOWED_ATTR: ['href', 'target', 'rel'],
89
+ }) }} />
90
+ );
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Parameterized Queries
96
+
97
+ Never concatenate user input into SQL queries. Use parameterized statements in every language.
98
+
99
+ ### Node.js (pg — PostgreSQL)
100
+ ```javascript
101
+ // Parameterized query — $1, $2 placeholders
102
+ const result = await pool.query(
103
+ 'SELECT * FROM users WHERE email = $1 AND status = $2',
104
+ [email, 'active']
105
+ );
106
+ ```
107
+
108
+ ### Python (psycopg2 — PostgreSQL)
109
+ ```python
110
+ # %s placeholders with tuple parameter
111
+ cursor.execute(
112
+ "SELECT * FROM users WHERE email = %s AND status = %s",
113
+ (email, "active")
114
+ )
115
+ ```
116
+
117
+ ### Java (JDBC — Prepared Statement)
118
+ ```java
119
+ PreparedStatement stmt = connection.prepareStatement(
120
+ "SELECT * FROM users WHERE email = ? AND status = ?"
121
+ );
122
+ stmt.setString(1, email);
123
+ stmt.setString(2, "active");
124
+ ResultSet rs = stmt.executeQuery();
125
+ ```
126
+
127
+ ### ORM Safety Note
128
+ ORMs generally produce parameterized queries, but raw query methods are still vulnerable:
129
+ ```javascript
130
+ // Sequelize — SAFE
131
+ await User.findAll({ where: { email: userInput } });
132
+
133
+ // Sequelize — VULNERABLE (raw query with interpolation)
134
+ await sequelize.query(`SELECT * FROM users WHERE email = '${userInput}'`);
135
+
136
+ // Sequelize — SAFE (raw query with bind)
137
+ await sequelize.query('SELECT * FROM users WHERE email = $1', {
138
+ bind: [userInput], type: QueryTypes.SELECT
139
+ });
140
+ ```
141
+
142
+ ---
143
+
144
+ ## CSRF Protection
145
+
146
+ ### SameSite Cookies (Primary Defense)
147
+ ```javascript
148
+ // SameSite=Lax: Cookie not sent on cross-origin POST (prevents CSRF for state-changing requests)
149
+ res.cookie('session', token, {
150
+ httpOnly: true,
151
+ secure: true,
152
+ sameSite: 'lax',
153
+ });
154
+ ```
155
+
156
+ ### CSRF Tokens (Defense in Depth)
157
+ ```javascript
158
+ const csrf = require('csurf');
159
+ const csrfProtection = csrf({ cookie: { httpOnly: true, sameSite: 'strict' } });
160
+
161
+ // Include token in forms
162
+ app.get('/form', csrfProtection, (req, res) => {
163
+ res.render('form', { csrfToken: req.csrfToken() });
164
+ });
165
+
166
+ // Validate token on submission
167
+ app.post('/submit', csrfProtection, (req, res) => {
168
+ // csurf middleware automatically validates _csrf field
169
+ });
170
+ ```
171
+
172
+ ### Double-Submit Cookie Pattern
173
+ ```javascript
174
+ // For SPAs where server-rendered tokens are impractical
175
+ // 1. Set a random CSRF token in a non-HttpOnly cookie
176
+ // 2. JavaScript reads the cookie and sends it as a header
177
+ // 3. Server validates cookie value matches header value
178
+
179
+ app.use((req, res, next) => {
180
+ if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(req.method)) {
181
+ const cookieToken = req.cookies['csrf-token'];
182
+ const headerToken = req.headers['x-csrf-token'];
183
+ if (!cookieToken || cookieToken !== headerToken) {
184
+ return res.status(403).json({ error: 'CSRF validation failed' });
185
+ }
186
+ }
187
+ next();
188
+ });
189
+ ```
190
+
191
+ ---
192
+
193
+ ## Secure Session Management
194
+
195
+ ### Cookie Flags
196
+ | Flag | Purpose | Setting |
197
+ |---|---|---|
198
+ | `HttpOnly` | Prevents JavaScript access | Always `true` |
199
+ | `Secure` | HTTPS-only transmission | Always `true` in production |
200
+ | `SameSite` | Cross-origin request control | `Lax` (default) or `Strict` |
201
+ | `Path` | Cookie scope | `/` (or narrower) |
202
+ | `Max-Age` | Expiration | 3600 (1h) for sessions |
203
+
204
+ ### Session Rotation on Authentication State Change
205
+ ```javascript
206
+ // Regenerate session ID on: login, logout, privilege change
207
+ function regenerateSession(req) {
208
+ return new Promise((resolve, reject) => {
209
+ const data = { ...req.session };
210
+ req.session.regenerate((err) => {
211
+ if (err) return reject(err);
212
+ Object.assign(req.session, data);
213
+ resolve();
214
+ });
215
+ });
216
+ }
217
+
218
+ // On login
219
+ await regenerateSession(req);
220
+ req.session.userId = user.id;
221
+
222
+ // On logout
223
+ req.session.destroy((err) => {
224
+ res.clearCookie('__Host-sid');
225
+ res.json({ success: true });
226
+ });
227
+ ```
228
+
229
+ ---
230
+
231
+ ## Password Handling
232
+
233
+ ### Algorithm Hierarchy
234
+ 1. **Argon2id** (preferred) — memory-hard, resistant to GPU/ASIC attacks
235
+ 2. **bcrypt** (acceptable) — widely supported, cost factor >= 12
236
+ 3. **PBKDF2** (minimum) — only if Argon2/bcrypt unavailable, iterations >= 600,000
237
+
238
+ ### Password Policy Implementation
239
+ ```javascript
240
+ const zxcvbn = require('zxcvbn');
241
+
242
+ function validatePassword(password) {
243
+ const errors = [];
244
+
245
+ if (password.length < 12) errors.push('Minimum 12 characters');
246
+ if (password.length > 128) errors.push('Maximum 128 characters');
247
+
248
+ // Strength check (zxcvbn score 0-4, require >= 3)
249
+ const strength = zxcvbn(password);
250
+ if (strength.score < 3) {
251
+ errors.push(`Password is too weak: ${strength.feedback.warning || 'Try a longer or more complex password'}`);
252
+ }
253
+
254
+ return { valid: errors.length === 0, errors };
255
+ }
256
+ ```
257
+
258
+ ---
259
+
260
+ ## API Key Management
261
+
262
+ ### Environment Variables (Minimum)
263
+ ```javascript
264
+ // Access via environment — never hardcode
265
+ const apiKey = process.env.STRIPE_SECRET_KEY;
266
+ if (!apiKey) throw new Error('STRIPE_SECRET_KEY is not configured');
267
+ ```
268
+
269
+ ### Secrets Manager Pattern
270
+ ```javascript
271
+ const { SecretsManagerClient, GetSecretValueCommand } = require('@aws-sdk/client-secrets-manager');
272
+
273
+ async function getSecret(secretName) {
274
+ const client = new SecretsManagerClient({ region: 'us-east-1' });
275
+ const response = await client.send(new GetSecretValueCommand({ SecretId: secretName }));
276
+ return JSON.parse(response.SecretString);
277
+ }
278
+
279
+ // Cache secrets to avoid repeated calls
280
+ let cachedSecrets = null;
281
+ async function getSecrets() {
282
+ if (!cachedSecrets) {
283
+ cachedSecrets = await getSecret('app/production/keys');
284
+ // Refresh cache every hour
285
+ setTimeout(() => { cachedSecrets = null; }, 3600000);
286
+ }
287
+ return cachedSecrets;
288
+ }
289
+ ```
290
+
291
+ ### Key Rotation Pattern
292
+ - Generate new key → deploy to consumers → mark old key deprecated → monitor for old key usage → revoke old key
293
+ - Automate with a minimum 90-day rotation cycle
294
+ - Never log API keys; mask in any output (`sk_live_...abc1`)
295
+
296
+ ---
297
+
298
+ ## Content Security Policy (CSP)
299
+
300
+ ### Directive Reference
301
+ | Directive | Controls | Recommended |
302
+ |---|---|---|
303
+ | `default-src` | Fallback for all types | `'self'` |
304
+ | `script-src` | JavaScript sources | `'self'` + nonce |
305
+ | `style-src` | CSS sources | `'self'` + nonce or `'unsafe-inline'` |
306
+ | `img-src` | Image sources | `'self' data: https:` |
307
+ | `connect-src` | XHR, fetch, WebSocket | `'self'` + API domains |
308
+ | `frame-src` | Iframes | `'none'` |
309
+ | `object-src` | Plugins (Flash, Java) | `'none'` |
310
+ | `base-uri` | `<base>` tag | `'self'` |
311
+
312
+ ### Nonce-Based CSP
313
+ ```javascript
314
+ const crypto = require('crypto');
315
+
316
+ app.use((req, res, next) => {
317
+ const nonce = crypto.randomBytes(16).toString('base64');
318
+ res.locals.cspNonce = nonce;
319
+ res.setHeader('Content-Security-Policy',
320
+ `default-src 'self'; script-src 'self' 'nonce-${nonce}'; style-src 'self' 'nonce-${nonce}'; object-src 'none'; base-uri 'self';`
321
+ );
322
+ next();
323
+ });
324
+
325
+ // In templates: <script nonce="<%= cspNonce %>">...</script>
326
+ ```
327
+
328
+ ---
329
+
330
+ ## CORS Configuration
331
+
332
+ ```javascript
333
+ const cors = require('cors');
334
+
335
+ app.use(cors({
336
+ origin: ['https://app.example.com', 'https://admin.example.com'], // Explicit origins
337
+ methods: ['GET', 'POST', 'PUT', 'DELETE'],
338
+ allowedHeaders: ['Content-Type', 'Authorization', 'X-CSRF-Token'],
339
+ credentials: true, // Allow cookies
340
+ maxAge: 86400, // Cache preflight for 24h
341
+ }));
342
+
343
+ // NEVER do this in production:
344
+ // origin: '*' — allows any origin
345
+ // origin: true — reflects any origin (equivalent to *)
346
+ // credentials: true with origin: '*' — browsers block this, but misconfig is dangerous
347
+ ```
348
+
349
+ ---
350
+
351
+ ## Rate Limiting
352
+
353
+ ### Sliding Window Implementation
354
+ ```javascript
355
+ const rateLimit = require('express-rate-limit');
356
+ const RedisStore = require('rate-limit-redis').default;
357
+ const Redis = require('ioredis');
358
+
359
+ const redisClient = new Redis(process.env.REDIS_URL);
360
+
361
+ // Tiered rate limiting
362
+ const apiLimiter = rateLimit({
363
+ store: new RedisStore({ sendCommand: (...args) => redisClient.call(...args) }),
364
+ windowMs: 60 * 1000, // 1 minute
365
+ max: 100, // 100 requests per minute
366
+ standardHeaders: true,
367
+ legacyHeaders: false,
368
+ keyGenerator: (req) => req.user?.id || req.ip,
369
+ skip: (req) => req.user?.role === 'service-account',
370
+ });
371
+
372
+ // Stricter limits for sensitive endpoints
373
+ const authLimiter = rateLimit({
374
+ store: new RedisStore({ sendCommand: (...args) => redisClient.call(...args) }),
375
+ windowMs: 15 * 60 * 1000, // 15 minutes
376
+ max: 5,
377
+ keyGenerator: (req) => req.body.email || req.ip,
378
+ });
379
+
380
+ app.use('/api/', apiLimiter);
381
+ app.post('/api/auth/login', authLimiter);
382
+ app.post('/api/auth/reset-password', authLimiter);
383
+ ```
384
+
385
+ ---
386
+
387
+ ## JWT Security
388
+
389
+ ### Algorithm Validation
390
+ ```javascript
391
+ const jwt = require('jsonwebtoken');
392
+
393
+ // ALWAYS specify algorithm explicitly to prevent algorithm confusion attacks
394
+ const JWT_SECRET = process.env.JWT_SECRET;
395
+ const JWT_OPTIONS = {
396
+ algorithms: ['HS256'], // Allowlist — prevents "none" and RS256 confusion
397
+ issuer: 'app.example.com',
398
+ audience: 'app.example.com',
399
+ };
400
+
401
+ function verifyToken(token) {
402
+ return jwt.verify(token, JWT_SECRET, JWT_OPTIONS);
403
+ }
404
+
405
+ // Short-lived access tokens + refresh token rotation
406
+ function generateTokenPair(userId) {
407
+ const accessToken = jwt.sign({ sub: userId, type: 'access' }, JWT_SECRET, {
408
+ expiresIn: '15m',
409
+ issuer: 'app.example.com',
410
+ });
411
+ const refreshToken = jwt.sign({ sub: userId, type: 'refresh' }, JWT_SECRET, {
412
+ expiresIn: '7d',
413
+ issuer: 'app.example.com',
414
+ jwtid: crypto.randomUUID(), // Unique ID for revocation tracking
415
+ });
416
+ return { accessToken, refreshToken };
417
+ }
418
+ ```
419
+
420
+ ### Token Revocation
421
+ ```javascript
422
+ // Maintain a denylist of revoked token IDs (jti) in Redis
423
+ async function revokeToken(jti, expiresAt) {
424
+ const ttl = Math.ceil((expiresAt * 1000 - Date.now()) / 1000);
425
+ if (ttl > 0) {
426
+ await redisClient.setex(`revoked:${jti}`, ttl, '1');
427
+ }
428
+ }
429
+
430
+ async function isTokenRevoked(jti) {
431
+ return await redisClient.exists(`revoked:${jti}`);
432
+ }
433
+ ```