aiden-runtime 3.19.5 → 3.19.6

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 (101) hide show
  1. package/dist/core/skillLoader.js +2 -0
  2. package/dist/core/version.js +1 -1
  3. package/dist-bundle/cli.js +3 -1
  4. package/dist-bundle/index.js +3 -1
  5. package/package.json +2 -1
  6. package/scripts/postinstall.js +58 -1
  7. package/workspace-templates/HEARTBEAT.md +16 -0
  8. package/workspace-templates/SOUL.md +267 -0
  9. package/workspace-templates/STANDING_ORDERS.md +21 -0
  10. package/workspace-templates/permissions.yaml +180 -0
  11. package/workspace-templates/skills/architecture-diagram/SKILL.md +126 -0
  12. package/workspace-templates/skills/architecture-diagram/skill.json +25 -0
  13. package/workspace-templates/skills/arxiv/SKILL.md +124 -0
  14. package/workspace-templates/skills/arxiv/skill.json +26 -0
  15. package/workspace-templates/skills/ascii-art/SKILL.md +142 -0
  16. package/workspace-templates/skills/ascii-art/skill.json +26 -0
  17. package/workspace-templates/skills/blogwatcher/SKILL.md +147 -0
  18. package/workspace-templates/skills/blogwatcher/skill.json +26 -0
  19. package/workspace-templates/skills/censys/SKILL.md +104 -0
  20. package/workspace-templates/skills/censys/index.ts +133 -0
  21. package/workspace-templates/skills/censys/skill.json +25 -0
  22. package/workspace-templates/skills/clipboard-history/SKILL.md +101 -0
  23. package/workspace-templates/skills/clipboard-history/skill.json +23 -0
  24. package/workspace-templates/skills/crt-sh/SKILL.md +102 -0
  25. package/workspace-templates/skills/crt-sh/index.ts +59 -0
  26. package/workspace-templates/skills/crt-sh/skill.json +25 -0
  27. package/workspace-templates/skills/cveapi/SKILL.md +114 -0
  28. package/workspace-templates/skills/cveapi/index.ts +249 -0
  29. package/workspace-templates/skills/cveapi/skill.json +25 -0
  30. package/workspace-templates/skills/docker-management/SKILL.md +156 -0
  31. package/workspace-templates/skills/docker-management/skill.json +25 -0
  32. package/workspace-templates/skills/excalidraw/SKILL.md +148 -0
  33. package/workspace-templates/skills/excalidraw/skill.json +25 -0
  34. package/workspace-templates/skills/explainshell/SKILL.md +93 -0
  35. package/workspace-templates/skills/explainshell/index.ts +132 -0
  36. package/workspace-templates/skills/explainshell/skill.json +25 -0
  37. package/workspace-templates/skills/financial_research/SKILL.md +21 -0
  38. package/workspace-templates/skills/financial_research/skill.json +24 -0
  39. package/workspace-templates/skills/gif-search/SKILL.md +122 -0
  40. package/workspace-templates/skills/gif-search/skill.json +25 -0
  41. package/workspace-templates/skills/github-auth/SKILL.md +134 -0
  42. package/workspace-templates/skills/github-auth/skill.json +26 -0
  43. package/workspace-templates/skills/github-issues/SKILL.md +130 -0
  44. package/workspace-templates/skills/github-issues/skill.json +25 -0
  45. package/workspace-templates/skills/github-pr-workflow/SKILL.md +143 -0
  46. package/workspace-templates/skills/github-pr-workflow/skill.json +26 -0
  47. package/workspace-templates/skills/github-repo-management/SKILL.md +147 -0
  48. package/workspace-templates/skills/github-repo-management/skill.json +26 -0
  49. package/workspace-templates/skills/google-workspace/SKILL.md +110 -0
  50. package/workspace-templates/skills/google-workspace/skill.json +26 -0
  51. package/workspace-templates/skills/greynoise/SKILL.md +96 -0
  52. package/workspace-templates/skills/greynoise/index.ts +107 -0
  53. package/workspace-templates/skills/greynoise/skill.json +25 -0
  54. package/workspace-templates/skills/haveibeenpwned/SKILL.md +100 -0
  55. package/workspace-templates/skills/haveibeenpwned/index.ts +72 -0
  56. package/workspace-templates/skills/haveibeenpwned/skill.json +24 -0
  57. package/workspace-templates/skills/jupyter-live-kernel/SKILL.md +116 -0
  58. package/workspace-templates/skills/jupyter-live-kernel/skill.json +25 -0
  59. package/workspace-templates/skills/linear/SKILL.md +107 -0
  60. package/workspace-templates/skills/linear/skill.json +25 -0
  61. package/workspace-templates/skills/nano-pdf/SKILL.md +113 -0
  62. package/workspace-templates/skills/nano-pdf/skill.json +26 -0
  63. package/workspace-templates/skills/notion/SKILL.md +108 -0
  64. package/workspace-templates/skills/notion/skill.json +24 -0
  65. package/workspace-templates/skills/obsidian/SKILL.md +115 -0
  66. package/workspace-templates/skills/obsidian/skill.json +24 -0
  67. package/workspace-templates/skills/ocr-and-documents/SKILL.md +125 -0
  68. package/workspace-templates/skills/ocr-and-documents/skill.json +26 -0
  69. package/workspace-templates/skills/p5js/SKILL.md +163 -0
  70. package/workspace-templates/skills/p5js/skill.json +24 -0
  71. package/workspace-templates/skills/research-paper-writing/SKILL.md +158 -0
  72. package/workspace-templates/skills/research-paper-writing/skill.json +26 -0
  73. package/workspace-templates/skills/securityheaders/SKILL.md +99 -0
  74. package/workspace-templates/skills/securityheaders/index.ts +213 -0
  75. package/workspace-templates/skills/securityheaders/skill.json +26 -0
  76. package/workspace-templates/skills/shodan/SKILL.md +113 -0
  77. package/workspace-templates/skills/shodan/index.ts +94 -0
  78. package/workspace-templates/skills/shodan/skill.json +26 -0
  79. package/workspace-templates/skills/songsee/SKILL.md +152 -0
  80. package/workspace-templates/skills/songsee/skill.json +25 -0
  81. package/workspace-templates/skills/ssllabs/SKILL.md +107 -0
  82. package/workspace-templates/skills/ssllabs/index.ts +208 -0
  83. package/workspace-templates/skills/ssllabs/skill.json +27 -0
  84. package/workspace-templates/skills/stable-diffusion-image-generation/SKILL.md +136 -0
  85. package/workspace-templates/skills/stable-diffusion-image-generation/skill.json +24 -0
  86. package/workspace-templates/skills/systematic-debugging/SKILL.md +131 -0
  87. package/workspace-templates/skills/systematic-debugging/skill.json +25 -0
  88. package/workspace-templates/skills/test-driven-development/SKILL.md +164 -0
  89. package/workspace-templates/skills/test-driven-development/skill.json +25 -0
  90. package/workspace-templates/skills/urlscan/SKILL.md +118 -0
  91. package/workspace-templates/skills/urlscan/index.ts +94 -0
  92. package/workspace-templates/skills/urlscan/skill.json +24 -0
  93. package/workspace-templates/skills/virustotal/SKILL.md +120 -0
  94. package/workspace-templates/skills/virustotal/index.ts +124 -0
  95. package/workspace-templates/skills/virustotal/skill.json +26 -0
  96. package/workspace-templates/skills/web_research/SKILL.md +18 -0
  97. package/workspace-templates/skills/web_research/skill.json +20 -0
  98. package/workspace-templates/skills/xitter/SKILL.md +148 -0
  99. package/workspace-templates/skills/xitter/skill.json +26 -0
  100. package/workspace-templates/skills/youtube-content/SKILL.md +121 -0
  101. package/workspace-templates/skills/youtube-content/skill.json +25 -0
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: p5js
3
+ description: Create generative visual art and interactive sketches using p5.js, rendered as self-contained HTML files
4
+ category: creative
5
+ version: 1.0.0
6
+ origin: aiden
7
+ license: Apache-2.0
8
+ tags: p5js, generative-art, creative-coding, canvas, animation, visualization, javascript, interactive
9
+ ---
10
+
11
+ # p5.js Generative Art and Creative Coding
12
+
13
+ Create generative visual art, animations, and interactive sketches using p5.js. Output is a self-contained HTML file that opens in any browser — no build step required.
14
+
15
+ ## When to Use
16
+
17
+ - User wants generative or procedural visual art
18
+ - User wants an interactive animation or visualization
19
+ - User wants to visualize data in a creative, non-standard way
20
+ - User wants a screensaver-style animation
21
+ - User wants to experiment with creative coding
22
+
23
+ ## How to Use
24
+
25
+ ### 1. Basic p5.js HTML template
26
+
27
+ ```html
28
+ <!DOCTYPE html>
29
+ <html>
30
+ <head>
31
+ <meta charset="utf-8">
32
+ <title>p5.js Sketch</title>
33
+ <style>body { margin: 0; background: #0d1117; overflow: hidden; }</style>
34
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"></script>
35
+ </head>
36
+ <body>
37
+ <script>
38
+ // Your p5.js sketch code goes here
39
+
40
+ function setup() {
41
+ createCanvas(windowWidth, windowHeight);
42
+ background(13, 17, 23);
43
+ }
44
+
45
+ function draw() {
46
+ // Called every frame (~60fps)
47
+ }
48
+ </script>
49
+ </body>
50
+ </html>
51
+ ```
52
+
53
+ ### 2. Flowing particles sketch
54
+
55
+ ```javascript
56
+ let particles = [];
57
+
58
+ function setup() {
59
+ createCanvas(windowWidth, windowHeight);
60
+ colorMode(HSB, 360, 100, 100, 100);
61
+ background(220, 30, 10);
62
+ for (let i = 0; i < 300; i++) {
63
+ particles.push({ x: random(width), y: random(height), hue: random(180, 280) });
64
+ }
65
+ }
66
+
67
+ function draw() {
68
+ fill(220, 30, 10, 8);
69
+ noStroke();
70
+ rect(0, 0, width, height);
71
+
72
+ for (let p of particles) {
73
+ let angle = noise(p.x * 0.003, p.y * 0.003) * TWO_PI * 4;
74
+ p.x += cos(angle) * 2;
75
+ p.y += sin(angle) * 2;
76
+ if (p.x < 0 || p.x > width || p.y < 0 || p.y > height) {
77
+ p.x = random(width); p.y = random(height);
78
+ }
79
+ stroke(p.hue, 70, 90, 60);
80
+ strokeWeight(1.5);
81
+ point(p.x, p.y);
82
+ }
83
+ }
84
+ ```
85
+
86
+ ### 3. Recursive fractal tree
87
+
88
+ ```javascript
89
+ function setup() {
90
+ createCanvas(800, 600);
91
+ background(13, 17, 23);
92
+ stroke(100, 200, 120, 180);
93
+ translate(width / 2, height);
94
+ branch(120);
95
+ }
96
+
97
+ function branch(len) {
98
+ strokeWeight(map(len, 5, 120, 0.5, 4));
99
+ line(0, 0, 0, -len);
100
+ translate(0, -len);
101
+ if (len > 8) {
102
+ push(); rotate(0.4); branch(len * 0.67); pop();
103
+ push(); rotate(-0.4); branch(len * 0.67); pop();
104
+ }
105
+ }
106
+ ```
107
+
108
+ ### 4. Interactive mouse repulsion
109
+
110
+ ```javascript
111
+ let circles = [];
112
+
113
+ function setup() {
114
+ createCanvas(windowWidth, windowHeight);
115
+ for (let i = 0; i < 100; i++) {
116
+ circles.push({ x: random(width), y: random(height), vx: 0, vy: 0, r: random(5, 15) });
117
+ }
118
+ }
119
+
120
+ function draw() {
121
+ background(13, 17, 23, 25);
122
+ for (let c of circles) {
123
+ let dx = c.x - mouseX, dy = c.y - mouseY;
124
+ let dist = sqrt(dx*dx + dy*dy);
125
+ if (dist < 100) { c.vx += dx / dist * 2; c.vy += dy / dist * 2; }
126
+ c.vx *= 0.95; c.vy *= 0.95;
127
+ c.x = constrain(c.x + c.vx, 0, width);
128
+ c.y = constrain(c.y + c.vy, 0, height);
129
+ fill(180, 100, 220, 180); noStroke();
130
+ ellipse(c.x, c.y, c.r * 2);
131
+ }
132
+ }
133
+ ```
134
+
135
+ ### 5. Generate and save the sketch file
136
+
137
+ ```python
138
+ template = open("sketch_template.html").read()
139
+ sketch_code = """/* paste sketch code here */"""
140
+ html = template.replace("// Your p5.js sketch code goes here", sketch_code)
141
+ with open("my_sketch.html", "w") as f:
142
+ f.write(html)
143
+ print("Open my_sketch.html in a browser")
144
+ ```
145
+
146
+ ## Examples
147
+
148
+ **"Create a flowing particle animation with a dark background"**
149
+ → Use template from step 1, insert sketch code from step 2. Save as `particles.html`.
150
+
151
+ **"Make an interactive sketch where particles run away from the mouse"**
152
+ → Use step 4 pasted into the template from step 1.
153
+
154
+ **"Generate a fractal tree visualization"**
155
+ → Use step 3 inside the basic template. Adjust branch length and angle for different tree shapes.
156
+
157
+ ## Cautions
158
+
159
+ - p5.js sketches run in the browser — they cannot access the local filesystem directly
160
+ - The CDN link requires internet access; for offline use, download `p5.min.js` locally
161
+ - Very high particle counts (> 5000) may cause frame rate drops — start with 300-500 particles
162
+ - `windowWidth`/`windowHeight` resize the canvas to fill the browser window — add `windowResized()` handler for responsive sketches
163
+ - For offline-first output, embed the p5.js library inline rather than using the CDN
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "p5js",
3
+ "version": "1.0.0",
4
+ "description": "Create generative visual art and interactive sketches using p5.js, rendered as self-contained HTML files",
5
+ "author": "aiden",
6
+ "license": "MIT",
7
+ "tools": [],
8
+ "trigger_phrases": [],
9
+ "compatible_agents": [
10
+ "aiden"
11
+ ],
12
+ "min_agent_version": "3.0.0",
13
+ "tags": [
14
+ "p5js",
15
+ "generative-art",
16
+ "creative-coding",
17
+ "canvas",
18
+ "animation",
19
+ "visualization",
20
+ "javascript",
21
+ "interactive"
22
+ ],
23
+ "created": "2026-04-27T17:11:40.572Z"
24
+ }
@@ -0,0 +1,158 @@
1
+ ---
2
+ name: research-paper-writing
3
+ description: Structured pipeline for writing ML and AI research papers — from literature review to LaTeX submission
4
+ category: research
5
+ version: 1.0.0
6
+ origin: aiden
7
+ license: Apache-2.0
8
+ tags: research, paper, writing, latex, ml, ai, academic, arxiv, publication, citation
9
+ ---
10
+
11
+ # Research Paper Writing Pipeline
12
+
13
+ A structured, step-by-step pipeline for writing ML/AI research papers: from problem framing through literature review, experiment design, writing, and LaTeX formatting for arXiv submission.
14
+
15
+ ## When to Use
16
+
17
+ - User wants to write or structure an academic research paper
18
+ - User wants help organizing experiments and results for a paper
19
+ - User wants to format a paper in LaTeX for arXiv or a conference
20
+ - User wants to do a literature review on a topic
21
+ - User wants to write an abstract, introduction, or related work section
22
+
23
+ ## How to Use
24
+
25
+ ### Phase 1: Frame the contribution
26
+
27
+ Define the paper's core claim before writing anything else.
28
+
29
+ ```
30
+ 1. One-sentence contribution: "We show that X outperforms Y on Z by doing W"
31
+ 2. Key insight: what is non-obvious about your approach?
32
+ 3. Research question: what question does the paper answer?
33
+ 4. Limitations scope: what is explicitly out of scope?
34
+ ```
35
+
36
+ ### Phase 2: Literature review
37
+
38
+ Use the arXiv skill to find related work, then organize findings:
39
+
40
+ ```
41
+ Search strategy:
42
+ - Start with 2-3 "seed" papers you know are relevant
43
+ - Find papers that cite them (via Semantic Scholar API)
44
+ - Search arXiv for your core keywords + recent date filter
45
+ - Organize into: direct predecessors, concurrent work, tangential work
46
+
47
+ For each related paper, note:
48
+ - Core method
49
+ - Dataset/benchmark used
50
+ - Key result number
51
+ - How your work differs
52
+ ```
53
+
54
+ ```python
55
+ # Semantic Scholar API — find papers citing a known paper
56
+ import requests
57
+ paper_id = "arXiv:2305.17333"
58
+ resp = requests.get(f"https://api.semanticscholar.org/graph/v1/paper/{paper_id}/citations?fields=title,year,authors,externalIds&limit=20")
59
+ for c in resp.json()["data"]:
60
+ print(c["citingPaper"]["title"])
61
+ ```
62
+
63
+ ### Phase 3: Structure the paper
64
+
65
+ Standard ML/AI paper structure:
66
+
67
+ ```
68
+ Abstract (150-250 words) — problem, method, key result, significance
69
+ 1. Introduction — motivation, gap, contribution, paper overview
70
+ 2. Related Work — organize by theme, not chronologically
71
+ 3. Method — notation, architecture/algorithm, key design choices
72
+ 4. Experiments — datasets, baselines, metrics, implementation details
73
+ 5. Results — main table, ablation study, qualitative examples
74
+ 6. Discussion — limitations, failure modes, future work
75
+ 7. Conclusion — restate contribution, broader impact
76
+ References
77
+ Appendix (optional) — proofs, additional experiments, hyperparameters
78
+ ```
79
+
80
+ ### Phase 4: Write in LaTeX
81
+
82
+ Basic arXiv-ready template:
83
+
84
+ ```latex
85
+ \documentclass[10pt,twocolumn]{article}
86
+ \usepackage{arxiv} % from https://github.com/kourgeorge/arxiv-style
87
+ \usepackage{amsmath,amssymb,graphicx,booktabs,hyperref}
88
+
89
+ \title{Your Paper Title}
90
+ \author{Author One \and Author Two}
91
+ \date{\today}
92
+
93
+ \begin{document}
94
+ \maketitle
95
+
96
+ \begin{abstract}
97
+ Your abstract here. State the problem, method, key result, and significance in 150--250 words.
98
+ \end{abstract}
99
+
100
+ \section{Introduction}
101
+ ...
102
+
103
+ \bibliography{refs}
104
+ \bibliographystyle{plain}
105
+ \end{document}
106
+ ```
107
+
108
+ ### Phase 5: Tables and figures
109
+
110
+ ```latex
111
+ % Results table with booktabs
112
+ \begin{table}[t]
113
+ \centering
114
+ \caption{Comparison on benchmark dataset.}
115
+ \begin{tabular}{lcc}
116
+ \toprule
117
+ Method & Accuracy & F1 \\
118
+ \midrule
119
+ Baseline & 72.3 & 71.1 \\
120
+ Prior SOTA & 78.6 & 77.9 \\
121
+ \textbf{Ours} & \textbf{83.2} & \textbf{82.7} \\
122
+ \bottomrule
123
+ \end{tabular}
124
+ \label{tab:results}
125
+ \end{table}
126
+ ```
127
+
128
+ ### Phase 6: Compile and check
129
+
130
+ ```powershell
131
+ # Compile LaTeX (requires MiKTeX or TeX Live)
132
+ pdflatex paper.tex
133
+ bibtex paper
134
+ pdflatex paper.tex
135
+ pdflatex paper.tex # run twice to resolve references
136
+
137
+ # Check word count
138
+ texcount paper.tex
139
+ ```
140
+
141
+ ## Examples
142
+
143
+ **"Help me write the abstract for my paper on efficient transformers"**
144
+ → Use Phase 1 to extract the core claim, then write 4 sentences: problem → gap → method → key result.
145
+
146
+ **"I need to find related papers on sparse attention before writing the related work section"**
147
+ → Use Phase 2: search arXiv (`cs.LG` + `sparse attention`), use Semantic Scholar to find citing papers.
148
+
149
+ **"Format my experiment results as a LaTeX table"**
150
+ → Use Phase 5 with the booktabs template.
151
+
152
+ ## Cautions
153
+
154
+ - Write the related work section after the method section — you need to know your contribution to characterize prior work accurately
155
+ - Ablation studies are required at top venues (NeurIPS, ICML, ICLR) — plan them during experiment design, not after
156
+ - arXiv LaTeX compilation is strict — avoid non-standard packages; test with `pdflatex` before submitting
157
+ - Never include fabricated citations — use only papers you have actually read
158
+ - Check target venue formatting guidelines — ICML, NeurIPS, and ICLR each have distinct style files
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "research-paper-writing",
3
+ "version": "1.0.0",
4
+ "description": "Structured pipeline for writing ML and AI research papers — from literature review to LaTeX submission",
5
+ "author": "aiden",
6
+ "license": "MIT",
7
+ "tools": [],
8
+ "trigger_phrases": [],
9
+ "compatible_agents": [
10
+ "aiden"
11
+ ],
12
+ "min_agent_version": "3.0.0",
13
+ "tags": [
14
+ "research",
15
+ "paper",
16
+ "writing",
17
+ "latex",
18
+ "ml",
19
+ "ai",
20
+ "academic",
21
+ "arxiv",
22
+ "publication",
23
+ "citation"
24
+ ],
25
+ "created": "2026-04-27T17:11:40.658Z"
26
+ }
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: securityheaders
3
+ description: Audit HTTP security headers for any URL and receive a grade (A+ to F) with specific recommendations for missing headers
4
+ category: security
5
+ version: 1.0.0
6
+ license: Apache-2.0
7
+ origin: aiden
8
+ tags: security, http, headers, csp, hsts, xframe, audit, web, hardening, compliance
9
+ ---
10
+
11
+ # Security Headers — HTTP Header Audit
12
+
13
+ Check any website for missing or misconfigured HTTP security headers. Returns a grade from A+ to F with a list of which headers are present, which are absent, and why each matters for protection against XSS, clickjacking, MIME sniffing, and data leakage.
14
+
15
+ **No API key required.** Powered by securityheaders.com.
16
+
17
+ ## When to Use
18
+
19
+ - Audit a website before a security review or penetration test
20
+ - Verify that a newly deployed application has the correct security headers
21
+ - Check compliance with security baselines (OWASP, NIST, CIS)
22
+ - User asks "check security headers for X", "is example.com missing HSTS?", "grade the headers on my site"
23
+
24
+ ## How to Use
25
+
26
+ ### Check security headers for a URL
27
+
28
+ ```powershell
29
+ $target = "https://taracod.com"
30
+ $encoded = [Uri]::EscapeDataString($target)
31
+ $url = "https://securityheaders.com/?q=$encoded&followRedirects=on&hide=on"
32
+
33
+ $response = Invoke-WebRequest -Uri $url -UseBasicParsing
34
+ # Extract grade from HTML badge
35
+ $grade = if ($response.Content -match 'class="[^"]*reportTitle[^"]*"[^>]*>[\s\S]*?label[^"]*"([^"]+)"') {
36
+ $Matches[1] -replace 'label[- ]', '' -replace 'success', 'A' -replace 'warning', 'B/C' -replace 'danger', 'D/F'
37
+ } else { 'check manually' }
38
+
39
+ Write-Host "URL: $target"
40
+ Write-Host "Grade: $grade"
41
+ Write-Host "Full report: $url"
42
+ ```
43
+
44
+ ### Audit headers and list missing ones
45
+
46
+ ```powershell
47
+ $target = "https://example.com"
48
+ $encoded = [Uri]::EscapeDataString($target)
49
+ $response = Invoke-WebRequest -Uri "https://securityheaders.com/?q=$encoded&followRedirects=on&hide=on" -UseBasicParsing
50
+ $html = $response.Content
51
+
52
+ # Extract missing headers (rows marked as warnings/missing)
53
+ $pattern = '<div[^>]*class="[^"]*missing[^"]*"[^>]*>([\s\S]*?)<\/div>'
54
+ $missing = [regex]::Matches($html, $pattern) | ForEach-Object {
55
+ $_.Groups[1].Value -replace '<[^>]+>', '' -replace '\s+', ' '
56
+ } | Where-Object { $_.Trim() }
57
+
58
+ Write-Host "Missing headers:"
59
+ $missing | ForEach-Object { Write-Host " ✗ $($_.Trim())" }
60
+ Write-Host ""
61
+ Write-Host "Report: https://securityheaders.com/?q=$encoded&followRedirects=on"
62
+ ```
63
+
64
+ ### Key security headers and what they do
65
+
66
+ ```
67
+ Strict-Transport-Security → Forces HTTPS; prevents downgrade attacks
68
+ Content-Security-Policy → Restricts content sources; blocks XSS
69
+ X-Frame-Options → Prevents clickjacking (deprecated by CSP)
70
+ X-Content-Type-Options → Blocks MIME-sniffing attacks
71
+ Referrer-Policy → Controls referrer data leakage
72
+ Permissions-Policy → Restricts browser feature access (camera, location, etc.)
73
+ ```
74
+
75
+ ## Examples
76
+
77
+ **"Audit security headers for taracod.com"**
78
+ → Returns grade, lists present and missing headers with fix suggestions.
79
+
80
+ **"Does github.com have Content-Security-Policy?"**
81
+ → Check the headers report — CSP row shows value if present.
82
+
83
+ **"My site is getting an F — what headers am I missing?"**
84
+ → Audit returns the full missing-headers list with descriptions.
85
+
86
+ **"Check HSTS on my production domain"**
87
+ → Look for Strict-Transport-Security in the report — check max-age value.
88
+
89
+ ## Cautions
90
+
91
+ - `hide=on` prevents results from appearing in the public "recent scans" feed — always use it
92
+ - `followRedirects=on` ensures the final destination URL is scanned, not just the redirect
93
+ - The tool scans what headers are **sent** — not what your server config says it should send
94
+ - Rate-limit: do not hammer the free service; add delays when scanning multiple URLs
95
+ - Grade is based on header presence, not perfect configuration — review values manually
96
+
97
+ ## Requirements
98
+
99
+ - None — no API key needed
@@ -0,0 +1,213 @@
1
+ // skills/securityheaders/index.ts
2
+ // Programmatic handler — HTTP security header audit via securityheaders.com.
3
+
4
+ import { ApiSkill } from '../../core/apiSkillBase'
5
+
6
+ const skill = new ApiSkill({
7
+ name: 'securityheaders',
8
+ baseUrl: 'https://securityheaders.com',
9
+ authType: 'none',
10
+ rateLimit: { requests: 3, windowMs: 1_000 },
11
+ timeout: 20_000,
12
+ retries: 2,
13
+ })
14
+
15
+ // ── Known security headers (for detection) ───────────────────
16
+
17
+ const KNOWN_HEADERS = [
18
+ 'Strict-Transport-Security',
19
+ 'Content-Security-Policy',
20
+ 'X-Frame-Options',
21
+ 'X-Content-Type-Options',
22
+ 'Referrer-Policy',
23
+ 'Permissions-Policy',
24
+ 'Cross-Origin-Opener-Policy',
25
+ 'Cross-Origin-Embedder-Policy',
26
+ 'Cross-Origin-Resource-Policy',
27
+ 'X-XSS-Protection', // deprecated but still checked
28
+ 'Expect-CT', // deprecated
29
+ ]
30
+
31
+ // ── HTML parsing helpers ──────────────────────────────────────
32
+
33
+ function stripTags(html: string): string {
34
+ return html
35
+ .replace(/<[^>]+>/g, ' ')
36
+ .replace(/&amp;/g, '&')
37
+ .replace(/&lt;/g, '<')
38
+ .replace(/&gt;/g, '>')
39
+ .replace(/&quot;/g, '"')
40
+ .replace(/&#39;/g, "'")
41
+ .replace(/&nbsp;/g, ' ')
42
+ .replace(/\s+/g, ' ')
43
+ .trim()
44
+ }
45
+
46
+ /**
47
+ * Extract the grade letter from securityheaders.com HTML.
48
+ *
49
+ * The grade appears inside an element like:
50
+ * <span class="label label-success">A+</span>
51
+ * <span class="label label-warning">C</span>
52
+ * <span class="label label-danger">F</span>
53
+ *
54
+ * It also appears in the page title:
55
+ * <title>Security headers for example.com - Grade: A</title>
56
+ */
57
+ function extractGrade(html: string): string {
58
+ // Try page title first — most reliable
59
+ const titleMatch = html.match(/<title>[^<]*Grade:\s*([A-F][+-]?)/i)
60
+ if (titleMatch) return titleMatch[1]
61
+
62
+ // Try the badge spans
63
+ const badgeRe = /<span[^>]*class="[^"]*label[^"]*"[^>]*>\s*([A-F][+-]?)\s*<\/span>/gi
64
+ let m: RegExpExecArray | null
65
+ const candidates: string[] = []
66
+ while ((m = badgeRe.exec(html)) !== null) {
67
+ const g = m[1].trim()
68
+ if (/^[A-F][+-]?$/.test(g)) candidates.push(g)
69
+ }
70
+ if (candidates.length > 0) return candidates[0]
71
+
72
+ return 'unknown'
73
+ }
74
+
75
+ /**
76
+ * Detect which known security headers are present and which are missing
77
+ * by scanning the HTML for header name strings near "positive" / "negative" signals.
78
+ */
79
+ function extractHeaders(html: string): { present: string[]; missing: string[] } {
80
+ const present: string[] = []
81
+ const missing: string[] = []
82
+
83
+ for (const header of KNOWN_HEADERS) {
84
+ // Escape for regex
85
+ const esc = header.replace(/[-]/g, '\\-')
86
+ const idx = html.search(new RegExp(esc, 'i'))
87
+ if (idx < 0) continue // not mentioned at all
88
+
89
+ // Look at the surrounding context (up to 400 chars before the header name)
90
+ // for class indicators like "bad", "warn", "missing", "success", "good"
91
+ const before = html.slice(Math.max(0, idx - 400), idx)
92
+ const rowCtx = before.slice(before.lastIndexOf('<tr'))
93
+
94
+ if (/class="[^"]*(?:bad|missing|warn|danger)[^"]*"/i.test(rowCtx)) {
95
+ missing.push(header)
96
+ } else {
97
+ present.push(header)
98
+ }
99
+ }
100
+
101
+ return { present, missing }
102
+ }
103
+
104
+ // ── Output types ──────────────────────────────────────────────
105
+
106
+ export interface SecurityHeadersAudit {
107
+ url: string
108
+ grade: string // A+ through F, or "unknown"
109
+ present: string[] // headers that were found
110
+ missing: string[] // headers that were absent
111
+ recommendations: string[] // brief fix suggestions for missing headers
112
+ scanUrl: string // link to full report
113
+ parsed: boolean // false if HTML parsing was inconclusive
114
+ }
115
+
116
+ // Suggested fixes for missing headers
117
+ const RECOMMENDATIONS: Record<string, string> = {
118
+ 'Strict-Transport-Security': 'Add: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload',
119
+ 'Content-Security-Policy': 'Add a Content-Security-Policy header to restrict content sources',
120
+ 'X-Frame-Options': 'Add: X-Frame-Options: SAMEORIGIN (or use CSP frame-ancestors)',
121
+ 'X-Content-Type-Options': 'Add: X-Content-Type-Options: nosniff',
122
+ 'Referrer-Policy': 'Add: Referrer-Policy: strict-origin-when-cross-origin',
123
+ 'Permissions-Policy': 'Add: Permissions-Policy: geolocation=(), camera=(), microphone=()',
124
+ 'Cross-Origin-Opener-Policy': 'Add: Cross-Origin-Opener-Policy: same-origin',
125
+ 'Cross-Origin-Embedder-Policy': 'Add: Cross-Origin-Embedder-Policy: require-corp',
126
+ 'Cross-Origin-Resource-Policy': 'Add: Cross-Origin-Resource-Policy: same-origin',
127
+ }
128
+
129
+ // ── Public API ────────────────────────────────────────────────
130
+
131
+ /**
132
+ * Audit HTTP security headers for a URL.
133
+ *
134
+ * Fetches the securityheaders.com report page and parses the grade
135
+ * and header presence/absence from the HTML.
136
+ *
137
+ * @param targetUrl The URL to audit (e.g. "https://example.com")
138
+ */
139
+ export async function audit(targetUrl: string): Promise<SecurityHeadersAudit> {
140
+ const scanUrl = `https://securityheaders.com/?q=${encodeURIComponent(targetUrl)}&followRedirects=on&hide=on`
141
+
142
+ let grade = 'unknown'
143
+ let present: string[] = []
144
+ let missing: string[] = []
145
+ let parsed = false
146
+
147
+ try {
148
+ const html = await skill.get('/', {
149
+ q: targetUrl,
150
+ followRedirects: 'on',
151
+ hide: 'on',
152
+ })
153
+
154
+ if (typeof html === 'string' && html.length > 500) {
155
+ grade = extractGrade(html)
156
+ const h = extractHeaders(html)
157
+ present = h.present
158
+ missing = h.missing
159
+ parsed = grade !== 'unknown' || present.length > 0 || missing.length > 0
160
+ }
161
+ } catch {
162
+ // Network error — return URL so user can visit manually
163
+ }
164
+
165
+ const recommendations = missing
166
+ .map(h => RECOMMENDATIONS[h])
167
+ .filter(Boolean) as string[]
168
+
169
+ return {
170
+ url: targetUrl,
171
+ grade,
172
+ present,
173
+ missing,
174
+ recommendations,
175
+ scanUrl,
176
+ parsed,
177
+ }
178
+ }
179
+
180
+ /** Format an audit result as a human-readable string. */
181
+ export function formatAudit(result: SecurityHeadersAudit): string {
182
+ const lines = [
183
+ `URL: ${result.url}`,
184
+ `Grade: ${result.grade}`,
185
+ '',
186
+ ]
187
+
188
+ if (result.present.length > 0) {
189
+ lines.push('✅ Present:')
190
+ result.present.forEach(h => lines.push(` ${h}`))
191
+ lines.push('')
192
+ }
193
+
194
+ if (result.missing.length > 0) {
195
+ lines.push('❌ Missing:')
196
+ result.missing.forEach(h => lines.push(` ${h}`))
197
+ lines.push('')
198
+ }
199
+
200
+ if (result.recommendations.length > 0) {
201
+ lines.push('Recommendations:')
202
+ result.recommendations.forEach(r => lines.push(` • ${r}`))
203
+ lines.push('')
204
+ }
205
+
206
+ lines.push(`Full report: ${result.scanUrl}`)
207
+
208
+ if (!result.parsed) {
209
+ lines.push('(Note: HTML parsing was inconclusive — view the full report for details)')
210
+ }
211
+
212
+ return lines.join('\n')
213
+ }