@ryuenn3123/agentic-senior-core 5.8.26 → 5.9.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.
@@ -0,0 +1,26 @@
1
+ {
2
+ "description": "Regex patterns for recurring security anti-patterns",
3
+ "patterns": [
4
+ {
5
+ "id": "insecure-redirect",
6
+ "regex": "location\\.href\\s*=\\s*(?!['\"`])([^;\\n]+)",
7
+ "message": "Unvalidated redirect target assigned to location.href. Ensure the variable is sanitized or use a safe routing method."
8
+ },
9
+ {
10
+ "id": "timing-unsafe-compare",
11
+ "regex": "(password|secret|token|key)\\s*(===|!==|==|!=)",
12
+ "message": "Non-timing-safe string comparison on a secret variable. Use crypto.timingSafeEqual instead."
13
+ },
14
+ {
15
+ "id": "user-input-http",
16
+ "regex": "(axios|fetch|got|superagent)\\s*\\(\\s*.*?(req\\.(query|body|params)|process\\.env)",
17
+ "message": "Potentially unsafe input passed directly into an HTTP client. Validate and sanitize URL parameters first."
18
+ }
19
+ ],
20
+ "fileSpecific": {
21
+ "Dockerfile": {
22
+ "require": "^(?=.*\\nUSER\\s).*$",
23
+ "message": "Missing USER instruction in Dockerfile. The container will run as root by default."
24
+ }
25
+ }
26
+ }
@@ -29,6 +29,14 @@ try {
29
29
  }
30
30
  } catch (_) {}
31
31
 
32
+ let SECURITY_PATTERNS = { patterns: [], fileSpecific: {} };
33
+ try {
34
+ const secPath = path.join(__dirname, 'lib', 'known-security-patterns.json');
35
+ if (fs.existsSync(secPath)) {
36
+ SECURITY_PATTERNS = JSON.parse(fs.readFileSync(secPath, 'utf8'));
37
+ }
38
+ } catch (_) {}
39
+
32
40
  const SOURCE_EXTENSIONS = new Set([
33
41
  'js', 'ts', 'mjs', 'cjs', 'jsx', 'tsx',
34
42
  'py', 'rb', 'go', 'rs', 'java', 'kt', 'swift', 'cs',
@@ -145,7 +153,6 @@ function processSingleEdit(toolName, toolInput, emitFn, skipArray) {
145
153
  checkDependencyAddition(toolName, toolInput, findings);
146
154
  }
147
155
 
148
- const ext = path.extname(filePath).slice(1);
149
156
  if (SOURCE_EXTENSIONS.has(ext)) {
150
157
  if (toolName === 'Edit') {
151
158
  checkLocDelta(toolInput, filePath, findings);
@@ -154,6 +161,11 @@ function processSingleEdit(toolName, toolInput, emitFn, skipArray) {
154
161
  }
155
162
  }
156
163
 
164
+ checkSecurityPatterns(toolName, toolInput, filePath, findings);
165
+ if (ext === 'js' || ext === 'ts' || ext === 'jsx' || ext === 'tsx' || ext === 'mjs' || ext === 'cjs') {
166
+ checkLinter(filePath, findings);
167
+ }
168
+
157
169
  checkLivingDocNudge(filePath, findings);
158
170
 
159
171
  if (ext !== 'md') {
@@ -238,6 +250,58 @@ function checkNewFileSize(toolInput, filePath, findings) {
238
250
  }
239
251
  }
240
252
 
253
+ function checkSecurityPatterns(toolName, toolInput, filePath, findings) {
254
+ var target = toolName === 'Edit' ? (toolInput.new_string || '') : (toolInput.content || '');
255
+ if (!target) return;
256
+
257
+ if (SECURITY_PATTERNS.patterns) {
258
+ SECURITY_PATTERNS.patterns.forEach(function (p) {
259
+ try {
260
+ var regex = new RegExp(p.regex, 'ig');
261
+ if (regex.test(target)) {
262
+ findings.push('[ASC Security] ' + p.message);
263
+ }
264
+ } catch (_) {}
265
+ });
266
+ }
267
+
268
+ var basename = path.basename(filePath);
269
+ if (SECURITY_PATTERNS.fileSpecific && SECURITY_PATTERNS.fileSpecific[basename]) {
270
+ var spec = SECURITY_PATTERNS.fileSpecific[basename];
271
+ try {
272
+ var regex = new RegExp(spec.require, 'g');
273
+ if (target.trim().length > 0 && !regex.test(target)) {
274
+ findings.push('[ASC Security] ' + spec.message);
275
+ }
276
+ } catch (_) {}
277
+ }
278
+ }
279
+
280
+ function checkLinter(filePath, findings) {
281
+ try {
282
+ var cwd = process.cwd();
283
+ var hasEslint = fs.existsSync(path.join(cwd, '.eslintrc.json')) ||
284
+ fs.existsSync(path.join(cwd, '.eslintrc.js')) ||
285
+ fs.existsSync(path.join(cwd, 'eslint.config.js')) ||
286
+ (fs.existsSync(path.join(cwd, 'package.json')) && fs.readFileSync(path.join(cwd, 'package.json'), 'utf8').includes('eslintConfig'));
287
+
288
+ if (hasEslint) {
289
+ var execSync = require('child_process').execSync;
290
+ execSync('npx eslint "' + filePath + '" --format json', { cwd: cwd, stdio: 'pipe' });
291
+ }
292
+ } catch (error) {
293
+ if (error.stdout) {
294
+ try {
295
+ var out = JSON.parse(error.stdout.toString());
296
+ if (Array.isArray(out) && out.length > 0 && out[0].messages && out[0].messages.length > 0) {
297
+ var firstErr = out[0].messages[0];
298
+ findings.push('[ASC Linter] ' + firstErr.message + ' at line ' + firstErr.line + '.');
299
+ }
300
+ } catch (_) {}
301
+ }
302
+ }
303
+ }
304
+
241
305
  function checkLivingDocNudge(filePath, findings) {
242
306
  var lower = filePath.toLowerCase();
243
307
  if (lower.includes('schema') || lower.includes('migration') || lower.includes('model') || lower.includes('prisma')) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
- "version": "5.8.26",
3
+ "version": "5.9.0",
4
4
  "description": "Universal AI coding rules. Write code like a staff engineer.",
5
5
  "contextFileName": "rules/agentic-senior-core.md",
6
6
  "rules": [
@@ -38,11 +38,12 @@ Format:
38
38
 
39
39
  1. On approval of Phase 1, update `workflow-gate.json` phase to `plan`.
40
40
  2. Ensure `docs/PRD.md` or feature brief exists.
41
- 3. Create a numbered, step-by-step implementation plan with specific files, functions, and line references.
42
- 4. Include a "Don't Build" list from the research phase.
43
- 5. **Callout: Plan-Reading Illusion.** Ask the user to explicitly verify the plan against the codebase, not just skim it.
44
- 6. Output the plan.
45
- 7. **STOP and wait for user approval.** Do not implement.
41
+ 3. Check if `.github/workflows/asc-quality-gate.yml` exists. If not, include scaffolding it in your plan (must run linter, type-check, and audit) and remind the user to enable Branch Protection.
42
+ 4. Create a numbered, step-by-step implementation plan with specific files, functions, and line references.
43
+ 5. Include a "Don't Build" list from the research phase.
44
+ 6. **Callout: Plan-Reading Illusion.** Ask the user to explicitly verify the plan against the codebase, not just skim it.
45
+ 7. Output the plan.
46
+ 8. **STOP and wait for user approval.** Do not implement.
46
47
 
47
48
  ## Phase 3: Implement
48
49
 
@@ -53,6 +53,7 @@ Format:
53
53
  2. Run Anti Context-Blindness check: verify entities/tables mentioned in `Schema.md` or `Architecture.md` align with proposed code targets.
54
54
  3. Build against the approved specs. Apply the ASC decision ladder on every file.
55
55
  4. Run the decision ladder: does this need to exist? Does stdlib cover it? One function or full module?
56
+ 5. Generate a `.github/workflows/asc-quality-gate.yml` file that runs linter, type-check, and dependency audit on `push` and `pull_request`. Remind the user to enable Branch Protection in GitHub (require status checks to pass) to enforce this gate globally.
56
57
 
57
58
  ## Phase 4: Validate
58
59
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-senior-core",
3
- "version": "5.8.26",
3
+ "version": "5.9.0",
4
4
  "description": "Universal AI coding rules. Write code like a staff engineer.",
5
5
  "author": "fatidaprilian",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuenn3123/agentic-senior-core",
3
- "version": "5.8.26",
3
+ "version": "5.9.0",
4
4
  "type": "module",
5
5
  "description": "Agentic Senior Core: Universal AI coding rules and workflows. Write code like a staff engineer, not a junior.",
6
6
  "bin": {
package/plugin.yaml CHANGED
@@ -1,5 +1,5 @@
1
1
  name: agentic-senior-core
2
- version: 5.8.26
2
+ version: 5.9.0
3
3
  description: Universal AI coding rules. Write code like a staff engineer.
4
4
  author: fatidaprilian
5
5
  provides_hooks: