ai-developer-skill-os 9.3.1 → 10.2.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 (258) hide show
  1. package/.agents/AGENTS.md +73 -40
  2. package/.agents/DEV_PROFILE.md +36 -2
  3. package/.agents/LICENSE +21 -21
  4. package/.agents/docs/ARCHITECTURE.md +56 -120
  5. package/.agents/docs/GOVERNANCE.md +3 -3
  6. package/.agents/docs/SPEC.md +137 -60
  7. package/.agents/docs/VERSIONING.md +25 -57
  8. package/.agents/docs/adr/0005-v10-platform-consolidation.md +50 -0
  9. package/.agents/docs/schemas/learning.schema.yml +22 -57
  10. package/.agents/docs/schemas/skill.schema.yml +116 -161
  11. package/.agents/docs/schemas/workflow.schema.yml +51 -26
  12. package/.agents/docs/skill-classification.md +1 -1
  13. package/.agents/registry/graph.json +193 -346
  14. package/.agents/registry/index.yaml +90 -233
  15. package/.agents/rules/coding.md +30 -12
  16. package/.agents/rules/command-safety.md +20 -9
  17. package/.agents/rules/global.md +234 -28
  18. package/.agents/rules/prompt-compiler.md +170 -0
  19. package/.agents/rules/safety.md +1 -1
  20. package/.agents/rules/security.md +1 -1
  21. package/.agents/rules/skill-quality.md +18 -3
  22. package/.agents/skills/_template/SKILL.md +238 -88
  23. package/.agents/skills/qk-api-data-discovery/SKILL.md +456 -0
  24. package/.agents/skills/qk-api-data-discovery/references/bronze-record-format.md +47 -0
  25. package/.agents/skills/qk-api-data-discovery/references/data-contract-yaml.md +72 -0
  26. package/.agents/skills/qk-api-data-discovery/references/discovery-report-template.md +110 -0
  27. package/.agents/skills/qk-backend-data/SKILL.md +339 -0
  28. package/.agents/skills/qk-bug-resolution/SKILL.md +328 -248
  29. package/.agents/skills/qk-bug-resolution/evals/scorecard.yaml +1 -1
  30. package/.agents/skills/qk-code-cleaner/SKILL.md +399 -0
  31. package/.agents/skills/qk-code-review/SKILL.md +320 -247
  32. package/.agents/skills/qk-code-review/evals/scorecard.yaml +1 -1
  33. package/.agents/skills/qk-code-review/references/ai/{v8-schema-validation.md → schema-validation.md} +2 -2
  34. package/.agents/skills/qk-code-review/references/cross-cutting/async-concurrency-patterns.md +515 -515
  35. package/.agents/skills/qk-code-review/references/cross-cutting/error-handling-principles.md +492 -492
  36. package/.agents/skills/qk-code-review/references/cross-cutting/n-plus-one-queries.md +309 -309
  37. package/.agents/skills/qk-code-review/references/cross-cutting/sql-injection-prevention.md +307 -307
  38. package/.agents/skills/qk-code-review/references/cross-cutting/xss-prevention.md +263 -263
  39. package/.agents/skills/qk-code-review/references/languages/angular.md +768 -768
  40. package/.agents/skills/qk-code-review/references/languages/c.md +890 -890
  41. package/.agents/skills/qk-code-review/references/languages/cpp.md +893 -893
  42. package/.agents/skills/qk-code-review/references/languages/css-less-sass.md +661 -661
  43. package/.agents/skills/qk-code-review/references/languages/django.md +985 -985
  44. package/.agents/skills/qk-code-review/references/languages/fastapi.md +580 -580
  45. package/.agents/skills/qk-code-review/references/languages/go.md +993 -993
  46. package/.agents/skills/qk-code-review/references/languages/java.md +409 -409
  47. package/.agents/skills/qk-code-review/references/languages/java8.md +586 -586
  48. package/.agents/skills/qk-code-review/references/languages/kotlin.md +1018 -1018
  49. package/.agents/skills/qk-code-review/references/languages/nestjs.md +593 -593
  50. package/.agents/skills/qk-code-review/references/languages/php.md +684 -684
  51. package/.agents/skills/qk-code-review/references/languages/python.md +1073 -1073
  52. package/.agents/skills/qk-code-review/references/languages/qt.md +757 -757
  53. package/.agents/skills/qk-code-review/references/languages/react.md +871 -871
  54. package/.agents/skills/qk-code-review/references/languages/ruby.md +964 -964
  55. package/.agents/skills/qk-code-review/references/languages/rust.md +846 -846
  56. package/.agents/skills/qk-code-review/references/languages/svelte.md +1064 -1064
  57. package/.agents/skills/qk-code-review/references/languages/swift.md +936 -936
  58. package/.agents/skills/qk-code-review/references/languages/typescript.md +1016 -1016
  59. package/.agents/skills/qk-code-review/references/languages/vue.md +924 -924
  60. package/.agents/skills/qk-code-review/references/languages/zig.md +440 -440
  61. package/.agents/skills/qk-devops-release/SKILL.md +294 -0
  62. package/.agents/skills/qk-feature-delivery/SKILL.md +331 -247
  63. package/.agents/skills/qk-feature-delivery/evals/scorecard.yaml +1 -1
  64. package/.agents/skills/qk-orchestrator/SKILL.md +286 -152
  65. package/.agents/skills/qk-orchestrator/evals/scorecard.yaml +1 -1
  66. package/.agents/skills/qk-orchestrator/references/routing-table.md +1 -1
  67. package/.agents/skills/qk-product-spec/SKILL.md +262 -0
  68. package/.agents/skills/qk-prompt-compiler/SKILL.md +444 -0
  69. package/.agents/skills/qk-ui-engineer/SKILL.md +286 -0
  70. package/.agents/workflows/_schema.yml +146 -146
  71. package/.agents/workflows/bug-resolution.yml +155 -121
  72. package/.agents/workflows/code-review.yml +127 -93
  73. package/.agents/workflows/context-discovery.yml +128 -94
  74. package/.agents/workflows/documentation.yml +124 -90
  75. package/.agents/workflows/feature-delivery.yml +158 -124
  76. package/.agents/workflows/production-release.yml +207 -173
  77. package/.agents/workflows/prompt-compilation.yml +126 -0
  78. package/.agents/workflows/refactor.yml +136 -102
  79. package/.agents/workflows/security-audit.yml +149 -115
  80. package/.agents/workflows/shared/quality-gate.yml +3 -1
  81. package/.agents/workflows/skin-governance.yml +149 -115
  82. package/.agents/workflows/spec-driven-development.yml +116 -87
  83. package/CHANGELOG.md +77 -0
  84. package/README.md +125 -205
  85. package/bin/install.js +324 -329
  86. package/package.json +68 -74
  87. package/tooling/build-registry.js +226 -208
  88. package/tooling/run-aar.js +55 -126
  89. package/tooling/sync-versions.js +2 -2
  90. package/tooling/validate-graph.js +100 -87
  91. package/tooling/validate-skills.js +32 -14
  92. package/.agents/README.md +0 -90
  93. package/.agents/docs/CHI_TIET_SKILLS.md +0 -126
  94. package/.agents/docs/HUONG_DAN_SU_DUNG.md +0 -120
  95. package/.agents/docs/MIGRATION-CLEANUP-V8.1.3.md +0 -36
  96. package/.agents/docs/MIGRATION-STATUS.md +0 -35
  97. package/.agents/docs/MIGRATION-V8.md +0 -10
  98. package/.agents/docs/ROADMAP-V8.2.md +0 -78
  99. package/.agents/docs/V8-CERTIFICATION.md +0 -27
  100. package/.agents/docs/decisions/ADR-001-v8-migration.md +0 -58
  101. package/.agents/docs/decisions/ADR-002-workflow-separation.md +0 -50
  102. package/.agents/docs/decisions/ADR-003-registry-generated.md +0 -54
  103. package/.agents/docs/decisions/ADR-008-skill-boundary-review.md +0 -27
  104. package/.agents/registry/capability-graph.yml +0 -390
  105. package/.agents/registry/skills-index.yml +0 -305
  106. package/.agents/skills/_template/capability.yaml +0 -34
  107. package/.agents/skills/_template/evals/scorecard.yaml +0 -19
  108. package/.agents/skills/qk-access-policy/SKILL.md +0 -206
  109. package/.agents/skills/qk-access-policy/capability.yaml +0 -23
  110. package/.agents/skills/qk-access-policy/evals/scorecard.yaml +0 -36
  111. package/.agents/skills/qk-agent-observability/SKILL.md +0 -108
  112. package/.agents/skills/qk-agent-observability/capability.yaml +0 -29
  113. package/.agents/skills/qk-agent-observability/evals/scorecard.yaml +0 -29
  114. package/.agents/skills/qk-agent-observability/references/scorecard.yaml +0 -80
  115. package/.agents/skills/qk-ai-builder/SKILL.md +0 -254
  116. package/.agents/skills/qk-ai-builder/capability.yaml +0 -23
  117. package/.agents/skills/qk-ai-builder/evals/scorecard.yaml +0 -30
  118. package/.agents/skills/qk-api-consumer/SKILL.md +0 -256
  119. package/.agents/skills/qk-api-consumer/capability.yaml +0 -21
  120. package/.agents/skills/qk-api-consumer/evals/scorecard.yaml +0 -29
  121. package/.agents/skills/qk-api-lifecycle/SKILL.md +0 -251
  122. package/.agents/skills/qk-api-lifecycle/capability.yaml +0 -23
  123. package/.agents/skills/qk-api-lifecycle/evals/scorecard.yaml +0 -29
  124. package/.agents/skills/qk-bug-resolution/capability.yaml +0 -25
  125. package/.agents/skills/qk-code-review/capability.yaml +0 -23
  126. package/.agents/skills/qk-context-loader/SKILL.md +0 -198
  127. package/.agents/skills/qk-context-loader/capability.yaml +0 -23
  128. package/.agents/skills/qk-context-loader/evals/scorecard.yaml +0 -28
  129. package/.agents/skills/qk-data-engineer/SKILL.md +0 -253
  130. package/.agents/skills/qk-data-lifecycle/SKILL.md +0 -197
  131. package/.agents/skills/qk-data-lifecycle/capability.yaml +0 -23
  132. package/.agents/skills/qk-data-lifecycle/evals/scorecard.yaml +0 -29
  133. package/.agents/skills/qk-db-optimizer/SKILL.md +0 -210
  134. package/.agents/skills/qk-db-optimizer/capability.yaml +0 -22
  135. package/.agents/skills/qk-db-optimizer/evals/scorecard.yaml +0 -28
  136. package/.agents/skills/qk-design-system-engineering/SKILL.md +0 -193
  137. package/.agents/skills/qk-design-system-engineering/capability.yaml +0 -25
  138. package/.agents/skills/qk-design-system-engineering/evals/scorecard.yaml +0 -27
  139. package/.agents/skills/qk-devops-platform/SKILL.md +0 -198
  140. package/.agents/skills/qk-devops-platform/capability.yaml +0 -29
  141. package/.agents/skills/qk-devops-platform/evals/scorecard.yaml +0 -28
  142. package/.agents/skills/qk-docs/SKILL.md +0 -193
  143. package/.agents/skills/qk-docs/capability.yaml +0 -23
  144. package/.agents/skills/qk-docs/evals/scorecard.yaml +0 -27
  145. package/.agents/skills/qk-engineering-standard/SKILL.md +0 -89
  146. package/.agents/skills/qk-engineering-standard/capability.yaml +0 -23
  147. package/.agents/skills/qk-engineering-standard/evals/scorecard.yaml +0 -28
  148. package/.agents/skills/qk-engineering-standard/references/anti-patterns.md +0 -121
  149. package/.agents/skills/qk-engineering-standard/rules/backend.md +0 -122
  150. package/.agents/skills/qk-engineering-standard/rules/database.md +0 -3
  151. package/.agents/skills/qk-engineering-standard/rules/frontend.md +0 -152
  152. package/.agents/skills/qk-engineering-standard/rules/security.md +0 -3
  153. package/.agents/skills/qk-engineering-standard/rules/testing.md +0 -3
  154. package/.agents/skills/qk-fe-api-integration/SKILL.md +0 -704
  155. package/.agents/skills/qk-fe-api-integration/capability.yaml +0 -21
  156. package/.agents/skills/qk-fe-api-integration/evals/scorecard.yaml +0 -29
  157. package/.agents/skills/qk-feature-delivery/capability.yaml +0 -24
  158. package/.agents/skills/qk-frontend-architecture/SKILL.md +0 -127
  159. package/.agents/skills/qk-frontend-architecture/capability.yaml +0 -28
  160. package/.agents/skills/qk-frontend-architecture/evals/scorecard.yaml +0 -28
  161. package/.agents/skills/qk-help/SKILL.md +0 -107
  162. package/.agents/skills/qk-help/capability.yaml +0 -20
  163. package/.agents/skills/qk-help/evals/scorecard.yaml +0 -13
  164. package/.agents/skills/qk-orchestrator/capability.yaml +0 -22
  165. package/.agents/skills/qk-product-specification/SKILL.md +0 -187
  166. package/.agents/skills/qk-product-specification/capability.yaml +0 -27
  167. package/.agents/skills/qk-product-specification/evals/scorecard.yaml +0 -27
  168. package/.agents/skills/qk-production-release/SKILL.md +0 -188
  169. package/.agents/skills/qk-production-release/capability.yaml +0 -27
  170. package/.agents/skills/qk-production-release/evals/scorecard.yaml +0 -28
  171. package/.agents/skills/qk-project-audit/SKILL.md +0 -174
  172. package/.agents/skills/qk-project-bootstrap/SKILL.md +0 -372
  173. package/.agents/skills/qk-project-bootstrap/capability.yaml +0 -23
  174. package/.agents/skills/qk-project-bootstrap/evals/scorecard.yaml +0 -28
  175. package/.agents/skills/qk-project-health/SKILL.md +0 -202
  176. package/.agents/skills/qk-project-health/capability.yaml +0 -23
  177. package/.agents/skills/qk-project-health/evals/scorecard.yaml +0 -27
  178. package/.agents/skills/qk-project-memory/SKILL.md +0 -303
  179. package/.agents/skills/qk-project-memory/capability.yaml +0 -23
  180. package/.agents/skills/qk-project-memory/evals/scorecard.yaml +0 -27
  181. package/.agents/skills/qk-refactor/SKILL.md +0 -243
  182. package/.agents/skills/qk-refactor/capability.yaml +0 -26
  183. package/.agents/skills/qk-refactor/evals/scorecard.yaml +0 -27
  184. package/.agents/skills/qk-security-audit/SKILL.md +0 -280
  185. package/.agents/skills/qk-security-audit/capability.yaml +0 -29
  186. package/.agents/skills/qk-security-audit/evals/scorecard.yaml +0 -27
  187. package/.agents/skills/qk-system-evolution/SKILL.md +0 -625
  188. package/.agents/skills/qk-system-evolution/capability.yaml +0 -24
  189. package/.agents/skills/qk-system-evolution/evals/scorecard.yaml +0 -26
  190. package/.agents/skills/qk-test-engineering/SKILL.md +0 -215
  191. package/.agents/skills/qk-test-engineering/capability.yaml +0 -28
  192. package/.agents/skills/qk-test-engineering/evals/scorecard.yaml +0 -26
  193. package/.agents/skills/qk-ui-audit/SKILL.md +0 -175
  194. package/.agents/skills/qk-ui-audit/capability.yaml +0 -23
  195. package/.agents/skills/qk-ui-audit/evals/scorecard.yaml +0 -26
  196. package/.agents/skills/qk-ui-audit/references/anti-slop-checklist.md +0 -136
  197. package/.agents/skills/qk-ui-builder/SKILL.md +0 -521
  198. package/.agents/skills/qk-ui-builder/capability.yaml +0 -29
  199. package/.agents/skills/qk-ui-builder/evals/scorecard.yaml +0 -26
  200. package/.agents/skills/qk-ui-builder/references/anti-patterns.md +0 -295
  201. package/.agents/skills/qk-ui-builder/references/color.md +0 -115
  202. package/.agents/skills/qk-ui-builder/references/component-cookbook.md +0 -458
  203. package/.agents/skills/qk-ui-builder/references/copy.md +0 -250
  204. package/.agents/skills/qk-ui-builder/references/interaction-and-states.md +0 -115
  205. package/.agents/skills/qk-ui-builder/references/layout-and-space.md +0 -111
  206. package/.agents/skills/qk-ui-builder/references/macrostructures/01-bento-grid.md +0 -48
  207. package/.agents/skills/qk-ui-builder/references/macrostructures/02-long-document.md +0 -50
  208. package/.agents/skills/qk-ui-builder/references/macrostructures/03-marquee-hero.md +0 -51
  209. package/.agents/skills/qk-ui-builder/references/macrostructures/04-stat-led.md +0 -49
  210. package/.agents/skills/qk-ui-builder/references/macrostructures/05-workbench.md +0 -44
  211. package/.agents/skills/qk-ui-builder/references/macrostructures/06-conversational-faq.md +0 -50
  212. package/.agents/skills/qk-ui-builder/references/macrostructures/07-manifesto.md +0 -51
  213. package/.agents/skills/qk-ui-builder/references/macrostructures/08-photographic.md +0 -50
  214. package/.agents/skills/qk-ui-builder/references/macrostructures/09-quote-led.md +0 -50
  215. package/.agents/skills/qk-ui-builder/references/macrostructures/11-catalogue.md +0 -49
  216. package/.agents/skills/qk-ui-builder/references/macrostructures/12-letter.md +0 -49
  217. package/.agents/skills/qk-ui-builder/references/macrostructures/13-index-first.md +0 -49
  218. package/.agents/skills/qk-ui-builder/references/macrostructures/14-narrative-workflow.md +0 -48
  219. package/.agents/skills/qk-ui-builder/references/macrostructures/15-split-studio.md +0 -48
  220. package/.agents/skills/qk-ui-builder/references/macrostructures/16-feature-stack.md +0 -51
  221. package/.agents/skills/qk-ui-builder/references/macrostructures/17-type-specimen.md +0 -48
  222. package/.agents/skills/qk-ui-builder/references/macrostructures/18-portfolio-grid.md +0 -48
  223. package/.agents/skills/qk-ui-builder/references/macrostructures/19-map-diagram.md +0 -50
  224. package/.agents/skills/qk-ui-builder/references/macrostructures/20-ecosystem-index.md +0 -48
  225. package/.agents/skills/qk-ui-builder/references/macrostructures/21-component-playground.md +0 -45
  226. package/.agents/skills/qk-ui-builder/references/macrostructures.md +0 -38
  227. package/.agents/skills/qk-ui-builder/references/motion.md +0 -95
  228. package/.agents/skills/qk-ui-builder/references/responsive.md +0 -115
  229. package/.agents/skills/qk-ui-builder/references/slop-test.md +0 -135
  230. package/.agents/skills/qk-ui-builder/references/structure.md +0 -280
  231. package/.agents/skills/qk-ui-builder/references/themes/atmospheric.md +0 -53
  232. package/.agents/skills/qk-ui-builder/references/themes/carnival.md +0 -52
  233. package/.agents/skills/qk-ui-builder/references/themes/cobalt.md +0 -52
  234. package/.agents/skills/qk-ui-builder/references/themes/editorial.md +0 -52
  235. package/.agents/skills/qk-ui-builder/references/themes/garden.md +0 -52
  236. package/.agents/skills/qk-ui-builder/references/themes/hum.md +0 -52
  237. package/.agents/skills/qk-ui-builder/references/themes/lumen.md +0 -52
  238. package/.agents/skills/qk-ui-builder/references/themes/midnight.md +0 -52
  239. package/.agents/skills/qk-ui-builder/references/themes/modern-minimal.md +0 -52
  240. package/.agents/skills/qk-ui-builder/references/themes/playful.md +0 -52
  241. package/.agents/skills/qk-ui-builder/references/themes/specimen.md +0 -52
  242. package/.agents/skills/qk-ui-builder/references/themes/terminal.md +0 -52
  243. package/.agents/skills/qk-ui-builder/references/typography.md +0 -129
  244. package/.agents/skills/qk-ui-system-builder/SKILL.md +0 -183
  245. package/.agents/skills/qk-ui-system-builder/capability.yaml +0 -25
  246. package/.agents/skills/qk-ui-system-builder/evals/scorecard.yaml +0 -26
  247. package/.agents/skills/qk-upgrade/SKILL.md +0 -301
  248. package/.agents/skills/qk-upgrade/capability.yaml +0 -24
  249. package/.agents/skills/qk-upgrade/evals/scorecard.yaml +0 -26
  250. package/.agents/skills/qk-validation-gate/SKILL.md +0 -88
  251. package/.agents/skills/qk-validation-gate/capability.yaml +0 -23
  252. package/.agents/skills/qk-validation-gate/evals/scorecard.yaml +0 -26
  253. package/.agents/skills/qk-web-quality-gate/SKILL.md +0 -197
  254. package/.agents/skills/qk-web-quality-gate/capability.yaml +0 -24
  255. package/.agents/skills/qk-web-quality-gate/evals/scorecard.yaml +0 -26
  256. package/.agents/workflows/research.yml +0 -75
  257. package/.agents/workflows/skill-evolution.yml +0 -97
  258. package/tooling/fix-refactor.js +0 -8
@@ -1,264 +1,264 @@
1
- # XSS Prevention Guide
2
-
3
- Language-agnostic Cross-Site Scripting prevention strategies with cross-framework code examples.
4
-
5
- > **Related**: [Security Review Guide](../security-review-guide.md) for comprehensive security checklist and decision framework.
6
-
7
- ## XSS Types
8
-
9
- XSS is ranked #3 in the OWASP Top 10 (2021, merged with Injection). Three variants:
10
-
11
- | Type | Description | Attack Vector |
12
- |------|-------------|---------------|
13
- | **Reflected** | Malicious script reflected off the server in the response | URL parameters, form submissions |
14
- | **Stored (Persistent)** | Malicious script stored in the database and served to users | Comments, profiles, messages |
15
- | **DOM-based** | Client-side JavaScript modifies the DOM unsafely | `innerHTML`, `document.write()`, `eval()` |
16
-
17
- ## Universal Prevention Strategy
18
-
19
- 1. **Output encoding** — encode data for the context it's rendered in (HTML, JS, URL, CSS)
20
- 2. **Content Security Policy (CSP)** — restrict which scripts can execute
21
- 3. **Input sanitization** — only when rich text is required (DOMPurify)
22
- 4. **Framework auto-escaping** — rely on framework defaults, audit escape hatches
23
-
24
- > **Key distinction**: Input validation prevents bad data from entering the system. Output encoding prevents bad data from being rendered as code. Both are necessary; neither alone is sufficient.
25
-
26
- ---
27
-
28
- ## Cross-Framework Examples
29
-
30
- ### React
31
-
32
- ```typescript
33
- // ✅ React auto-escapes JSX expressions (default safe)
34
- return <div>{userInput}</div>;
35
-
36
- // ❌ dangerouslySetInnerHTML bypasses escaping
37
- return <div dangerouslySetInnerHTML={{ __html: userInput }} />;
38
-
39
- // ✅ If HTML is required, sanitize first
40
- import DOMPurify from 'dompurify';
41
- return <div dangerouslySetInnerHTML={{
42
- __html: DOMPurify.sanitize(userInput)
43
- }} />;
44
-
45
- // ❌ href with javascript: protocol
46
- return <a href={`javascript:void(${userInput})`}>Click</a>;
47
-
48
- // ✅ Validate URL protocol
49
- const safeUrl = userInput.startsWith('https://') ? userInput : '#';
50
- return <a href={safeUrl}>Click</a>;
51
-
52
- // ❌ eval / new Function with user input
53
- const result = eval(userInput);
54
-
55
- // ❌ innerHTML in refs / effects
56
- useEffect(() => {
57
- ref.current.innerHTML = userInput;
58
- }, [userInput]);
59
- ```
60
-
61
- ### Vue
62
-
63
- ```html
64
- <!-- ✅ Vue auto-escapes text interpolation -->
65
- <div>{{ userInput }}</div>
66
-
67
- <!-- ❌ v-html bypasses escaping -->
68
- <div v-html="userInput"></div>
69
-
70
- <!-- ✅ Sanitize before v-html -->
71
- <div v-html="sanitized(userInput)"></div>
72
- ```
73
-
74
- ```typescript
75
- import DOMPurify from 'dompurify';
76
-
77
- export default {
78
- methods: {
79
- sanitized(input: string): string {
80
- return DOMPurify.sanitize(input);
81
- }
82
- }
83
- };
84
-
85
- // ❌ v-bind:href with javascript: protocol
86
- // <a :href="userInput">Click</a> — userInput could be "javascript:alert(1)"
87
- ```
88
-
89
- ### Angular
90
-
91
- ```typescript
92
- // ✅ Angular auto-escapes interpolation (default safe)
93
- template: `<div>{{ userInput }}</div>`
94
-
95
- // ❌ bypassSecurityTrustHtml disables sanitization
96
- import { DomSanitizer } from '@angular/platform-browser';
97
-
98
- constructor(private sanitizer: DomSanitizer) {
99
- this.unsafe = this.sanitizer.bypassSecurityTrustHtml(userInput);
100
- }
101
-
102
- // ❌ bypassSecurityTrustUrl with javascript: protocol
103
- this.unsafeUrl = this.sanitizer.bypassSecurityTrustUrl(userInput);
104
-
105
- // ✅ Only use bypassSecurityTrust* with server-validated content
106
- // and document the reason
107
- ```
108
-
109
- ### Svelte
110
-
111
- ```svelte
112
- <!-- ✅ Svelte auto-escapes expressions -->
113
- <div>{userInput}</div>
114
-
115
- <!-- ❌ {@html} bypasses escaping -->
116
- <div>{@html userInput}</div>
117
-
118
- <!-- ✅ Sanitize before {@html} -->
119
- <script>
120
- import DOMPurify from 'dompurify';
121
- const sanitized = DOMPurify.sanitize(userInput);
122
- </script>
123
- <div>{@html sanitized}</div>
124
- ```
125
-
126
- ### Django (Server-Side)
127
-
128
- ```python
129
- # ✅ Django auto-escapes template variables
130
- # template: <p>{{ user_bio }}</p>
131
-
132
- # ❌ mark_safe bypasses auto-escaping
133
- from django.utils.safestring import mark_safe
134
- return HttpResponse(mark_safe(f"<p>{user_bio}</p>"))
135
-
136
- # ❌ autoescape off in template
137
- # {% autoescape off %}{{ user_bio }}{% endautoescape %}
138
-
139
- # ✅ If mark_safe is necessary, escape first
140
- from django.utils.html import escape
141
- return HttpResponse(mark_safe(f"<p>{escape(user_bio)}</p>"))
142
- ```
143
-
144
- ### Server-Side Rendering
145
-
146
- ```typescript
147
- // ❌ SSR: injecting raw user data into HTML
148
- const html = `<div>${userInput}</div>`;
149
-
150
- // ✅ Always escape server-side rendered content
151
- import escapeHtml from 'escape-html';
152
- const html = `<div>${escapeHtml(userInput)}</div>`;
153
-
154
- // ❌ JSON serialization without escaping
155
- const json = JSON.stringify({ name: userInput });
156
- // userInput could contain </script> to break out of script tags
157
-
158
- // ✅ JSON in HTML: escape < and >
159
- const safe = JSON.stringify({ name: userInput })
160
- .replace(/</g, '\\u003c')
161
- .replace(/>/g, '\\u003e');
162
- ```
163
-
164
- ---
165
-
166
- ## Content Security Policy (CSP)
167
-
168
- CSP is defense-in-depth. Even if XSS escapes output encoding, CSP limits what an attacker can do.
169
-
170
- ```nginx
171
- # ✅ Recommended CSP (strict)
172
- Content-Security-Policy:
173
- default-src 'self';
174
- script-src 'self' 'nonce-{random}' 'strict-dynamic';
175
- style-src 'self' 'unsafe-inline';
176
- img-src 'self' data: https:;
177
- object-src 'none';
178
- base-uri 'self';
179
- form-action 'self';
180
- frame-ancestors 'none';
181
- ```
182
-
183
- ```typescript
184
- // ✅ Express middleware
185
- import helmet from 'helmet';
186
-
187
- app.use(helmet.contentSecurityPolicy({
188
- directives: {
189
- defaultSrc: ["'self'"],
190
- scriptSrc: ["'self'", "'nonce-{random}'"],
191
- styleSrc: ["'self'", "'unsafe-inline'"],
192
- objectSrc: ["'none'"],
193
- baseUri: ["'self'"],
194
- formAction: ["'self'"],
195
- frameAncestors: ["'none'"],
196
- },
197
- }));
198
- ```
199
-
200
- ```html
201
- <!-- ✅ CSP nonce in script tags -->
202
- <script nonce="{random}">
203
- // Allowed by CSP
204
- </script>
205
-
206
- <!-- ❌ Inline event handlers (blocked by CSP without 'unsafe-inline') -->
207
- <button onclick="doSomething()">Click</button>
208
-
209
- <!-- ✅ Event listeners in JS with nonce -->
210
- <script nonce="{random}">
211
- document.getElementById('btn').addEventListener('click', doSomething);
212
- </script>
213
- ```
214
-
215
- **CSP anti-patterns to avoid:**
216
- - `script-src 'unsafe-inline'` without nonce/hash
217
- - `script-src 'unsafe-eval'` (enables `eval()`)
218
- - `default-src *` (allows loading from any origin)
219
- - `script-src https:` (allows any HTTPS origin, including attacker-controlled)
220
-
221
- ---
222
-
223
- ## Input Validation vs Output Encoding
224
-
225
- | Layer | What | When | Example |
226
- |-------|------|------|---------|
227
- | **Input validation** | Reject/clean data on entry | At API boundary | Reject `<script>` in a name field |
228
- | **Output encoding** | Encode data for render context | At render time | `&lt;script&gt;` in HTML |
229
-
230
- **Rule**: Input validation is a convenience (reject obviously bad data). Output encoding is the security boundary. Never rely on input validation alone.
231
-
232
- ---
233
-
234
- ## Detection & Testing
235
-
236
- ```bash
237
- # Automated scanning
238
- # OWASP ZAP
239
- zap-cli quick-scan --spider https://example.com
240
-
241
- # Manual testing payloads
242
- <script>alert(1)</script>
243
- <img src=x onerror=alert(1)>
244
- " onmouseover="alert(1)
245
- javascript:alert(1)
246
- '-alert(1)-'
247
-
248
- # Static analysis (code review)
249
- grep -rn "innerHTML\|dangerouslySetInnerHTML\|v-html\|bypassSecurityTrust\|mark_safe\|@html\|{@html" src/
250
- grep -rn "eval(\|new Function\|document.write\|setTimeout.*string\|setInterval.*string" src/
251
- ```
252
-
253
- ---
254
-
255
- ## Review Checklist
256
-
257
- - [ ] Framework auto-escaping is relied upon by default (no manual escaping)
258
- - [ ] `dangerouslySetInnerHTML` / `v-html` / `bypassSecurityTrust` / `{@html}` / `mark_safe` are audited
259
- - [ ] All HTML rendering escape hatches are preceded by `DOMPurify.sanitize()` or equivalent
260
- - [ ] CSP is configured with nonce-based or hash-based script-src
261
- - [ ] No `eval()`, `new Function()`, or `javascript:` URLs with user input
262
- - [ ] No inline event handlers (`onclick="..."`) when CSP is enabled
263
- - [ ] Server-side rendered content is escaped before injection
1
+ # XSS Prevention Guide
2
+
3
+ Language-agnostic Cross-Site Scripting prevention strategies with cross-framework code examples.
4
+
5
+ > **Related**: [Security Review Guide](../security-review-guide.md) for comprehensive security checklist and decision framework.
6
+
7
+ ## XSS Types
8
+
9
+ XSS is ranked #3 in the OWASP Top 10 (2021, merged with Injection). Three variants:
10
+
11
+ | Type | Description | Attack Vector |
12
+ |------|-------------|---------------|
13
+ | **Reflected** | Malicious script reflected off the server in the response | URL parameters, form submissions |
14
+ | **Stored (Persistent)** | Malicious script stored in the database and served to users | Comments, profiles, messages |
15
+ | **DOM-based** | Client-side JavaScript modifies the DOM unsafely | `innerHTML`, `document.write()`, `eval()` |
16
+
17
+ ## Universal Prevention Strategy
18
+
19
+ 1. **Output encoding** — encode data for the context it's rendered in (HTML, JS, URL, CSS)
20
+ 2. **Content Security Policy (CSP)** — restrict which scripts can execute
21
+ 3. **Input sanitization** — only when rich text is required (DOMPurify)
22
+ 4. **Framework auto-escaping** — rely on framework defaults, audit escape hatches
23
+
24
+ > **Key distinction**: Input validation prevents bad data from entering the system. Output encoding prevents bad data from being rendered as code. Both are necessary; neither alone is sufficient.
25
+
26
+ ---
27
+
28
+ ## Cross-Framework Examples
29
+
30
+ ### React
31
+
32
+ ```typescript
33
+ // ✅ React auto-escapes JSX expressions (default safe)
34
+ return <div>{userInput}</div>;
35
+
36
+ // ❌ dangerouslySetInnerHTML bypasses escaping
37
+ return <div dangerouslySetInnerHTML={{ __html: userInput }} />;
38
+
39
+ // ✅ If HTML is required, sanitize first
40
+ import DOMPurify from 'dompurify';
41
+ return <div dangerouslySetInnerHTML={{
42
+ __html: DOMPurify.sanitize(userInput)
43
+ }} />;
44
+
45
+ // ❌ href with javascript: protocol
46
+ return <a href={`javascript:void(${userInput})`}>Click</a>;
47
+
48
+ // ✅ Validate URL protocol
49
+ const safeUrl = userInput.startsWith('https://') ? userInput : '#';
50
+ return <a href={safeUrl}>Click</a>;
51
+
52
+ // ❌ eval / new Function with user input
53
+ const result = eval(userInput);
54
+
55
+ // ❌ innerHTML in refs / effects
56
+ useEffect(() => {
57
+ ref.current.innerHTML = userInput;
58
+ }, [userInput]);
59
+ ```
60
+
61
+ ### Vue
62
+
63
+ ```html
64
+ <!-- ✅ Vue auto-escapes text interpolation -->
65
+ <div>{{ userInput }}</div>
66
+
67
+ <!-- ❌ v-html bypasses escaping -->
68
+ <div v-html="userInput"></div>
69
+
70
+ <!-- ✅ Sanitize before v-html -->
71
+ <div v-html="sanitized(userInput)"></div>
72
+ ```
73
+
74
+ ```typescript
75
+ import DOMPurify from 'dompurify';
76
+
77
+ export default {
78
+ methods: {
79
+ sanitized(input: string): string {
80
+ return DOMPurify.sanitize(input);
81
+ }
82
+ }
83
+ };
84
+
85
+ // ❌ v-bind:href with javascript: protocol
86
+ // <a :href="userInput">Click</a> — userInput could be "javascript:alert(1)"
87
+ ```
88
+
89
+ ### Angular
90
+
91
+ ```typescript
92
+ // ✅ Angular auto-escapes interpolation (default safe)
93
+ template: `<div>{{ userInput }}</div>`
94
+
95
+ // ❌ bypassSecurityTrustHtml disables sanitization
96
+ import { DomSanitizer } from '@angular/platform-browser';
97
+
98
+ constructor(private sanitizer: DomSanitizer) {
99
+ this.unsafe = this.sanitizer.bypassSecurityTrustHtml(userInput);
100
+ }
101
+
102
+ // ❌ bypassSecurityTrustUrl with javascript: protocol
103
+ this.unsafeUrl = this.sanitizer.bypassSecurityTrustUrl(userInput);
104
+
105
+ // ✅ Only use bypassSecurityTrust* with server-validated content
106
+ // and document the reason
107
+ ```
108
+
109
+ ### Svelte
110
+
111
+ ```svelte
112
+ <!-- ✅ Svelte auto-escapes expressions -->
113
+ <div>{userInput}</div>
114
+
115
+ <!-- ❌ {@html} bypasses escaping -->
116
+ <div>{@html userInput}</div>
117
+
118
+ <!-- ✅ Sanitize before {@html} -->
119
+ <script>
120
+ import DOMPurify from 'dompurify';
121
+ const sanitized = DOMPurify.sanitize(userInput);
122
+ </script>
123
+ <div>{@html sanitized}</div>
124
+ ```
125
+
126
+ ### Django (Server-Side)
127
+
128
+ ```python
129
+ # ✅ Django auto-escapes template variables
130
+ # template: <p>{{ user_bio }}</p>
131
+
132
+ # ❌ mark_safe bypasses auto-escaping
133
+ from django.utils.safestring import mark_safe
134
+ return HttpResponse(mark_safe(f"<p>{user_bio}</p>"))
135
+
136
+ # ❌ autoescape off in template
137
+ # {% autoescape off %}{{ user_bio }}{% endautoescape %}
138
+
139
+ # ✅ If mark_safe is necessary, escape first
140
+ from django.utils.html import escape
141
+ return HttpResponse(mark_safe(f"<p>{escape(user_bio)}</p>"))
142
+ ```
143
+
144
+ ### Server-Side Rendering
145
+
146
+ ```typescript
147
+ // ❌ SSR: injecting raw user data into HTML
148
+ const html = `<div>${userInput}</div>`;
149
+
150
+ // ✅ Always escape server-side rendered content
151
+ import escapeHtml from 'escape-html';
152
+ const html = `<div>${escapeHtml(userInput)}</div>`;
153
+
154
+ // ❌ JSON serialization without escaping
155
+ const json = JSON.stringify({ name: userInput });
156
+ // userInput could contain </script> to break out of script tags
157
+
158
+ // ✅ JSON in HTML: escape < and >
159
+ const safe = JSON.stringify({ name: userInput })
160
+ .replace(/</g, '\\u003c')
161
+ .replace(/>/g, '\\u003e');
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Content Security Policy (CSP)
167
+
168
+ CSP is defense-in-depth. Even if XSS escapes output encoding, CSP limits what an attacker can do.
169
+
170
+ ```nginx
171
+ # ✅ Recommended CSP (strict)
172
+ Content-Security-Policy:
173
+ default-src 'self';
174
+ script-src 'self' 'nonce-{random}' 'strict-dynamic';
175
+ style-src 'self' 'unsafe-inline';
176
+ img-src 'self' data: https:;
177
+ object-src 'none';
178
+ base-uri 'self';
179
+ form-action 'self';
180
+ frame-ancestors 'none';
181
+ ```
182
+
183
+ ```typescript
184
+ // ✅ Express middleware
185
+ import helmet from 'helmet';
186
+
187
+ app.use(helmet.contentSecurityPolicy({
188
+ directives: {
189
+ defaultSrc: ["'self'"],
190
+ scriptSrc: ["'self'", "'nonce-{random}'"],
191
+ styleSrc: ["'self'", "'unsafe-inline'"],
192
+ objectSrc: ["'none'"],
193
+ baseUri: ["'self'"],
194
+ formAction: ["'self'"],
195
+ frameAncestors: ["'none'"],
196
+ },
197
+ }));
198
+ ```
199
+
200
+ ```html
201
+ <!-- ✅ CSP nonce in script tags -->
202
+ <script nonce="{random}">
203
+ // Allowed by CSP
204
+ </script>
205
+
206
+ <!-- ❌ Inline event handlers (blocked by CSP without 'unsafe-inline') -->
207
+ <button onclick="doSomething()">Click</button>
208
+
209
+ <!-- ✅ Event listeners in JS with nonce -->
210
+ <script nonce="{random}">
211
+ document.getElementById('btn').addEventListener('click', doSomething);
212
+ </script>
213
+ ```
214
+
215
+ **CSP anti-patterns to avoid:**
216
+ - `script-src 'unsafe-inline'` without nonce/hash
217
+ - `script-src 'unsafe-eval'` (enables `eval()`)
218
+ - `default-src *` (allows loading from any origin)
219
+ - `script-src https:` (allows any HTTPS origin, including attacker-controlled)
220
+
221
+ ---
222
+
223
+ ## Input Validation vs Output Encoding
224
+
225
+ | Layer | What | When | Example |
226
+ |-------|------|------|---------|
227
+ | **Input validation** | Reject/clean data on entry | At API boundary | Reject `<script>` in a name field |
228
+ | **Output encoding** | Encode data for render context | At render time | `&lt;script&gt;` in HTML |
229
+
230
+ **Rule**: Input validation is a convenience (reject obviously bad data). Output encoding is the security boundary. Never rely on input validation alone.
231
+
232
+ ---
233
+
234
+ ## Detection & Testing
235
+
236
+ ```bash
237
+ # Automated scanning
238
+ # OWASP ZAP
239
+ zap-cli quick-scan --spider https://example.com
240
+
241
+ # Manual testing payloads
242
+ <script>alert(1)</script>
243
+ <img src=x onerror=alert(1)>
244
+ " onmouseover="alert(1)
245
+ javascript:alert(1)
246
+ '-alert(1)-'
247
+
248
+ # Static analysis (code review)
249
+ grep -rn "innerHTML\|dangerouslySetInnerHTML\|v-html\|bypassSecurityTrust\|mark_safe\|@html\|{@html" src/
250
+ grep -rn "eval(\|new Function\|document.write\|setTimeout.*string\|setInterval.*string" src/
251
+ ```
252
+
253
+ ---
254
+
255
+ ## Review Checklist
256
+
257
+ - [ ] Framework auto-escaping is relied upon by default (no manual escaping)
258
+ - [ ] `dangerouslySetInnerHTML` / `v-html` / `bypassSecurityTrust` / `{@html}` / `mark_safe` are audited
259
+ - [ ] All HTML rendering escape hatches are preceded by `DOMPurify.sanitize()` or equivalent
260
+ - [ ] CSP is configured with nonce-based or hash-based script-src
261
+ - [ ] No `eval()`, `new Function()`, or `javascript:` URLs with user input
262
+ - [ ] No inline event handlers (`onclick="..."`) when CSP is enabled
263
+ - [ ] Server-side rendered content is escaped before injection
264
264
  - [ ] JSON in HTML is properly escaped (`</script>` → `\u003c/script\u003e`)