contextos-agents 2.3.0 → 2.3.2

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 (129) hide show
  1. package/.agents/adapters/cursor/export.js +3 -27
  2. package/.agents/adapters/gemini/export.js +5 -7
  3. package/.agents/adapters/shared.js +14 -1
  4. package/.agents/adapters/zed/export.js +4 -16
  5. package/.agents/compiled/registry.v2.json +33 -33
  6. package/.agents/compiled/registry.v2.sha256 +1 -1
  7. package/.agents/compiler/manifest-compiler.js +8 -5
  8. package/.agents/core/skills/context-manager/EXAMPLES.md +5 -17
  9. package/.agents/core/skills/context-manager/SKILL.md +10 -100
  10. package/.agents/core/skills/context-manager/TROUBLESHOOTING.md +6 -6
  11. package/.agents/core/skills/context-manager/VALIDATION.json +115 -4
  12. package/.agents/core/skills/context-manager/references/context-rules.md +3 -57
  13. package/.agents/core/skills/context-manager/skill.yaml +1 -3
  14. package/.agents/core/skills/context-os/EXAMPLES.md +25 -15
  15. package/.agents/core/skills/context-os/SKILL.md +12 -135
  16. package/.agents/core/skills/context-os/TROUBLESHOOTING.md +11 -6
  17. package/.agents/core/skills/context-os/VALIDATION.json +115 -4
  18. package/.agents/core/skills/context-os/packs.yaml +10 -59
  19. package/.agents/core/skills/context-os/references/context-rules.md +27 -59
  20. package/.agents/core/skills/context-os/references/pipeline.md +14 -119
  21. package/.agents/core/skills/context-os/references/project-graph.md +11 -100
  22. package/.agents/core/skills/context-os/rules.yaml +8 -135
  23. package/.agents/core/skills/engineering-workflow/EXAMPLES.md +15 -50
  24. package/.agents/core/skills/engineering-workflow/SKILL.md +10 -10
  25. package/.agents/core/skills/engineering-workflow/TROUBLESHOOTING.md +11 -19
  26. package/.agents/core/skills/engineering-workflow/VALIDATION.json +115 -4
  27. package/.agents/core/skills/engineering-workflow/references/workflow.md +55 -317
  28. package/.agents/core/skills/gemini-precision/EXAMPLES.md +33 -53
  29. package/.agents/core/skills/gemini-precision/SKILL.md +11 -147
  30. package/.agents/core/skills/gemini-precision/TROUBLESHOOTING.md +12 -25
  31. package/.agents/core/skills/gemini-precision/VALIDATION.json +115 -4
  32. package/.agents/core/skills/gemini-precision/skill.yaml +1 -1
  33. package/.agents/core/skills/gstack-roles/EXAMPLES.md +5 -21
  34. package/.agents/core/skills/gstack-roles/SKILL.md +10 -12
  35. package/.agents/core/skills/gstack-roles/TROUBLESHOOTING.md +6 -12
  36. package/.agents/core/skills/gstack-roles/VALIDATION.json +115 -4
  37. package/.agents/core/skills/gstack-roles/references/roles.md +3 -147
  38. package/.agents/core/skills/ponytail-mindset/EXAMPLES.md +12 -45
  39. package/.agents/core/skills/ponytail-mindset/SKILL.md +10 -13
  40. package/.agents/core/skills/ponytail-mindset/TROUBLESHOOTING.md +10 -19
  41. package/.agents/core/skills/ponytail-mindset/VALIDATION.json +115 -4
  42. package/.agents/core/skills/ponytail-mindset/references/minimalism.md +58 -174
  43. package/.agents/core/skills/security/EXAMPLES.md +19 -55
  44. package/.agents/core/skills/security/SKILL.md +61 -137
  45. package/.agents/core/skills/security/TROUBLESHOOTING.md +13 -19
  46. package/.agents/core/skills/security/VALIDATION.json +115 -4
  47. package/.agents/core/skills/security/skill.yaml +1 -1
  48. package/.agents/generated/claude/skills/context-manager/EXAMPLES.md +5 -17
  49. package/.agents/generated/claude/skills/context-manager/SKILL.md +9 -96
  50. package/.agents/generated/claude/skills/context-manager/TROUBLESHOOTING.md +6 -6
  51. package/.agents/generated/claude/skills/context-manager/VALIDATION.json +115 -4
  52. package/.agents/generated/claude/skills/context-manager/references/context-rules.md +3 -57
  53. package/.agents/generated/claude/skills/context-os/EXAMPLES.md +25 -15
  54. package/.agents/generated/claude/skills/context-os/SKILL.md +11 -133
  55. package/.agents/generated/claude/skills/context-os/TROUBLESHOOTING.md +11 -6
  56. package/.agents/generated/claude/skills/context-os/VALIDATION.json +115 -4
  57. package/.agents/generated/claude/skills/context-os/packs.yaml +10 -59
  58. package/.agents/generated/claude/skills/context-os/references/context-rules.md +27 -59
  59. package/.agents/generated/claude/skills/context-os/references/pipeline.md +14 -119
  60. package/.agents/generated/claude/skills/context-os/references/project-graph.md +11 -100
  61. package/.agents/generated/claude/skills/context-os/rules.yaml +8 -135
  62. package/.agents/generated/claude/skills/engineering-workflow/EXAMPLES.md +15 -50
  63. package/.agents/generated/claude/skills/engineering-workflow/SKILL.md +9 -9
  64. package/.agents/generated/claude/skills/engineering-workflow/TROUBLESHOOTING.md +11 -19
  65. package/.agents/generated/claude/skills/engineering-workflow/VALIDATION.json +115 -4
  66. package/.agents/generated/claude/skills/engineering-workflow/references/workflow.md +55 -317
  67. package/.agents/generated/claude/skills/gemini-precision/EXAMPLES.md +33 -53
  68. package/.agents/generated/claude/skills/gemini-precision/SKILL.md +10 -143
  69. package/.agents/generated/claude/skills/gemini-precision/TROUBLESHOOTING.md +12 -25
  70. package/.agents/generated/claude/skills/gemini-precision/VALIDATION.json +115 -4
  71. package/.agents/generated/claude/skills/gstack-roles/EXAMPLES.md +5 -21
  72. package/.agents/generated/claude/skills/gstack-roles/SKILL.md +9 -11
  73. package/.agents/generated/claude/skills/gstack-roles/TROUBLESHOOTING.md +6 -12
  74. package/.agents/generated/claude/skills/gstack-roles/VALIDATION.json +115 -4
  75. package/.agents/generated/claude/skills/gstack-roles/references/roles.md +3 -147
  76. package/.agents/generated/claude/skills/ponytail-mindset/EXAMPLES.md +12 -45
  77. package/.agents/generated/claude/skills/ponytail-mindset/SKILL.md +9 -12
  78. package/.agents/generated/claude/skills/ponytail-mindset/TROUBLESHOOTING.md +10 -19
  79. package/.agents/generated/claude/skills/ponytail-mindset/VALIDATION.json +115 -4
  80. package/.agents/generated/claude/skills/ponytail-mindset/references/minimalism.md +58 -174
  81. package/.agents/generated/claude/skills/security/EXAMPLES.md +19 -55
  82. package/.agents/generated/claude/skills/security/SKILL.md +60 -134
  83. package/.agents/generated/claude/skills/security/TROUBLESHOOTING.md +13 -19
  84. package/.agents/generated/claude/skills/security/VALIDATION.json +115 -4
  85. package/.agents/generated/gemini/skills/context-manager/EXAMPLES.md +5 -17
  86. package/.agents/generated/gemini/skills/context-manager/SKILL.md +10 -99
  87. package/.agents/generated/gemini/skills/context-manager/TROUBLESHOOTING.md +6 -6
  88. package/.agents/generated/gemini/skills/context-manager/VALIDATION.json +115 -4
  89. package/.agents/generated/gemini/skills/context-manager/references/context-rules.md +3 -57
  90. package/.agents/generated/gemini/skills/context-os/EXAMPLES.md +25 -15
  91. package/.agents/generated/gemini/skills/context-os/SKILL.md +12 -135
  92. package/.agents/generated/gemini/skills/context-os/TROUBLESHOOTING.md +11 -6
  93. package/.agents/generated/gemini/skills/context-os/VALIDATION.json +115 -4
  94. package/.agents/generated/gemini/skills/context-os/packs.yaml +10 -59
  95. package/.agents/generated/gemini/skills/context-os/references/context-rules.md +27 -59
  96. package/.agents/generated/gemini/skills/context-os/references/pipeline.md +14 -119
  97. package/.agents/generated/gemini/skills/context-os/references/project-graph.md +11 -100
  98. package/.agents/generated/gemini/skills/context-os/rules.yaml +8 -135
  99. package/.agents/generated/gemini/skills/engineering-workflow/EXAMPLES.md +15 -50
  100. package/.agents/generated/gemini/skills/engineering-workflow/SKILL.md +10 -11
  101. package/.agents/generated/gemini/skills/engineering-workflow/TROUBLESHOOTING.md +11 -19
  102. package/.agents/generated/gemini/skills/engineering-workflow/VALIDATION.json +115 -4
  103. package/.agents/generated/gemini/skills/engineering-workflow/references/workflow.md +55 -317
  104. package/.agents/generated/gemini/skills/gemini-precision/EXAMPLES.md +33 -53
  105. package/.agents/generated/gemini/skills/gemini-precision/SKILL.md +11 -145
  106. package/.agents/generated/gemini/skills/gemini-precision/TROUBLESHOOTING.md +12 -25
  107. package/.agents/generated/gemini/skills/gemini-precision/VALIDATION.json +115 -4
  108. package/.agents/generated/gemini/skills/gstack-roles/EXAMPLES.md +5 -21
  109. package/.agents/generated/gemini/skills/gstack-roles/SKILL.md +10 -13
  110. package/.agents/generated/gemini/skills/gstack-roles/TROUBLESHOOTING.md +6 -12
  111. package/.agents/generated/gemini/skills/gstack-roles/VALIDATION.json +115 -4
  112. package/.agents/generated/gemini/skills/gstack-roles/references/roles.md +3 -147
  113. package/.agents/generated/gemini/skills/ponytail-mindset/EXAMPLES.md +12 -45
  114. package/.agents/generated/gemini/skills/ponytail-mindset/SKILL.md +10 -14
  115. package/.agents/generated/gemini/skills/ponytail-mindset/TROUBLESHOOTING.md +10 -19
  116. package/.agents/generated/gemini/skills/ponytail-mindset/VALIDATION.json +115 -4
  117. package/.agents/generated/gemini/skills/ponytail-mindset/references/minimalism.md +58 -174
  118. package/.agents/generated/gemini/skills/security/EXAMPLES.md +19 -55
  119. package/.agents/generated/gemini/skills/security/SKILL.md +61 -136
  120. package/.agents/generated/gemini/skills/security/TROUBLESHOOTING.md +13 -19
  121. package/.agents/generated/gemini/skills/security/VALIDATION.json +115 -4
  122. package/.agents/resolver/canonical-resolver.js +34 -21
  123. package/.agents/rules/rule-catalog.js +5 -5
  124. package/.agents/validate.js +9 -2
  125. package/.agents/validation-evidence.js +89 -0
  126. package/README.md +132 -197
  127. package/bin/index.js +1 -1
  128. package/catalog/skills/typescript/SKILL.md +16 -2
  129. package/package.json +90 -89
@@ -1,64 +1,28 @@
1
- # Application Security Examples — Anti-patterns vs ContextOS Standard
1
+ # Security boundary examples
2
2
 
3
- ## Example 1: Timing-Safe Secret Verification
3
+ ## Protected document mutation
4
4
 
5
- ### Anti-pattern: Anti-pattern (Vulnerable to side-channel timing attack)
5
+ Illustrative integration sketch: authenticate through trusted middleware, check
6
+ the tenant role permits the action, and scope the query by document ID and trusted
7
+ tenant ID. Return the established denied/missing response when no accessible
8
+ document matches. Tenant membership alone may not permit deletion.
6
9
 
7
- ```typescript
8
- // BAD: string comparison returns early on the first mismatched byte
9
- export function verifyApiKey(providedKey: string, storedKey: string): boolean {
10
- return providedKey === storedKey; // Vulnerable to timing analysis!
11
- }
12
- ```
13
-
14
- ### Best practice: ContextOS Standard (Constant-time buffer comparison)
10
+ Do not report a working endpoint from a sketch with assumed ORM/middleware.
11
+ Verify another user's or tenant's document is inaccessible before persistence.
15
12
 
16
- ```typescript
17
- // GOOD: crypto.timingSafeEqual executes in constant time
18
- import crypto from 'crypto';
13
+ ## Executable controls
19
14
 
20
- export function verifyApiKey(providedKey: string, storedKey: string): boolean {
21
- const providedBuffer = Buffer.from(providedKey, 'utf8');
22
- const storedBuffer = Buffer.from(storedKey, 'utf8');
15
+ The original runnable HMAC and partner-fetch blocks are in [SKILL.md](SKILL.md).
16
+ The verifier extracts these blocks rather than manually maintained copies.
17
+ Checks cover signatures and URL scheme, credentials, host, port, transport, and
18
+ redirect policy. Egress, DNS, and replay defenses need separate integration tests.
23
19
 
24
- if (providedBuffer.length !== storedBuffer.length) {
25
- return false;
26
- }
20
+ ## Source-checkout scanner
27
21
 
28
- return crypto.timingSafeEqual(providedBuffer, storedBuffer);
29
- }
22
+ ```powershell
23
+ node bin/index.js scan --staged --enforce --placeholders
30
24
  ```
31
25
 
32
- ---
33
-
34
- ## Example 2: Preventing IDOR (Insecure Direct Object Reference)
35
-
36
- ### Anti-pattern: Anti-pattern (Trusting client ID without ownership check)
37
-
38
- ```typescript
39
- // BAD: any authenticated user can delete any other user's document!
40
- app.delete('/api/documents/:id', requireAuth, async (req, res) => {
41
- await prisma.document.delete({ where: { id: req.params.id } });
42
- res.status(204).end();
43
- });
44
- ```
45
-
46
- ### Best practice: ContextOS Standard (Multi-tenant scoped authorization check)
47
-
48
- ```typescript
49
- // GOOD: document deletion is strictly scoped to authenticated user or org
50
- app.delete('/api/documents/:id', requireAuth, async (req, res) => {
51
- const deleted = await prisma.document.deleteMany({
52
- where: {
53
- id: req.params.id,
54
- organizationId: req.user.organizationId, // Tenant isolation
55
- },
56
- });
57
-
58
- if (deleted.count === 0) {
59
- return res.status(404).json({ error: 'Document not found or access denied' });
60
- }
61
-
62
- return res.status(204).end();
63
- });
64
- ```
26
+ This checks staged secrets and placeholders. Supply --scope <file> with the
27
+ actual scope JSON for write boundaries. Inspect unstaged changes separately.
28
+ An empty index does not prove a candidate contains no unsafe code.
@@ -1,184 +1,109 @@
1
1
  ---
2
2
  name: security
3
- description: >
4
- Protect authentication, authorization, sensitive data, untrusted input, external integrations, and agent tool execution.
3
+ description: "Protect authentication, authorization, sensitive data, untrusted input, external integrations, and agent tool execution."
5
4
  ---
6
5
  # security
7
6
 
8
7
  ## Overview
9
8
 
10
- Enforces zero-trust defense-in-depth, OWASP API Top 10 mitigation, cryptographic hardening, sensitive data leakage protection, and AI/LLM safety across all services, endpoints, and agent integrations.
9
+ Protect application and agent trust boundaries. These instructions guide work;
10
+ automated checkers enforce only their explicitly tested scope.
11
11
 
12
12
  ## When to Use
13
13
 
14
- Activate whenever writing authentication, authorization, session management, database queries, cryptography, external API integrations, user input handling, or agent tool calling.
14
+ Authentication, authorization, protected data, inputs, cryptography, external
15
+ requests, payments, destructive actions, and tool execution.
15
16
 
16
17
  ## Rules & Patterns
17
18
 
18
- ### Negative Constraints (What NOT to Do)
19
-
20
- 1. **NEVER use standard string comparison (`===`) for secrets/hashes**: Always use `crypto.timingSafeEqual` to prevent timing attacks.
21
- 2. **NEVER store sensitive JWT access/refresh tokens in `localStorage`**: Store tokens in `httpOnly`, `Secure`, `SameSite=Strict` cookies.
22
- 3. **NEVER return raw database/internal error messages or stack traces to the client**: Return standardized generic error codes (`INTERNAL_SERVER_ERROR`) and log details internally.
23
- 4. **NEVER trust client-provided IDs for authorization without tenant/ownership checks**: Always verify `where: { id, userId: session.userId }` to prevent Broken Object Level Authorization (BOLA/IDOR).
24
- 5. **NEVER disable CSRF protection, CORS allow-all (`*`), or TLS verification (`NODE_TLS_REJECT_UNAUTHORIZED=0`) in production**: Always enforce strict origin whitelists and HTTPS.
25
- 6. **NEVER pass un-sanitized third-party content directly into system prompts or shell execution**: Treat all external data as potentially adversarial.
26
-
27
- ---
28
-
29
- ### OWASP Top 10 for Modern APIs & Full-Stack
30
-
31
- #### 1. Injection (SQL, NoSQL, Command)
32
-
33
- - Always use parameterized queries - never concatenate user input into SQL or shell commands.
34
- - Use ORMs (Prisma, Drizzle, SQLAlchemy) with strict schema validation.
35
- - Validate and sanitize all user input before processing.
36
-
37
- #### 2. Broken Object Level Authorization (BOLA / IDOR)
38
-
39
- - Validate user ownership on EVERY database read, update, or delete:
40
-
41
- ```typescript
42
- // [GOOD] Scoped to authenticated user
43
- const doc = await db.document.findFirst({
44
- where: { id: documentId, tenantId: session.tenantId }
45
- });
46
- ```
47
-
48
- #### 3. Broken Authentication & Session Management
49
-
50
- - Use Argon2id or bcrypt (cost factor ≥ 12) for password hashing.
51
- - Short-lived access tokens (15 min) + secure HTTP-only refresh tokens.
52
- - Enforce rate limiting and brute-force lockouts on auth endpoints.
53
-
54
- #### 4. SSRF (Server-Side Request Forgery)
55
-
56
- - Restrict server-side URL fetching: validate URL scheme (`https:` only), resolve IP, and block private CIDR blocks (`10.0.0.0/8`, `127.0.0.0/8`, `169.254.0.0/16`, `192.168.0.0/16`).
57
-
58
- #### 5. Security Misconfiguration & Headers
59
-
60
- Enforce modern production security headers:
61
-
62
- ```http
63
- Content-Security-Policy: default-src 'self'
64
- X-Content-Type-Options: nosniff
65
- X-Frame-Options: DENY
66
- Strict-Transport-Security: max-age=31536000; includeSubDomains
67
- Referrer-Policy: strict-origin-when-cross-origin
68
- Permissions-Policy: camera=(), microphone=(), geolocation=()
69
- ```
70
-
71
- ---
72
-
73
- ### AI Agent & LLM Security Invariants
74
-
75
- When building AI workflows, tools, or MCP servers:
76
-
77
- 1. **Prompt Injection Defense**:
78
- - Clearly delineate untrusted user/web content using boundary markers (e.g. `<untrusted_content>` tags).
79
- - Never allow untrusted content to override system instructions or tool execution permissions.
80
- 2. **Tool Execution Boundaries**:
81
- - Destructive operations (database drops, file deletions, payment triggers) MUST require explicit user confirmation.
82
- - Restrict file system tools to the workspace root - block directory traversal (`../`).
83
- 3. **Secret Masking & Output Sanitization**:
84
- - Scrub API keys (`sk-...`, `Bearer ...`), tokens, and credentials before writing to agent logs or step summaries.
85
- 4. **Sandbox Execution & Write Isolation (Supply-Chain Defense)**:
86
- - Target code is inspected strictly read-only; never execute target-controlled builds or tests with write access to the repository root.
87
- - Restrict process write boundaries strictly to an isolated temporary `scratch/` directory.
88
- - Enforce zero outbound external network access during security audits to prevent secret exfiltration via malicious scripts or dependencies.
89
- - Promote verified non-secret results to retained `artifacts/` only via trusted parent-side inspection code.
90
-
91
- ---
19
+ - Obtain identity from trusted authentication. Enforce ownership/tenant policy
20
+ before protected reads or mutations; client IDs are not authorization.
21
+ - Validate boundary inputs and reject unknown privilege fields. Parameterize
22
+ queries and encode output for its context; avoid shell interpolation. An ORM
23
+ does not secure interpolated raw SQL.
24
+ - Keep credentials out of source, logs, arguments, and client bundles. Use
25
+ established password/session libraries and cookie, CSRF, origin, and TLS
26
+ policies appropriate to the threat model.
27
+ - Use constant-time primitives for secret comparisons. Surrounding code and
28
+ length handling matter; the whole flow is not necessarily constant-time.
29
+ - External content remains untrusted data. Delimit it and preserve instruction
30
+ and tool authority; markers alone do not prevent prompt injection.
31
+ - Existing authorization carries forward. For destructive actions verify it
32
+ covers the actual target and effect; ask only for missing authority.
33
+ - For untrusted repositories/dependency scripts, inspect before execution,
34
+ isolate writes, withhold credentials, and restrict network access. Ordinary
35
+ authorized development uses relevant project checks. State actual sandbox
36
+ capabilities instead of claiming isolation the tools do not provide.
92
37
 
93
38
  ## Code Examples
94
39
 
40
+ ### Timing-safe webhook signature comparison
95
41
 
96
- ### Timing-Safe Secret Verification
42
+ This runnable block verifies SHA-256 hexadecimal HMAC signatures. Timestamp,
43
+ replay protection, raw-body capture, and provider formats are separate requirements.
97
44
 
45
+ <!-- example: security-hmac -->
98
46
  ```javascript
99
47
  import crypto from 'node:crypto';
100
48
 
101
49
  export function verifyWebhookSignature(payload, signature, secret) {
102
- const hmac = crypto.createHmac('sha256', secret);
103
- const digest = Buffer.from(hmac.update(payload).digest('hex'), 'utf8');
104
- const sigBuffer = Buffer.from(signature, 'utf8');
105
-
106
- if (digest.length !== sigBuffer.length) return false;
107
- return crypto.timingSafeEqual(digest, sigBuffer);
50
+ if (typeof signature !== 'string' || !/^[a-f0-9]{64}$/i.test(signature)) return false;
51
+ const digest = crypto.createHmac('sha256', secret).update(payload).digest();
52
+ const received = Buffer.from(signature, 'hex');
53
+ return digest.length === received.length && crypto.timingSafeEqual(digest, received);
108
54
  }
109
55
  ```
110
56
 
111
- ### SSRF Prevention Requirements (OWASP Compliant)
112
-
113
- Per [OWASP SSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html), naive application-level DNS pre-checks followed by standard `fetch(url)` are fundamentally flawed due to DNS rebinding (TOCTOU) and unvalidated HTTP 3xx redirects.
57
+ ### Restricted partner URL fetch
114
58
 
115
- #### Mandatory Architectural Controls
59
+ Follow the [OWASP SSRF guidance](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html).
60
+ A hostname check followed by ordinary DNS resolution is not a complete SSRF
61
+ boundary. Use a trusted egress transport/proxy that validates IPv4/IPv6 addresses
62
+ at connection time and blocks private, loopback, link-local, and metadata targets,
63
+ including DNS changes. Arbitrary URL fetchers need a separate network policy;
64
+ this sample covers known partner hostnames.
116
65
 
117
- 1. **Network-Layer Defense (Primary)**: For user-supplied arbitrary webhooks or URLs, route all outbound traffic through an isolated egress forward proxy (e.g., Smokescreen, Envoy, Squid) configured with firewall-level IP filters blocking RFC 1918, RFC 6598, link-local (`169.254.169.254`), loopback, and IPv6 local addresses at the socket handshake level.
118
- 2. **Positive Destination Allowlist**: If fetching from known external partners, validate destination hostname against a strict positive allowlist.
119
- 3. **Disable Automatic Redirects**: Always set `redirect: 'error'` or `'manual'`. Never follow HTTP redirects automatically without re-validating the target URL against allowlist rules.
120
- 4. **Protocol & Credential Restrictions**: Enforce `https:` exclusively; reject embedded credentials (`user:pass@host`) and non-standard ports.
66
+ Supply that trusted transport explicitly. This block checks URL syntax, HTTPS,
67
+ credentials, port 443, a trusted hostname allowlist, and redirect policy. There
68
+ is no ambient fetch fallback. Local tests inject a controlled transport; they
69
+ do not verify production egress or DNS behavior.
121
70
 
122
- ```typescript
123
- /**
124
- * Verified Allowlist-based HTTP Client (OWASP SSRF Prevention)
125
- * Enforces HTTPS, strict destination allowlist, and rejects HTTP redirects.
126
- */
127
- export async function fetchFromAllowlist(
128
- urlString: string,
129
- allowedHostnames: ReadonlySet<string>,
130
- options: RequestInit = {}
131
- ): Promise<Response> {
71
+ <!-- example: security-ssrf -->
72
+ ```javascript
73
+ export async function fetchFromAllowlist(urlString, allowedHostnames, options, transport) {
132
74
  const parsed = new URL(urlString);
133
-
134
- // 1. Enforce HTTPS only
135
75
  if (parsed.protocol !== 'https:') {
136
- throw new Error(`SSRF blocked: protocol "${parsed.protocol}" is not permitted; HTTPS required`);
76
+ throw new Error('SSRF blocked: protocol "' + parsed.protocol + '" is not permitted; HTTPS required');
137
77
  }
138
-
139
- // 2. Reject credentials in URL
140
78
  if (parsed.username || parsed.password) {
141
79
  throw new Error('SSRF blocked: URL credentials (user:password@host) are prohibited');
142
80
  }
143
-
144
- // 3. Strict positive destination allowlist (prevents internal network probing)
81
+ if (parsed.port && parsed.port !== '443') throw new Error('SSRF blocked: non-standard port');
145
82
  const normalizedHost = parsed.hostname.toLowerCase();
146
83
  if (!allowedHostnames.has(normalizedHost)) {
147
- throw new Error(`SSRF blocked: destination host "${normalizedHost}" is not in the approved allowlist`);
84
+ throw new Error('SSRF blocked: destination host "' + normalizedHost + '" is not in the approved allowlist');
148
85
  }
149
-
150
- // 4. Disable automatic redirects to prevent redirection to private IPs or metadata endpoints
151
- return fetch(urlString, {
152
- ...options,
153
- redirect: 'error'
154
- });
86
+ if (typeof transport !== 'function') throw new TypeError('Trusted egress transport required');
87
+ return transport(parsed.href, { ...options, redirect: 'error' });
155
88
  }
156
89
  ```
157
90
 
158
- ---
159
-
160
91
  ## Validation Checklist
161
92
 
162
- - [ ] All database queries parameterized or managed by type-safe ORM.
163
- - [ ] BOLA/IDOR prevented: all entity queries scoped by tenant/user id.
164
- - [ ] Cookies set with `HttpOnly`, `Secure`, and `SameSite=Strict` or `Lax`.
165
- - [ ] Passwords hashed with Argon2id / bcrypt.
166
- - [ ] Security headers active in middleware/reverse proxy.
167
- - [ ] No secrets or tokens checked into source control or exposed in logs.
168
-
169
- ---
93
+ - [ ] Allowed and denied identity/tenant cases are checked before data access.
94
+ - [ ] Invalid and unknown inputs never reach protected persistence.
95
+ - [ ] Secrets and production errors preserve their boundaries.
96
+ - [ ] External requests and tool policies are checked at the stated scope.
97
+ - [ ] Commands, results, unrun checks, and limitations are reported.
170
98
 
171
99
  ## Common Mistakes
172
100
 
173
- - **Trusting client-side claims**: Checking role or permissions only on the frontend without server-side validation.
174
- - **Timing attacks on tokens**: Comparing tokens with `token === expectedToken` instead of `timingSafeEqual`.
175
- - **Exposing internal stack traces**: Returning full error objects to client in production.
176
- - **Unvalidated redirects / URLs**: Allowing arbitrary URLs in redirect or fetch parameters.
177
-
178
- ---
101
+ Treating an allowlist as network isolation; comparing role labels instead of
102
+ permissions; passing client payloads into persistence; interpreting a secret scan
103
+ or document validator as a complete application security audit.
179
104
 
180
105
  ## Integration Notes
181
106
 
182
- - Runs in the REVIEW phase for every backend route, auth flow, and database mutation.
183
- - Integrates with `engineering-workflow` during Phase 5 (5-axis quality gate).
184
- - Pairs with `system-design` to mandate secure network boundaries and authorization layers.
107
+ Use engineering-workflow's proportional verification and existing authority.
108
+ The staged scanner needs --placeholders for stubs and --scope with a real scope
109
+ JSON file for write boundaries. Validate does not replace either check.
@@ -1,19 +1,13 @@
1
- # security Troubleshooting & Common Mistakes
2
-
3
- ## 1. Insecure Direct Object References (IDOR)
4
-
5
- - **Symptom**: User A can access User B's invoices by simply modifying the ID in the URL.
6
- - **Root Cause**: Querying by record ID without scoping to the authenticated `user.id` or tenant ID.
7
- - **Fix**: Always query with ownership predicate: `db.invoice.findFirst({ where: { id, userId: auth.user.id } })`.
8
-
9
- ## 2. SQL Injection via Raw String Concatenation
10
-
11
- - **Symptom**: Database compromised through input fields.
12
- - **Root Cause**: String templating in raw queries (`db.query("SELECT * FROM users WHERE id = " + id)`).
13
- - **Fix**: Always use parameterized queries (`$1, $2`) or ORM/query-builder methods.
14
-
15
- ## 3. Storing Sensitive Secrets in Git or Client Bundles
16
-
17
- - **Symptom**: API keys or JWT signing secrets exposed publicly.
18
- - **Root Cause**: Hardcoding secrets in source files or prefixing server secrets with NEXT_PUBLIC_.
19
- - **Fix**: Store all secrets in server-only environment variables; add git-secrets to pre-commit hooks.
1
+ # Security troubleshooting
2
+
3
+ - IDOR/BOLA: verify denied users/tenants before persistence and require the action
4
+ permission, not merely an object ID.
5
+ - SQL/shell interpolation: use parameters or safe argument APIs. Schema checks
6
+ alone do not repair command interpolation.
7
+ - SSRF: DNS prechecks followed by ambient fetch can resolve again; verify the
8
+ connection-time transport policy, A/AAAA results, and redirects.
9
+ - Untrusted scripts: inspect/isolate without credentials; state actual controls.
10
+ - Authority: confirm targets/effects against existing permission instead of
11
+ asking again merely because a phase changed.
12
+ - Green scan: inspect enabled flags, staged files, scope input, and exclusions.
13
+ Results do not prove all security invariants or unstaged code.
@@ -1,12 +1,123 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "x-contextos-evidence-contract": 1,
4
+ "title": "Scoped verification evidence",
5
+ "description": "Report shape and outcome consistency only; command execution and agent behavior require separate evidence.",
3
6
  "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "status",
10
+ "checks",
11
+ "limitations"
12
+ ],
4
13
  "properties": {
5
- "rules_followed": {
6
- "type": "boolean"
14
+ "status": {
15
+ "enum": [
16
+ "verified",
17
+ "partial",
18
+ "not_run"
19
+ ]
20
+ },
21
+ "checks": {
22
+ "type": "array",
23
+ "items": {
24
+ "type": "object",
25
+ "additionalProperties": false,
26
+ "required": [
27
+ "command",
28
+ "exitCode",
29
+ "scope"
30
+ ],
31
+ "properties": {
32
+ "command": {
33
+ "type": "string",
34
+ "minLength": 1
35
+ },
36
+ "exitCode": {
37
+ "type": [
38
+ "integer",
39
+ "null"
40
+ ]
41
+ },
42
+ "scope": {
43
+ "type": "string",
44
+ "minLength": 1
45
+ }
46
+ }
47
+ }
48
+ },
49
+ "limitations": {
50
+ "type": "array",
51
+ "items": {
52
+ "type": "string",
53
+ "minLength": 1
54
+ }
7
55
  }
8
56
  },
9
- "required": [
10
- "rules_followed"
57
+ "allOf": [
58
+ {
59
+ "if": {
60
+ "properties": {
61
+ "status": {
62
+ "const": "verified"
63
+ }
64
+ }
65
+ },
66
+ "then": {
67
+ "properties": {
68
+ "checks": {
69
+ "minItems": 1,
70
+ "items": {
71
+ "properties": {
72
+ "exitCode": {
73
+ "const": 0
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
80
+ },
81
+ {
82
+ "if": {
83
+ "properties": {
84
+ "status": {
85
+ "enum": [
86
+ "partial",
87
+ "not_run"
88
+ ]
89
+ }
90
+ }
91
+ },
92
+ "then": {
93
+ "properties": {
94
+ "limitations": {
95
+ "minItems": 1
96
+ }
97
+ }
98
+ }
99
+ },
100
+ {
101
+ "if": {
102
+ "properties": {
103
+ "status": {
104
+ "const": "not_run"
105
+ }
106
+ }
107
+ },
108
+ "then": {
109
+ "properties": {
110
+ "checks": {
111
+ "items": {
112
+ "properties": {
113
+ "exitCode": {
114
+ "type": "null"
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ }
11
122
  ]
12
123
  }
@@ -59,10 +59,10 @@ const WORKFLOW_TEMPLATES = {
59
59
  summary: 'High-risk feature: auth, migration, public API, security, CI, concurrency',
60
60
  steps: [
61
61
  '1. SPEC: Document explicit in-scope/out-of-scope and acceptance criteria',
62
- '2. APPROVED_PLAN: Atomic tasks (<2h), risk mitigation, and rollback strategy',
62
+ '2. PLAN: Scoped tasks, risk mitigation, and rollback strategy; carry existing authorization forward',
63
63
  '3. ISOLATED_CHANGE: Surgical implementation strictly within planned files',
64
- '4. FULL_VERIFICATION: Global test suite + secret scanner + validator',
65
- '5. INDEPENDENT_REVIEW: Review through security, database, and accessibility lenses',
64
+ '4. VERIFICATION: Behavioral regression checks and relevant integration, security, and project gates',
65
+ '5. REVIEW: Inspect correctness and applicable security, database, or accessibility boundaries; distinguish self-review from peer review',
66
66
  ],
67
67
  },
68
68
  destructive: {
@@ -71,7 +71,7 @@ const WORKFLOW_TEMPLATES = {
71
71
  steps: [
72
72
  '1. EXPLICIT_AUTHORITY: Confirm explicit user authorization and bounds',
73
73
  '2. ROLLBACK_REHEARSAL: Verify snapshot, backup, or rollback transaction log',
74
- '3. GUARDED_CHANGE: Execute modification inside journaled transaction with project lock',
74
+ '3. GUARDED_CHANGE: Use supported transactional project tools or a verified backup and bounded operation',
75
75
  '4. POST_VERIFY: Confirm integrity, state consistency, and absence of data loss',
76
76
  ],
77
77
  },
@@ -391,24 +391,38 @@ function collectWorkspaceEvidence(projectRoot, registry) {
391
391
  /**
392
392
  * Evaluates task risk level according to Milestone 3 spec.
393
393
  */
394
+ // JavaScript \\b/\\w do not delimit Cyrillic words. Use Unicode boundaries for
395
+ // task phrases, including stem suffixes where the language requires them.
396
+ function matchesTaskPhrase(text, pattern) {
397
+ return new RegExp(`(?:^|[^\\p{L}\\p{N}_])(?:${pattern})(?=$|[^\\p{L}\\p{N}_])`, 'iu').test(text);
398
+ }
399
+
400
+ const SECURITY_TASK_PATTERN = String.raw`secur\w*|auth\w*|jwt|passwords?|tokens?|secrets?|permissions?|idor|bola|ssrf|csrf|xss|login|access\s*control|rate\s*limit|безопасн[\p{L}]*|авториз[\p{L}]*|аутентифик[\p{L}]*|парол[\p{L}]*|токен[\p{L}]*|доступ(?:а|у|ом|е|ы|ов)?|прав[\p{L}]*\s+доступ[\p{L}]*`;
401
+
402
+ // Bounded noun phrases allow common articles/adjectives without interpreting
403
+ // "remove unused imports from files" as deletion of the files themselves.
404
+ const DESTRUCTIVE_TASK_PATTERN = [
405
+ String.raw`(?:delete|remove|erase|purge|drop)\s+(?:(?:all|the|a|an|these|those|selected|old|stale|temporary|generated|unused|existing)\s+){0,4}(?:files?|folders?|directory|directories|tables?|databases?|rows?|records?)`,
406
+ String.raw`(?:удал[\p{L}]*|сотри|стереть|стирай|очист[\p{L}]*|уничтож[\p{L}]*)\s+(?:(?:все|всю|весь|всех|эти|эту|этот|стар[\p{L}]*|временн[\p{L}]*|выбранн[\p{L}]*|неиспользуем[\p{L}]*|сгенерированн[\p{L}]*)\s+){0,4}(?:баз[\p{L}]*|таблиц[\p{L}]*|диск[\p{L}]*|файл[\p{L}]*|папк[\p{L}]*)`,
407
+ String.raw`rm\s+-(?:rf|fr)|truncate|destroy|delete\s*from|format\s*disk|git\s+reset\s+--hard|git\s+push\s+(?:--force|-f)|git\s+clean\s+-[a-z]*f[a-z]*`,
408
+ ].join('|');
409
+
394
410
  function evaluateRisk(taskText, files = []) {
395
411
  const reasons = [];
396
412
  const text = (taskText || '').toLowerCase();
397
413
  let value = 'standard';
398
414
 
399
415
  // Destructive operations
400
- if (/\b(drop\s*database|drop\s*table|rm\s*-rf|truncate|destroy|delete\s*from|format\s*disk)\b/i.test(text) ||
401
- /\b(удали\w*\s*(?:базу|таблиц|диск|файл)|очист\w*\s*базу|уничтож\w*)\b/i.test(text)) {
416
+ if (matchesTaskPhrase(text, DESTRUCTIVE_TASK_PATTERN)) {
402
417
  reasons.push({ kind: 'risk_keyword', weight: 100, reason: 'Mentions destructive database or filesystem operation' });
403
418
  value = 'destructive';
404
- } else if (/\b(secur\w*|auth\w*|jwt|password|token|secret|migration|schema|permission|billing|payment|credit\s*card|crypto)\b/i.test(text) ||
405
- /\b(безопасн\w*|авториз\w*|аутентифик\w*|парол\w*|токен\w*|миграц\w*|платеж\w*|платёж\w*|доступ\w*)\b/i.test(text) ||
406
- files.some(f => /\b(auth|security|migration|schema)\b/i.test(f))) {
419
+ } else if (matchesTaskPhrase(text, SECURITY_TASK_PATTERN) ||
420
+ matchesTaskPhrase(text, String.raw`migration|schema|billing|payments?|credit\s*card|crypto|concurr\w*|public\s*api|ci|миграц[\p{L}]*|плат[её]ж[\p{L}]*|конкурент[\p{L}]*|параллельн[\p{L}]*|публичн[\p{L}]*\s*api`) ||
421
+ files.some(f => /(?:auth|security|migrations?|schema|\.github\/workflows)(?:[^a-z]|$)/i.test(f))) {
407
422
  // High-risk operations
408
423
  reasons.push({ kind: 'risk_keyword', weight: 50, reason: 'Touches security, authentication, migration, or sensitive domain' });
409
424
  value = 'high';
410
- } else if ((/\b(typo|readme|doc|comment|format|lint|prettier)\b/i.test(text) ||
411
- /\b(опечатк\w*|документац\w*|комментар\w*|форматирован\w*)\b/i.test(text)) &&
425
+ } else if (matchesTaskPhrase(text, String.raw`typo|readme|docs?|comments?|format|lint|prettier|опечатк[\p{L}]*|документац[\p{L}]*|комментар[\p{L}]*|форматирован[\p{L}]*`) &&
412
426
  files.every(f => /\.(md|txt|json|ya?ml)$/i.test(f))) {
413
427
  // Routine operations
414
428
  reasons.push({ kind: 'risk_keyword', weight: 10, reason: 'Routine documentation or formatting change' });
@@ -437,19 +451,19 @@ function resolvePhaseAndRole(phaseArg, taskText, selectedSkills) {
437
451
  phaseSource = 'explicit';
438
452
  } else {
439
453
  const lower = (taskText || '').toLowerCase();
440
- if (/\b(spec|requirements|user\s*story|критерии|требован)\b/i.test(lower)) {
454
+ if (matchesTaskPhrase(lower, String.raw`spec|requirements|user\s*story|критери[\p{L}]*|требован[\p{L}]*`)) {
441
455
  phaseValue = 'Define';
442
456
  phaseSource = 'prompt';
443
- } else if (/\b(plan|architecture|design\s*the\s*system|спланируй|архитектур)\b/i.test(lower)) {
457
+ } else if (matchesTaskPhrase(lower, String.raw`plan|architecture|design\s*the\s*system|спланир[\p{L}]*|архитектур[\p{L}]*`)) {
444
458
  phaseValue = 'Plan';
445
459
  phaseSource = 'prompt';
446
- } else if (/\b(review|audit|check\s*pr|ревью|проверь\s*код)\b/i.test(lower)) {
460
+ } else if (matchesTaskPhrase(lower, String.raw`review|audit|check\s*pr|ревью|провер[\p{L}]*\s*код[\p{L}]*`)) {
447
461
  phaseValue = 'Review';
448
462
  phaseSource = 'prompt';
449
- } else if (/\b(test|vitest|jest|playwright|tdd|тест)\b/i.test(lower)) {
463
+ } else if (matchesTaskPhrase(lower, String.raw`tests?|vitest|jest|playwright|tdd|тест[\p{L}]*`)) {
450
464
  phaseValue = 'Verify';
451
465
  phaseSource = 'prompt';
452
- } else if (/\b(deploy|release|ship|production|релиз|деплой)\b/i.test(lower)) {
466
+ } else if (matchesTaskPhrase(lower, String.raw`deploy|release|ship|production|релиз[\p{L}]*|деплой[\p{L}]*`)) {
453
467
  phaseValue = 'Ship';
454
468
  phaseSource = 'prompt';
455
469
  }
@@ -747,8 +761,7 @@ class CanonicalResolver {
747
761
  // Exact alias match
748
762
  for (const alias of signals.aliases || []) {
749
763
  const escaped = alias.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
750
- const re = new RegExp(`\\b${escaped}\\b`, 'i');
751
- if (re.test(taskLower)) {
764
+ if (matchesTaskPhrase(taskLower, escaped)) {
752
765
  addEvidence(id, 'alias', WEIGHTS.EXACT_ALIAS, `Exact alias match "${alias}" in task description`);
753
766
  break;
754
767
  }
@@ -757,8 +770,8 @@ class CanonicalResolver {
757
770
  // Keyword matches
758
771
  for (const kw of signals.keywords || []) {
759
772
  const escaped = kw.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
760
- const re = new RegExp(`\\b${escaped}\\b`, 'i');
761
- if (re.test(taskLower)) {
773
+ const pattern = kw.locale === 'ru' ? `${escaped}[\\p{L}]*` : escaped;
774
+ if (matchesTaskPhrase(taskLower, pattern)) {
762
775
  const w = kw.weight || WEIGHTS.TASK_KEYWORD_STRONG;
763
776
  addEvidence(id, 'keyword', w, `Task keyword "${kw.value}" (+${w})`);
764
777
  }
@@ -788,7 +801,7 @@ class CanonicalResolver {
788
801
  { id: 'react', re: /\b(react|reactjs|useOptimistic)\b|компонент|хук|модал\w*/i, w: 40, kw: 'react' },
789
802
  { id: 'typescript', re: /\b(typescript|type-?safe|generics?|tsconfig)\b|тайпскрипт|типизац/i, w: 40, kw: 'typescript' },
790
803
  { id: 'ui-ux-pro', re: /\b(ui|ux|tailwind|styling)\b|дизайн|верстк|макет|интерфейс|модал\w*/i, w: 35, kw: 'ui/ux' },
791
- { id: 'security', re: /\b(security|auth|jwt|login|csrf|xss|rate\s*limit)\b|авториз|аутентифик|парол|безопасност/i, w: 40, kw: 'security' },
804
+ { id: 'security', re: { test: text => matchesTaskPhrase(text, SECURITY_TASK_PATTERN) }, w: 40, kw: 'security' },
792
805
  { id: 'database', re: /\b(database|sql|postgres|prisma|drizzle|migration|orm)\b|баз.*данн|миграц|таблиц/i, w: 40, kw: 'database' },
793
806
  { id: 'testing', re: /\b(vitest|jest|playwright|tdd|bdd|e2e)\b|тестирован|покрыти|юнит|тест/i, w: 40, kw: 'testing' },
794
807
  { id: 'performance', re: /\b(performance|latency|lcp|cls|inp|core\s*web\s*vitals)\b|производительн|ускор|быстр|throughput/i, w: 40, kw: 'performance' },