secure-repo 1.0.9 → 1.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.
- package/bin/cli.js +102 -8
- package/package.json +1 -1
- package/templates/free/ACCESSIBILITY.md +99 -0
package/bin/cli.js
CHANGED
|
@@ -21,6 +21,7 @@ const RECOMMENDED_FILES = [
|
|
|
21
21
|
{ file: "SECURITY.md", category: "security", severity: "high" },
|
|
22
22
|
{ file: "AUTH.md", category: "security", severity: "high" },
|
|
23
23
|
{ file: "API.md", category: "security", severity: "high" },
|
|
24
|
+
{ file: "ACCESSIBILITY.md", category: "accessibility", severity: "medium" },
|
|
24
25
|
{ file: "DATABASE.md", category: "security", severity: "medium" },
|
|
25
26
|
{ file: "DEPLOYMENT.md", category: "operations", severity: "medium" },
|
|
26
27
|
{ file: "INCIDENT_RESPONSE.md", category: "operations", severity: "medium" },
|
|
@@ -56,9 +57,10 @@ function printHelp() {
|
|
|
56
57
|
--output Output directory (default: current directory)
|
|
57
58
|
|
|
58
59
|
Free templates (always included):
|
|
59
|
-
SECURITY.md
|
|
60
|
-
AUTH.md
|
|
61
|
-
API.md
|
|
60
|
+
SECURITY.md Secrets management, attack surface, enforced architecture
|
|
61
|
+
AUTH.md Token handling, session rules, password policy, roles
|
|
62
|
+
API.md Input validation, rate limiting, error handling
|
|
63
|
+
ACCESSIBILITY.md WCAG compliance, semantic HTML, keyboard nav, screen readers
|
|
62
64
|
|
|
63
65
|
Pro templates (purchase at https://buy.polar.sh/polar_cl_q7Wa3Gcng42437OoTx4wHVNyMMyYv0WbtobUv145EZH):
|
|
64
66
|
30 additional files — templates, audit checklist, stack presets, examples
|
|
@@ -273,6 +275,88 @@ function installFromZip(zipPath, outputDir, force) {
|
|
|
273
275
|
}
|
|
274
276
|
}
|
|
275
277
|
|
|
278
|
+
// ============================================================
|
|
279
|
+
// Agent instruction files — tell AI agents to read policy files
|
|
280
|
+
// ============================================================
|
|
281
|
+
const AGENT_INSTRUCTION = `# Security Policies — MUST READ
|
|
282
|
+
|
|
283
|
+
This project uses ShipSecure security policies. Before writing or modifying code, you MUST read and follow every policy file that exists in this repository.
|
|
284
|
+
|
|
285
|
+
## Policy Files
|
|
286
|
+
|
|
287
|
+
Read each of these files if they exist before making changes:
|
|
288
|
+
|
|
289
|
+
### Core
|
|
290
|
+
- SECURITY.md — Secrets management, attack surface, enforced architecture
|
|
291
|
+
- AUTH.md — Token handling, session rules, password policy, roles
|
|
292
|
+
- API.md — Input validation, rate limiting, error handling
|
|
293
|
+
- ACCESSIBILITY.md — WCAG compliance, semantic HTML, keyboard navigation, screen readers
|
|
294
|
+
|
|
295
|
+
### Extended
|
|
296
|
+
- DATABASE.md — Query safety, access control, migrations
|
|
297
|
+
- ENV_VARIABLES.md — Environment variable handling, secret rotation
|
|
298
|
+
- DEPLOYMENT.md — Deploy pipeline, environment isolation
|
|
299
|
+
- INCIDENT_RESPONSE.md — Breach response, escalation procedures
|
|
300
|
+
- ACCESS_CONTROL.md — Role-based access, permission boundaries
|
|
301
|
+
- DATA_PRIVACY.md — PII handling, data retention, GDPR compliance
|
|
302
|
+
- PAYMENTS.md — Payment processing, PCI compliance
|
|
303
|
+
- FILE_UPLOADS.md — Upload validation, storage security
|
|
304
|
+
- RATE_LIMITING.md — Throttling, abuse prevention
|
|
305
|
+
- THIRD_PARTY.md — Dependency security, vendor risk
|
|
306
|
+
- LOGGING_PII.md — Log sanitization, PII redaction
|
|
307
|
+
- TESTING.md — Security test requirements
|
|
308
|
+
- OBSERVABILITY.md — Monitoring, alerting, audit trails
|
|
309
|
+
- THREAT_MODEL.md — Known threats and mitigations
|
|
310
|
+
- PR_CHECKLIST.md — Pre-merge security checklist
|
|
311
|
+
- CONTRIBUTING_SECURITY.md — Security contribution guidelines
|
|
312
|
+
- VULNERABILITY_REPORTING.md — Responsible disclosure process
|
|
313
|
+
- POLICY_INDEX.md — Index of all policies
|
|
314
|
+
- FULL_AUDIT_CHECKLIST.md — 100+ point security audit checklist
|
|
315
|
+
|
|
316
|
+
### Stack Presets
|
|
317
|
+
- supabase-preset/ — Supabase-specific security rules (if present)
|
|
318
|
+
- firebase-preset/ — Firebase-specific security rules (if present)
|
|
319
|
+
|
|
320
|
+
## Rules
|
|
321
|
+
|
|
322
|
+
1. Always check policy files before writing code — if your task touches auth, APIs, database, payments, file uploads, or any area with a policy file, read that file first.
|
|
323
|
+
2. Never violate a policy — if a policy says "never do X", do not do X. Flag it if unsure.
|
|
324
|
+
3. Secrets are never hardcoded — no API keys, tokens, passwords, or credentials in source code.
|
|
325
|
+
4. Validate all input — every endpoint, every form, every external data source.
|
|
326
|
+
5. Follow the principle of least privilege — only request the permissions you need.
|
|
327
|
+
`;
|
|
328
|
+
|
|
329
|
+
function writeAgentFiles(outputDir, force) {
|
|
330
|
+
const agentFiles = [
|
|
331
|
+
{ path: "CLAUDE.md", name: "Claude" },
|
|
332
|
+
{ path: ".cursorrules", name: "Cursor" },
|
|
333
|
+
{ path: ".github/copilot-instructions.md", name: "GitHub Copilot" },
|
|
334
|
+
{ path: ".windsurfrules", name: "Windsurf" },
|
|
335
|
+
{ path: ".clinerules", name: "Cline" },
|
|
336
|
+
];
|
|
337
|
+
|
|
338
|
+
let written = 0;
|
|
339
|
+
let skipped = 0;
|
|
340
|
+
|
|
341
|
+
console.log("\n Agent instructions:");
|
|
342
|
+
agentFiles.forEach(({ path: filePath, name }) => {
|
|
343
|
+
const fullPath = path.join(outputDir, filePath);
|
|
344
|
+
const dir = path.dirname(fullPath);
|
|
345
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
346
|
+
|
|
347
|
+
if (fs.existsSync(fullPath) && !force) {
|
|
348
|
+
console.log(` [skip] ${filePath} (${name}) — use --force to overwrite`);
|
|
349
|
+
skipped++;
|
|
350
|
+
} else {
|
|
351
|
+
fs.writeFileSync(fullPath, AGENT_INSTRUCTION);
|
|
352
|
+
console.log(` [done] ${filePath} (${name})`);
|
|
353
|
+
written++;
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
return { written, skipped };
|
|
358
|
+
}
|
|
359
|
+
|
|
276
360
|
// ============================================================
|
|
277
361
|
// INIT — install templates (free, or free + pro with --key)
|
|
278
362
|
// ============================================================
|
|
@@ -307,8 +391,11 @@ async function init() {
|
|
|
307
391
|
await downloadProZip(zipPath, licenseKey);
|
|
308
392
|
const proResult = installFromZip(zipPath, outputDir, force);
|
|
309
393
|
|
|
310
|
-
|
|
311
|
-
const
|
|
394
|
+
// Write agent instruction files
|
|
395
|
+
const agentResult = writeAgentFiles(outputDir, force);
|
|
396
|
+
|
|
397
|
+
const totalCopied = freeResult.copied + proResult.copied + agentResult.written;
|
|
398
|
+
const totalSkipped = freeResult.skipped + proResult.skipped + agentResult.skipped;
|
|
312
399
|
|
|
313
400
|
console.log(`\n Done! ${totalCopied} files installed, ${totalSkipped} skipped.`);
|
|
314
401
|
console.log("\n Next steps:");
|
|
@@ -330,7 +417,13 @@ async function init() {
|
|
|
330
417
|
console.log(" Free templates:");
|
|
331
418
|
const result = copyFiles(FREE_DIR, outputDir, force);
|
|
332
419
|
|
|
333
|
-
|
|
420
|
+
// Write agent instruction files
|
|
421
|
+
const agentResult = writeAgentFiles(outputDir, force);
|
|
422
|
+
|
|
423
|
+
const totalCopied = result.copied + agentResult.written;
|
|
424
|
+
const totalSkipped = result.skipped + agentResult.skipped;
|
|
425
|
+
|
|
426
|
+
console.log(`\n Done! ${totalCopied} files added, ${totalSkipped} skipped.`);
|
|
334
427
|
console.log("\n Next steps:");
|
|
335
428
|
console.log(" 1. Customize the templates for your project");
|
|
336
429
|
console.log(" 2. Run: npx secure-repo audit");
|
|
@@ -374,9 +467,10 @@ function importPack() {
|
|
|
374
467
|
|
|
375
468
|
try {
|
|
376
469
|
const proResult = installFromZip(resolvedPath, outputDir, force);
|
|
470
|
+
const agentResult = writeAgentFiles(outputDir, force);
|
|
377
471
|
|
|
378
|
-
const totalCopied = freeResult.copied + proResult.copied;
|
|
379
|
-
const totalSkipped = freeResult.skipped + proResult.skipped;
|
|
472
|
+
const totalCopied = freeResult.copied + proResult.copied + agentResult.written;
|
|
473
|
+
const totalSkipped = freeResult.skipped + proResult.skipped + agentResult.skipped;
|
|
380
474
|
|
|
381
475
|
console.log(`\n Done! ${totalCopied} files imported, ${totalSkipped} skipped.\n`);
|
|
382
476
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Accessibility Policy
|
|
2
|
+
|
|
3
|
+
This repository must meet WCAG 2.1 Level AA standards. Treat accessibility requirements as **non-optional**.
|
|
4
|
+
|
|
5
|
+
## Agent Rules (MUST FOLLOW)
|
|
6
|
+
|
|
7
|
+
- **Semantic HTML first**
|
|
8
|
+
- Use `<button>` for actions, `<a>` for navigation, `<nav>`, `<main>`, `<header>`, `<footer>`, `<section>`, `<article>` for structure.
|
|
9
|
+
- Never use `<div>` or `<span>` for interactive elements. If it's clickable, it must be a `<button>` or `<a>`.
|
|
10
|
+
- Use heading hierarchy (`h1` > `h2` > `h3`) — never skip levels.
|
|
11
|
+
|
|
12
|
+
- **All images must have alt text**
|
|
13
|
+
- Informative images: describe the content (`alt="Bar chart showing 40% growth in Q3"`).
|
|
14
|
+
- Decorative images: use empty alt (`alt=""`) or CSS background.
|
|
15
|
+
- Never use `alt="image"`, `alt="photo"`, or `alt="icon"`.
|
|
16
|
+
|
|
17
|
+
- **All form inputs must have labels**
|
|
18
|
+
- Use `<label htmlFor="id">` or `aria-label` / `aria-labelledby`.
|
|
19
|
+
- Never use placeholder text as the only label.
|
|
20
|
+
- Error messages must be associated with their input via `aria-describedby`.
|
|
21
|
+
|
|
22
|
+
- **Keyboard navigation is mandatory**
|
|
23
|
+
- Every interactive element must be reachable and operable with keyboard only (Tab, Enter, Escape, Arrow keys).
|
|
24
|
+
- Focus order must follow visual reading order.
|
|
25
|
+
- Never remove `:focus` or `:focus-visible` outlines without providing a visible alternative.
|
|
26
|
+
- Modal dialogs must trap focus and return focus on close.
|
|
27
|
+
|
|
28
|
+
- **Color is never the only indicator**
|
|
29
|
+
- Error states, status indicators, and required fields must use text, icons, or patterns in addition to color.
|
|
30
|
+
- Maintain minimum contrast ratios:
|
|
31
|
+
- Normal text: 4.5:1 against background.
|
|
32
|
+
- Large text (18px+ bold or 24px+): 3:1 against background.
|
|
33
|
+
- UI components and icons: 3:1 against adjacent colors.
|
|
34
|
+
|
|
35
|
+
- **Font sizes and readability**
|
|
36
|
+
- Minimum body text: 16px (1rem). Never go below 14px for any readable text.
|
|
37
|
+
- Use relative units (`rem`, `em`) not fixed `px` for font sizes — allows user browser zoom and font size preferences.
|
|
38
|
+
- Line height: minimum 1.5 for body text, 1.2 for headings.
|
|
39
|
+
- Paragraph max-width: 65–75 characters for comfortable reading.
|
|
40
|
+
- Never disable user text scaling — do not set `maximum-scale=1` in viewport meta.
|
|
41
|
+
- Touch targets: minimum 44x44px for buttons and links on mobile.
|
|
42
|
+
|
|
43
|
+
- **ARIA usage**
|
|
44
|
+
- Prefer native HTML elements over ARIA. ARIA is a last resort, not a first choice.
|
|
45
|
+
- If you use ARIA: `aria-label`, `aria-labelledby`, `aria-describedby`, `aria-live`, `aria-expanded`, `aria-hidden`.
|
|
46
|
+
- Never use `aria-hidden="true"` on focusable elements.
|
|
47
|
+
- Dynamic content updates must use `aria-live="polite"` or `aria-live="assertive"`.
|
|
48
|
+
|
|
49
|
+
- **Motion and animation**
|
|
50
|
+
- Respect `prefers-reduced-motion`. Wrap animations in `@media (prefers-reduced-motion: no-preference)`.
|
|
51
|
+
- Never auto-play video or audio without user consent.
|
|
52
|
+
- Avoid flashing content (no more than 3 flashes per second).
|
|
53
|
+
|
|
54
|
+
## Required Checks Before Merge
|
|
55
|
+
|
|
56
|
+
- **Keyboard test**
|
|
57
|
+
- Tab through every interactive element on the page.
|
|
58
|
+
- Verify focus is visible, logical, and never trapped (except in modals).
|
|
59
|
+
|
|
60
|
+
- **Screen reader test**
|
|
61
|
+
- Headings, landmarks, form labels, and alt text must be announced correctly.
|
|
62
|
+
- Dynamic updates (toasts, errors, loading states) must be announced via `aria-live`.
|
|
63
|
+
|
|
64
|
+
- **Color contrast check**
|
|
65
|
+
- Run a contrast checker on all text and interactive elements.
|
|
66
|
+
- Verify no information is conveyed by color alone.
|
|
67
|
+
|
|
68
|
+
- **Zoom test**
|
|
69
|
+
- Page must be usable at 200% browser zoom with no content loss or overlap.
|
|
70
|
+
|
|
71
|
+
## Patterns To Use
|
|
72
|
+
|
|
73
|
+
- **Skip navigation link**
|
|
74
|
+
- Add a "Skip to main content" link as the first focusable element.
|
|
75
|
+
- `<a href="#main" className="sr-only focus:not-sr-only">Skip to main content</a>`
|
|
76
|
+
|
|
77
|
+
- **Loading states**
|
|
78
|
+
- Use `aria-busy="true"` on containers that are loading.
|
|
79
|
+
- Announce completion with `aria-live="polite"`.
|
|
80
|
+
|
|
81
|
+
- **Error handling in forms**
|
|
82
|
+
- Show error summary at the top of the form.
|
|
83
|
+
- Link each error to its field with `aria-describedby`.
|
|
84
|
+
- Move focus to the first error field or the error summary.
|
|
85
|
+
|
|
86
|
+
- **Icon buttons**
|
|
87
|
+
- Every icon-only button must have `aria-label`.
|
|
88
|
+
- Example: `<button aria-label="Close dialog"><XIcon /></button>`
|
|
89
|
+
|
|
90
|
+
- **Tables**
|
|
91
|
+
- Use `<th scope="col">` for column headers and `<th scope="row">` for row headers.
|
|
92
|
+
- Use `<caption>` to describe the table's purpose.
|
|
93
|
+
|
|
94
|
+
## Testing Tools
|
|
95
|
+
|
|
96
|
+
- axe DevTools (browser extension)
|
|
97
|
+
- Lighthouse accessibility audit
|
|
98
|
+
- VoiceOver (macOS) / NVDA (Windows) for screen reader testing
|
|
99
|
+
- `prefers-reduced-motion` emulation in DevTools
|