Skip to content

Conversation

@frontegg-david
Copy link
Contributor

@frontegg-david frontegg-david commented Nov 23, 2025

Summary by CodeRabbit

  • New Features

    • Added a new ast-guard library with a public validator API, error types, configurable security presets (strict/secure/standard/permissive) and several built-in validation rules for JS/TS safety.
  • Documentation

    • Added a development guide, library README, security audit, penetration-test summary and changelog.
  • Tests

    • Added extensive unit and security test suites covering presets, rules, advanced attack vectors and error handling.
  • Chores

    • Added project configs for TypeScript, testing, linting, packaging and publishing.

✏️ Tip: You can customize this high-level summary in your review settings.

Add comprehensive AST-based JavaScript validation library with:

Features:
- 7 validation rules (DisallowedIdentifier, NoEval, NoAsync, ForbiddenLoop, etc.)
- 4-tier security preset system (STRICT > SECURE > STANDARD > PERMISSIVE)
- Custom error classes (RuleConfigurationError, ConfigurationError, etc.)
- Extensible rule plugin architecture
- TypeScript with strict mode

Testing & Quality:
- 188 tests with 95.11% code coverage
- Advanced security testing with 24 attack vector scenarios
- Comprehensive error handling tests

Documentation:
- Complete API documentation with examples
- SECURITY-AUDIT.md documenting 67 blocked attack vectors
- Known limitations and defense-in-depth strategies
- CLAUDE.md for monorepo development guidelines

Security Model:
- STRICT preset: Bank-grade security (90+ dangerous identifiers blocked)
- SECURE preset: High security with flexibility
- STANDARD preset: Balanced security for general use
- PERMISSIVE preset: Minimal restrictions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 23, 2025

Walkthrough

Adds a new ast-guard library under libs/ast-guard: validator, interfaces, errors, seven built-in validation rules, preset factories (strict/secure/standard/permissive), extensive tests, ESLint/Jest/TS/Nx configs, package metadata, changelog, security audit, and documentation. No changes to other runtime projects.

Changes

Cohort / File(s) Summary
Documentation & Audit
CLAUDE.md, libs/ast-guard/README.md, libs/ast-guard/CHANGELOG.md, libs/ast-guard/PENETRATION-TEST-SUMMARY.md, libs/ast-guard/SECURITY-AUDIT.md
New documentation and audit artifacts: development guide, library README, changelog (v1.0.0 notes), penetration-test summary, and bank‑level security audit.
Project & Tooling Config
libs/ast-guard/package.json, libs/ast-guard/project.json, libs/ast-guard/tsconfig*.json, libs/ast-guard/eslint.config.mjs, libs/ast-guard/jest.config.ts, libs/ast-guard/jest.setup.ts
New package manifest, Nx project config with build/publish targets, TypeScript build/test configs, ESLint project config, and Jest configuration/setup.
Public API Barrel
libs/ast-guard/src/index.ts
New public entry aggregating and re-exporting validator, interfaces, errors, built-in rules, rule option types, and presets.
Core Validator & Types
libs/ast-guard/src/validator.ts, libs/ast-guard/src/interfaces.ts, libs/ast-guard/src/errors.ts
Adds JSAstValidator (rule registry, parsing/validation flow, early-exit, stats), validation interfaces/enums, and a typed error class hierarchy.
Built-in Rules & Barrel
libs/ast-guard/src/rules/*, libs/ast-guard/src/rules/index.ts
Adds seven validation rules and a rules barrel: DisallowedIdentifierRule, ForbiddenLoopRule, RequiredFunctionCallRule, UnreachableCodeRule, CallArgumentValidationRule, NoEvalRule, NoAsyncRule.
Preset System
libs/ast-guard/src/presets/*
Adds PresetOptions and PresetLevel types, four preset factory implementations (strict/secure/standard/permissive), and a createPreset/Presets facade to compose rule sets.
Tests
libs/ast-guard/src/__tests__/*
Extensive test suites covering validator lifecycle, error classes, each rule, presets, security scenarios, advanced attack-vector tests, and penetration/security validation examples.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant JSAstValidator
    participant Acorn
    participant Rule as ValidationRule
    participant Result

    User->>JSAstValidator: validate(source, config)
    JSAstValidator->>Acorn: parse(source)
    Acorn-->>JSAstValidator: AST or parseError
    JSAstValidator->>JSAstValidator: getEnabledRules(config)
    loop each enabled Rule
      JSAstValidator->>Rule: validate(context)
      alt rule reports issue
        Rule->>JSAstValidator: report(issue)
        JSAstValidator->>Result: collect issue
        alt stopOnFirstError or maxIssues reached
            JSAstValidator->>JSAstValidator: short-circuit (StopValidationError)
        end
      else
        Rule-->>JSAstValidator: no issues
      end
    end
    JSAstValidator->>Result: assemble ValidationResult & stats
    Result-->>User: return result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Pay special attention to:
    • libs/ast-guard/src/validator.ts: parsing error handling, rule enablement precedence, stopOnFirstError/maxIssues short-circuiting, async behavior, and stats calculation.
    • libs/ast-guard/src/rules/call-argument-validation.rule.ts and required-function-call.rule.ts: argument-type inference, member vs identifier call matching, and error data payloads.
    • libs/ast-guard/src/rules/unreachable-code.rule.ts: terminal-statement detection across nested branches and edge cases.
    • presets modules: correct option merging, defaults, and deterministic rule ordering.
    • tests: ensure expectations align with documented limitations and messages.

Possibly related PRs

  • updated libs creation #10 — touches publish/build flow and strip-dist usage referenced by libs/ast-guard/project.json publish target; likely related to packaging/publish targets.

Poem

🐇 I hop through ASTs with careful eyes,

Blocking sneaky calls in subtle disguise,
From STRICT down to PERMISSIVE I stitch each rule,
Tests and presets sharpen my vigilant tool,
A tidy rabbit guardian — small, brave, and cool.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: add ast-guard lib an AST validator' clearly describes the main change—adding a new AST Guard library for validating JavaScript/TypeScript AST. It accurately reflects the primary objective.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/ast-guard

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f1ca51b and 2226544.

📒 Files selected for processing (1)
  • libs/ast-guard/src/rules/unreachable-code.rule.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/ast-guard/src/rules/unreachable-code.rule.ts

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🧹 Nitpick comments (19)
libs/ast-guard/README.md (1)

13-20: Clarify “Zero Dependencies” wording for accuracy

The bullet says “Zero Dependencies” but immediately lists acorn and acorn-walk as dependencies. This can confuse users scanning for transitive footprint.

Consider rephrasing to something like:

Minimal Dependencies: Only acorn and acorn-walk as runtime dependencies

to avoid contradicting the heading.

libs/ast-guard/PENETRATION-TEST-SUMMARY.md (1)

226-242: Add a language identifier to this fenced code block

markdownlint (MD040) flags the defense‑in‑depth “Layer 1/2/3/4” block because it uses a bare triple‑backtick fence without a language.

Consider adding a language hint, e.g.:

```text
Layer 1: AST Guard (Static Analysis)
...

to satisfy linting and improve rendering consistency.

</blockquote></details>
<details>
<summary>libs/ast-guard/SECURITY-AUDIT.md (1)</summary><blockquote>

`463-488`: **Add language to fenced “Recommended Security Stack” block**

The ASCII‑diagram block under “Recommended Security Stack (Defense in Depth)” uses a bare triple‑backtick fence, which triggers MD040.

You can mark it as plain text:

```markdown
```text
┌─────────────────────────────────────┐
│  1. AST Guard (STRICT preset)      │
...

to keep markdownlint happy and make the intent clearer in rendered views.

</blockquote></details>
<details>
<summary>libs/ast-guard/src/rules/required-function-call.rule.ts (1)</summary><blockquote>

`25-105`: **Rule implementation looks solid; consider tightening MemberExpression handling**

Core behavior (constructor guard, counting logic, min/max reporting, and error shapes) looks correct and consistent with the rest of the framework.

Two edge cases you may want to refine:

- In the `MemberExpression` branch you currently count any call where `callee.property.type === 'Identifier'`. That will include `obj[callTool]()` as a call to `"callTool"` but not `obj["callTool"]()`. If you only want plain method syntax (`obj.callTool()`), you could restrict to non‑computed properties; if you also want `obj["callTool"]()` to count, you’d need a separate `Literal` branch.

  ```diff
-        // Handle member calls: obj.funcName()
-        if (callee.type === 'MemberExpression' && callee.property.type === 'Identifier') {
-          const name = callee.property.name;
+        // Handle member calls: obj.funcName()
+        if (
+          callee.type === 'MemberExpression' &&
+          !callee.computed &&
+          callee.property.type === 'Identifier'
+        ) {
+          const name = callee.property.name;
           if (callCounts.has(name)) {
             callCounts.set(name, callCounts.get(name)! + 1);
           }
         }
  • If you consider configurations with minCalls > maxCalls invalid, you might also add a small sanity check in the constructor to fail fast instead of allowing contradictory thresholds.

These are non‑blocking; current behavior is coherent as long as the above semantics are intentional.

libs/ast-guard/package.json (1)

1-48: Verify that main/types/exports match the actual published layout

This manifest looks generally good, but a couple of details are worth double‑checking before publishing:

  • main/types/exports all assume ./dist/src/index.{js,d.ts} relative to the package root. Make sure the published package root and your build output actually produce that structure (e.g., if you publish from dist/libs/ast-guard, you should confirm that dist/libs/ast-guard/dist/src/index.js really exists).

  • The development condition currently points to ./src/index.ts. If any consumer tooling enables the development condition but does not understand TypeScript in node_modules, this can fail at runtime/bundle time. If you don’t explicitly need to ship TS source to consumers, consider pointing development at the built JS (same as import/default) instead.

These are packaging/interop concerns rather than functional bugs, but worth validating now to avoid broken entry points after publish.

libs/ast-guard/tsconfig.lib.json (1)

1-12: Lib tsconfig looks solid; decorator flags are optional.

The config matches typical Nx-style library settings (shared base, dist/out-tsc, declarations, test files excluded). If this lib never uses decorators, you could drop emitDecoratorMetadata and experimentalDecorators to keep compiler options minimal, but it’s fine as-is.

libs/ast-guard/src/rules/index.ts (1)

1-11: Rule barrel cleanly defines the built-in rule surface; align docs accordingly.

The exports line up with the rules used by presets and tests, which is good for a single public entry point. Since this is part of the SDK API, just make sure the docs under docs/draft/docs/** enumerate these rule names so consumers know what’s available.

libs/ast-guard/src/__tests__/presets.spec.ts (1)

209-220: Inline comment about SECURE preset’s disallowed identifiers is slightly misleading.

The comment says “constructor and proto are not in the disallowed list for secure”, but from secure.preset.ts only constructor is allowed—__proto__ is actually disallowed there. The test itself only checks constructor, so it’s correct; updating the comment to mention just constructor would avoid confusion:

-      // constructor and __proto__ are not in the disallowed list for secure
+      // constructor is not in the disallowed list for secure
libs/ast-guard/src/rules/no-eval.rule.ts (1)

18-52: Broaden detection to member-access and indirect eval patterns

The current logic correctly flags direct eval(...), new Function(...), and setTimeout/setInterval with a string literal first argument, which is a solid baseline. However, it will miss several common dynamic-code patterns:

  • Member access: window.eval(...), globalThis.setTimeout('...'), or this.setInterval('...') (callee is a MemberExpression, not an Identifier).
  • Indirect eval: (0, eval)('code') where the callee is a SequenceExpression.
  • Non-Literal string code, e.g. simple template literals that still represent static strings.

If you want this rule to act as a true “no dynamic execution” guard, consider:

  • Treating MemberExpression callees with a property named eval, setTimeout, or setInterval as violations.
  • Optionally handling obvious static TemplateLiteral cases as equivalent to string Literals.
  • Adding tests in __tests__ that lock in these behaviors.

This would materially improve security coverage without changing the public API surface.

Also applies to: 55-70

libs/ast-guard/src/rules/disallowed-identifier.rule.ts (1)

31-42: Clarify identifier contexts you intend to block (and optionally precompute the set)

Functionally this works, but a couple of behavioral nuances are worth calling out:

  • Matching on every Identifier node means you’ll flag cases like object keys, property accesses, and parameter names, e.g. { eval: 1 }, obj.eval, or function eval() {}. If the intent is specifically to block usage of certain globals (like process or require), you may want to narrow matches to particular contexts (e.g., identifier references, not property keys/params) and add tests to lock that behavior in.
  • The disallowed list never changes per rule instance, so you could precompute the Set once in the constructor and reuse it in validate to avoid reallocation on every run. This is a micro-optimization but easy to apply.

If the current behavior is intentional (block any appearance of those identifiers), then just documenting that explicitly in the rule’s docs would be enough.

Also applies to: 44-60

libs/ast-guard/eslint.config.mjs (1)

1-37: ESLint flat config is reasonable; consider simplifying the JSON parser import

Extending the root eslint.config.mjs and adding TS/JSON overrides plus ignore patterns looks good.

For the JSON parser, you currently use:

languageOptions: {
  parser: await import('jsonc-eslint-parser'),
},

This relies on top‑level await and on ESLint accepting the dynamic import namespace as a parser object. To reduce surprises, you might prefer one of:

  • A static ESM import:

    import jsoncParser from 'jsonc-eslint-parser';
    
    // ...
    languageOptions: {
      parser: jsoncParser,
    },
  • Or, if you keep the dynamic import, explicitly use .default to make the intent clear:

    languageOptions: {
      parser: (await import('jsonc-eslint-parser')).default,
    },

Also just confirm your Node/ESLint toolchain is configured to support top‑level await in flat configs.

libs/ast-guard/src/__tests__/advanced-attack-vectors.spec.ts (1)

481-507: Minor comment mismatch in multi‑vector attack test

In the “Comprehensive Multi‑Vector Attack” test, the comment says:

// BLOCKED: Multiple identifiers caught ('e', 'constructor', 'process', 'Function')

Under the strict preset, constructor, process, and Function are indeed in the disallowed list, but plain 'e' is not. The test only asserts issues.length > 0, so behavior is fine; the comment is just slightly misleading.

You may want to update the comment to only list identifiers that are actually disallowed by default (or explicitly configured) to avoid confusion for future readers.

libs/ast-guard/src/presets/strict.preset.ts (1)

58-175: Factor out shared disallowed identifier sets between presets

The strict preset’s disallowedIdentifiers array is long and largely overlaps with the secure preset’s list. Maintaining two separate hard‑coded lists will be error‑prone when you inevitably adjust what counts as “dangerous”.

Consider extracting shared constants or small helpers, e.g.:

  • BASE_DANGEROUS_IDENTIFIERS
  • STRICT_ONLY_IDENTIFIERS
  • SECURE_ONLY_IDENTIFIERS

and compose the preset lists from those, possibly adding options.additionalDisallowedIdentifiers on top. This keeps behavior between presets intentionally different while making changes auditable and less likely to drift.

libs/ast-guard/src/rules/no-async.rule.ts (1)

7-14: NoAsyncRule logic is correct; consider refining message customization

The traversal and allow flags behave as expected (covering async declarations/expressions/arrows and await), and align with the tests.

One minor ergonomic point: a single message option is reused for all violation types (NO_ASYNC and NO_AWAIT). If consumers ever want different wording for async functions vs await, you might later extend the options to support more granular messages (e.g., asyncMessage, awaitMessage) while keeping the current message as a default fallback.

Also applies to: 21-26, 29-93

libs/ast-guard/src/presets/index.ts (1)

13-30: Preset factory and Presets helper provide a clean public API

createPreset cleanly switches on PresetLevel and fails fast with ConfigurationError for unknown values, and the Presets object offers a convenient, typed entry point for consumers. The extra re-exports plus local imports for the same factories are slightly redundant but not problematic.

Also applies to: 31-65, 86-97

libs/ast-guard/src/rules/unreachable-code.rule.ts (1)

4-11: Doc comment overstates current detection scope

The rule comment mentions “code after infinite loops” and “dead branches in conditionals”, but the implementation only handles:

  • Statements following terminal statements (return/throw/break/continue) in blocks.
  • Simple if constructs where both branches are terminal.

There is no current detection for infinite loops or general dead branches. Consider tightening the description to match implemented behavior, or extending the implementation to actually cover those cases.

libs/ast-guard/src/__tests__/advanced-security.spec.ts (2)

12-52: Align test names with current expectations (or mark as TODO)

Several specs under “Property Access Obfuscation Attacks” are named as if the guard already blocks the attacks (e.g., “should block computed property access to constructor”), but the assertions explicitly expect result.valid to be true and comments explain this as a current limitation.

That can be misleading to someone scanning test names only. Consider either:

  • Renaming these tests to reflect that they document known gaps (e.g., it('documents current limitation for computed property access to constructor', ...)), or
  • Adding a clear TODO marker in the titles so it’s obvious these are aspirational.

680-682: Avoid console.log in tests to keep CI output clean

The “Comprehensive Bank-Level Lockdown Test” logs validation issues on failure. This can clutter CI output and hide more relevant Jest diagnostics. It’s usually better to rely on Jest’s assertion messages, or only log conditionally when debugging locally (e.g., behind an env flag).

libs/ast-guard/src/rules/call-argument-validation.rule.ts (1)

176-200: Tighten getArgumentType to better match supported expectedTypes

getArgumentType has a few inconsistencies with the advertised expectedTypes:

  • For Literal nodes:
    • Array.isArray(node.value) will never be true for acorn ASTs; arrays are represented as ArrayExpression, so this branch is effectively dead.
    • BigInt literals will produce typeof node.value === 'bigint', but 'bigint' is not in the allowed expectedTypes union, so any BigInt argument will always be reported as a type mismatch.
  • Only null literals are classified as 'literal'; other primitive literals ('foo', 42, true) are reported as 'string', 'number', 'boolean' respectively, so expectedTypes: ['literal'] doesn’t behave as a general “any literal” matcher.
  • Node kinds like TemplateLiteral (for string-like arguments) are reported as 'unknown', which may be surprising if a caller expects template strings to satisfy 'string'.

To make behavior more predictable, consider:

  • Removing the Array.isArray(node.value) branch and relying on ArrayExpression for 'array'.
  • Deciding what expectedTypes: 'literal' should mean (e.g., “any literal”, or only null), and aligning getArgumentType accordingly.
  • Mapping TemplateLiteral (and possibly tagged templates) to 'string', and normalizing BigInt literals either to 'literal' or to a dedicated 'bigint' type that can be configured.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 11df6bf and 402f50d.

📒 Files selected for processing (38)
  • CLAUDE.md (1 hunks)
  • libs/ast-guard/CHANGELOG.md (1 hunks)
  • libs/ast-guard/PENETRATION-TEST-SUMMARY.md (1 hunks)
  • libs/ast-guard/README.md (1 hunks)
  • libs/ast-guard/SECURITY-AUDIT.md (1 hunks)
  • libs/ast-guard/eslint.config.mjs (1 hunks)
  • libs/ast-guard/jest.config.ts (1 hunks)
  • libs/ast-guard/jest.setup.ts (1 hunks)
  • libs/ast-guard/package.json (1 hunks)
  • libs/ast-guard/project.json (1 hunks)
  • libs/ast-guard/src/__tests__/advanced-attack-vectors.spec.ts (1 hunks)
  • libs/ast-guard/src/__tests__/advanced-security.spec.ts (1 hunks)
  • libs/ast-guard/src/__tests__/errors.spec.ts (1 hunks)
  • libs/ast-guard/src/__tests__/presets.spec.ts (1 hunks)
  • libs/ast-guard/src/__tests__/rules.spec.ts (1 hunks)
  • libs/ast-guard/src/__tests__/security.spec.ts (1 hunks)
  • libs/ast-guard/src/__tests__/validator.spec.ts (1 hunks)
  • libs/ast-guard/src/errors.ts (1 hunks)
  • libs/ast-guard/src/index.ts (1 hunks)
  • libs/ast-guard/src/interfaces.ts (1 hunks)
  • libs/ast-guard/src/presets/index.ts (1 hunks)
  • libs/ast-guard/src/presets/permissive.preset.ts (1 hunks)
  • libs/ast-guard/src/presets/secure.preset.ts (1 hunks)
  • libs/ast-guard/src/presets/standard.preset.ts (1 hunks)
  • libs/ast-guard/src/presets/strict.preset.ts (1 hunks)
  • libs/ast-guard/src/presets/types.ts (1 hunks)
  • libs/ast-guard/src/rules/call-argument-validation.rule.ts (1 hunks)
  • libs/ast-guard/src/rules/disallowed-identifier.rule.ts (1 hunks)
  • libs/ast-guard/src/rules/forbidden-loop.rule.ts (1 hunks)
  • libs/ast-guard/src/rules/index.ts (1 hunks)
  • libs/ast-guard/src/rules/no-async.rule.ts (1 hunks)
  • libs/ast-guard/src/rules/no-eval.rule.ts (1 hunks)
  • libs/ast-guard/src/rules/required-function-call.rule.ts (1 hunks)
  • libs/ast-guard/src/rules/unreachable-code.rule.ts (1 hunks)
  • libs/ast-guard/src/validator.ts (1 hunks)
  • libs/ast-guard/tsconfig.json (1 hunks)
  • libs/ast-guard/tsconfig.lib.json (1 hunks)
  • libs/ast-guard/tsconfig.spec.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
libs/**

⚙️ CodeRabbit configuration file

libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).

Files:

  • libs/ast-guard/README.md
  • libs/ast-guard/package.json
  • libs/ast-guard/src/rules/no-eval.rule.ts
  • libs/ast-guard/CHANGELOG.md
  • libs/ast-guard/src/rules/forbidden-loop.rule.ts
  • libs/ast-guard/jest.config.ts
  • libs/ast-guard/src/rules/disallowed-identifier.rule.ts
  • libs/ast-guard/src/rules/required-function-call.rule.ts
  • libs/ast-guard/src/presets/strict.preset.ts
  • libs/ast-guard/src/__tests__/advanced-security.spec.ts
  • libs/ast-guard/src/__tests__/rules.spec.ts
  • libs/ast-guard/src/index.ts
  • libs/ast-guard/tsconfig.lib.json
  • libs/ast-guard/src/presets/secure.preset.ts
  • libs/ast-guard/src/rules/call-argument-validation.rule.ts
  • libs/ast-guard/src/presets/types.ts
  • libs/ast-guard/src/presets/permissive.preset.ts
  • libs/ast-guard/src/errors.ts
  • libs/ast-guard/src/rules/no-async.rule.ts
  • libs/ast-guard/src/__tests__/errors.spec.ts
  • libs/ast-guard/src/presets/index.ts
  • libs/ast-guard/jest.setup.ts
  • libs/ast-guard/src/interfaces.ts
  • libs/ast-guard/src/rules/unreachable-code.rule.ts
  • libs/ast-guard/src/validator.ts
  • libs/ast-guard/src/__tests__/advanced-attack-vectors.spec.ts
  • libs/ast-guard/src/presets/standard.preset.ts
  • libs/ast-guard/project.json
  • libs/ast-guard/PENETRATION-TEST-SUMMARY.md
  • libs/ast-guard/src/rules/index.ts
  • libs/ast-guard/tsconfig.json
  • libs/ast-guard/tsconfig.spec.json
  • libs/ast-guard/src/__tests__/security.spec.ts
  • libs/ast-guard/src/__tests__/validator.spec.ts
  • libs/ast-guard/eslint.config.mjs
  • libs/ast-guard/src/__tests__/presets.spec.ts
  • libs/ast-guard/SECURITY-AUDIT.md
🧬 Code graph analysis (14)
libs/ast-guard/src/rules/no-eval.rule.ts (1)
libs/ast-guard/src/interfaces.ts (2)
  • ValidationRule (62-77)
  • ValidationContext (44-57)
libs/ast-guard/src/rules/forbidden-loop.rule.ts (2)
libs/ast-guard/src/interfaces.ts (2)
  • ValidationRule (62-77)
  • ValidationContext (44-57)
scripts/strip-dist-from-pkg.js (1)
  • walk (22-37)
libs/ast-guard/src/rules/disallowed-identifier.rule.ts (2)
libs/ast-guard/src/interfaces.ts (2)
  • ValidationRule (62-77)
  • ValidationContext (44-57)
libs/ast-guard/src/errors.ts (1)
  • RuleConfigurationError (26-32)
libs/ast-guard/src/presets/secure.preset.ts (9)
libs/ast-guard/src/index.ts (8)
  • createSecurePreset (62-62)
  • PresetOptions (67-67)
  • ValidationRule (12-12)
  • NoEvalRule (41-41)
  • ForbiddenLoopRule (37-37)
  • NoAsyncRule (42-42)
  • UnreachableCodeRule (39-39)
  • CallArgumentValidationRule (40-40)
libs/ast-guard/src/presets/index.ts (2)
  • createSecurePreset (18-18)
  • PresetOptions (14-14)
libs/ast-guard/src/presets/types.ts (1)
  • PresetOptions (6-50)
libs/ast-guard/src/interfaces.ts (1)
  • ValidationRule (62-77)
libs/ast-guard/src/rules/no-eval.rule.ts (1)
  • NoEvalRule (12-74)
libs/ast-guard/src/rules/forbidden-loop.rule.ts (1)
  • ForbiddenLoopRule (28-84)
libs/ast-guard/src/rules/no-async.rule.ts (1)
  • NoAsyncRule (21-94)
libs/ast-guard/src/rules/unreachable-code.rule.ts (1)
  • UnreachableCodeRule (12-124)
libs/ast-guard/src/rules/call-argument-validation.rule.ts (1)
  • CallArgumentValidationRule (40-201)
libs/ast-guard/src/presets/types.ts (1)
libs/ast-guard/src/rules/call-argument-validation.rule.ts (1)
  • FunctionArgumentConfig (13-24)
libs/ast-guard/src/errors.ts (1)
libs/ast-guard/src/index.ts (6)
  • AstGuardError (26-26)
  • ParseError (27-27)
  • RuleConfigurationError (28-28)
  • ConfigurationError (29-29)
  • RuleNotFoundError (30-30)
  • InvalidSourceError (31-31)
libs/ast-guard/src/__tests__/errors.spec.ts (2)
libs/ast-guard/src/errors.ts (6)
  • AstGuardError (4-10)
  • ParseError (15-21)
  • RuleConfigurationError (26-32)
  • ConfigurationError (37-43)
  • RuleNotFoundError (48-54)
  • InvalidSourceError (59-65)
libs/ast-guard/src/index.ts (6)
  • AstGuardError (26-26)
  • ParseError (27-27)
  • RuleConfigurationError (28-28)
  • ConfigurationError (29-29)
  • RuleNotFoundError (30-30)
  • InvalidSourceError (31-31)
libs/ast-guard/src/presets/index.ts (7)
libs/ast-guard/src/presets/types.ts (1)
  • PresetOptions (6-50)
libs/ast-guard/src/interfaces.ts (1)
  • ValidationRule (62-77)
libs/ast-guard/src/presets/strict.preset.ts (1)
  • createStrictPreset (52-220)
libs/ast-guard/src/presets/secure.preset.ts (1)
  • createSecurePreset (47-148)
libs/ast-guard/src/presets/standard.preset.ts (1)
  • createStandardPreset (48-107)
libs/ast-guard/src/presets/permissive.preset.ts (1)
  • createPermissivePreset (45-88)
libs/ast-guard/src/errors.ts (1)
  • ConfigurationError (37-43)
libs/ast-guard/src/rules/unreachable-code.rule.ts (2)
libs/ast-guard/src/index.ts (4)
  • UnreachableCodeRule (39-39)
  • ValidationRule (12-12)
  • ValidationSeverity (22-22)
  • ValidationContext (15-15)
libs/ast-guard/src/interfaces.ts (2)
  • ValidationRule (62-77)
  • ValidationContext (44-57)
libs/ast-guard/src/validator.ts (2)
libs/ast-guard/src/interfaces.ts (6)
  • ValidationRule (62-77)
  • ValidationConfig (94-103)
  • ValidationResult (108-117)
  • ValidationIssue (28-39)
  • ValidationContext (44-57)
  • ValidationStats (122-135)
libs/ast-guard/src/errors.ts (3)
  • ConfigurationError (37-43)
  • InvalidSourceError (59-65)
  • ParseError (15-21)
libs/ast-guard/src/__tests__/advanced-attack-vectors.spec.ts (2)
libs/ast-guard/src/validator.ts (1)
  • JSAstValidator (16-229)
libs/ast-guard/src/presets/index.ts (1)
  • Presets (86-97)
libs/ast-guard/src/presets/standard.preset.ts (9)
libs/ast-guard/src/presets/types.ts (1)
  • PresetOptions (6-50)
libs/ast-guard/src/interfaces.ts (1)
  • ValidationRule (62-77)
libs/ast-guard/src/rules/no-eval.rule.ts (1)
  • NoEvalRule (12-74)
libs/ast-guard/src/rules/disallowed-identifier.rule.ts (1)
  • DisallowedIdentifierRule (25-62)
libs/ast-guard/src/rules/forbidden-loop.rule.ts (1)
  • ForbiddenLoopRule (28-84)
libs/ast-guard/src/rules/no-async.rule.ts (1)
  • NoAsyncRule (21-94)
libs/ast-guard/src/rules/unreachable-code.rule.ts (1)
  • UnreachableCodeRule (12-124)
libs/ast-guard/src/rules/required-function-call.rule.ts (1)
  • RequiredFunctionCallRule (25-106)
libs/ast-guard/src/rules/call-argument-validation.rule.ts (1)
  • CallArgumentValidationRule (40-201)
libs/ast-guard/src/__tests__/security.spec.ts (8)
libs/ast-guard/src/index.ts (7)
  • JSAstValidator (8-8)
  • NoEvalRule (41-41)
  • DisallowedIdentifierRule (36-36)
  • ForbiddenLoopRule (37-37)
  • RequiredFunctionCallRule (38-38)
  • CallArgumentValidationRule (40-40)
  • UnreachableCodeRule (39-39)
libs/ast-guard/src/validator.ts (1)
  • JSAstValidator (16-229)
libs/ast-guard/src/rules/no-eval.rule.ts (1)
  • NoEvalRule (12-74)
libs/ast-guard/src/rules/disallowed-identifier.rule.ts (1)
  • DisallowedIdentifierRule (25-62)
libs/ast-guard/src/rules/forbidden-loop.rule.ts (1)
  • ForbiddenLoopRule (28-84)
libs/ast-guard/src/rules/required-function-call.rule.ts (1)
  • RequiredFunctionCallRule (25-106)
libs/ast-guard/src/rules/call-argument-validation.rule.ts (1)
  • CallArgumentValidationRule (40-201)
libs/ast-guard/src/rules/unreachable-code.rule.ts (1)
  • UnreachableCodeRule (12-124)
libs/ast-guard/src/__tests__/presets.spec.ts (7)
libs/ast-guard/src/index.ts (8)
  • createStrictPreset (61-61)
  • JSAstValidator (8-8)
  • createSecurePreset (62-62)
  • createStandardPreset (63-63)
  • createPermissivePreset (64-64)
  • createPreset (60-60)
  • PresetLevel (58-58)
  • Presets (59-59)
libs/ast-guard/src/presets/index.ts (7)
  • createStrictPreset (17-17)
  • createSecurePreset (18-18)
  • createStandardPreset (19-19)
  • createPermissivePreset (20-20)
  • createPreset (52-65)
  • PresetLevel (14-14)
  • Presets (86-97)
libs/ast-guard/src/presets/strict.preset.ts (1)
  • createStrictPreset (52-220)
libs/ast-guard/src/validator.ts (1)
  • JSAstValidator (16-229)
libs/ast-guard/src/presets/secure.preset.ts (1)
  • createSecurePreset (47-148)
libs/ast-guard/src/presets/standard.preset.ts (1)
  • createStandardPreset (48-107)
libs/ast-guard/src/presets/permissive.preset.ts (1)
  • createPermissivePreset (45-88)
🪛 LanguageTool
CLAUDE.md

[style] ~186-~186: For a more polite and respectful tone, consider rephrasing with ‘please’.
Context: ...rameters 5. Test Utility Functions: Don't forget small helper functions ### Coverage-Fo...

(DONT_FORGET)

libs/ast-guard/SECURITY-AUDIT.md

[grammar] ~38-~38: Use a hyphen to join words.
Context: ... - Use Case: Internal scripts, high trust environments - Blocks: eval() ...

(QB_NEW_EN_HYPHEN)


[grammar] ~173-~173: Use a hyphen to join words.
Context: ...rty is blocked, preventing getter/setter based side effects. --- #### 9. **Bina...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
libs/ast-guard/PENETRATION-TEST-SUMMARY.md

228-228: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

libs/ast-guard/SECURITY-AUDIT.md

463-463: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (21)
libs/ast-guard/src/errors.ts (1)

1-65: Error hierarchy implementation looks solid

The custom error classes (AstGuardError and its subclasses) correctly:

  • Extend Error with a stable code field and additional context (line/column, ruleName).
  • Set name and use Object.setPrototypeOf to preserve instanceof behavior across inheritance.

This provides a clean, type‑safe error surface for consumers and internal code.

CLAUDE.md (2)

136-168: <!-- [scratchpad_start]
[task verify_review_comment complete 3/3]
[observations]

  • README.md is for FrontMCP (MCP server framework), NOT ast-guard
  • No "validate", "astguard", or custom rule patterns found in README.md
  • README.md contains Tool implementations with async execute() methods (for Tools, not ValidationRules)
  • CLAUDE.md is ast-guard documentation, but root README is FrontMCP documentation
  • ValidationRule.validate() actual signature: validate(context: ValidationContext): void | Promise<void> (allows sync OR async)
  • CLAUDE.md example shows async execute() - this is WRONG on both counts:
    1. Method name should be validate, not execute
    2. Should allow sync OR async, not strictly async Promise
  • No AstGuard class or alias exists in codebase - only JSAstValidator
  • Anti-pattern comment about "export { JSAstValidator as AstGuard } // WRONG" is misleading since this export doesn't exist

[analysis]

  • Review comment is based on false premise: README.md does not contain ValidationRule examples or AstGuard imports
  • CLAUDE.md examples have TWO errors: wrong method name (execute vs validate) and wrong return type (Promise vs void | Promise)
  • The concern about syncing with README is invalid - README is unrelated FrontMCP docs
  • Only real actionable issue: CLAUDE.md code pattern is incorrect

[done]

  • Verification complete: review comment is INCORRECT regarding README.md content
  • Code pattern in CLAUDE.md is factually wrong about method signature
    </scratchpad_end] -->

Update CLAUDE.md to use correct ValidationRule contract signature

The ValidationRule interface uses validate() method, not execute(). The method signature also supports both sync and async operations—not async-only.

Correct the code pattern at lines 136–168 from:

  • async execute(context: ValidationContext): Promise<void>

To:

  • validate(context: ValidationContext): void | Promise<void>

The claim about README.md containing ValidationRule examples or AstGuard imports is unsupported; the repository's README.md covers FrontMCP (an MCP server framework), not ast-guard validation rules. Remove the references to reconciling with README examples unless documentation for ast-guard exists at a different location (e.g., docs/ subdirectory).

Likely an incorrect or invalid review comment.


115-135: CLAUDE.md preset section is correct; README.md and CHANGELOG.md require fixes

Verification confirms the CLAUDE.md section (lines 115–135) is accurate and matches the actual implementation. The real inconsistency is elsewhere:

  • CLAUDE.md (lines 115–135): ✓ Correctly documents PresetLevel {STRICT, SECURE, STANDARD, PERMISSIVE} and Presets.strict/secure/standard/permissive
  • Implementation (src/presets/): ✓ Confirms STRICT, SECURE, STANDARD, PERMISSIVE with corresponding factory functions
  • SECURITY-AUDIT.md: ✓ Correctly uses STRICT, SECURE, STANDARD, PERMISSIVE
  • README.md & CHANGELOG.md: ✗ Document LOCKDOWN, SECURED, BALANCED, NAIVE, NO_BUILTIN with Presets.lockdown(), Presets.secured(), etc.—these presets do not exist in the code

The problem is not CLAUDE.md; it requires no changes. Instead, libs/ast-guard/README.md and libs/ast-guard/CHANGELOG.md must be rewritten to document the actual preset API (STRICT, SECURE, STANDARD, PERMISSIVE) and correct the function names (.strict(), .secure(), .standard(), .permissive()).

Likely an incorrect or invalid review comment.

libs/ast-guard/jest.setup.ts (1)

1-2: Jest setup placeholder is fine

A minimal commented stub is OK for now; you can flesh this out once you need shared Jest globals or custom matchers.

libs/ast-guard/tsconfig.json (1)

1-28: TS config structure looks appropriate for a strict library

Extending the base config, using project references (lib/spec), and enabling strict/null/return/switch checks is a solid setup for this library; no issues from what’s visible here.

libs/ast-guard/tsconfig.spec.json (1)

1-9: Test tsconfig aligns with Jest usage

Spec config (CommonJS module, Jest/Node types, and test file globs) is consistent with a standard Jest+TS setup; looks good as-is.

libs/ast-guard/jest.config.ts (1)

1-25: Jest config is well-scoped and consistent.

Preset, SWC transform, testMatch, and coverage settings all look appropriate for a Node-focused TS library; no issues from a testing/config standpoint.

libs/ast-guard/src/__tests__/validator.spec.ts (1)

6-62: Rule registration and lookup tests are comprehensive.

Constructor, registerRule/unregisterRule, duplicate detection, and getRule/getRules behaviors are all exercised cleanly, which should keep the rule registry semantics stable.

libs/ast-guard/src/__tests__/presets.spec.ts (2)

12-140: Preset tests for STRICT behavior are very thorough.

You exercise eval blocking, dangerous identifiers, all loop variants, async/await defaults, required function calls, argument validation, and custom disallowed identifiers, which gives high confidence that createStrictPreset and its options are wired correctly.


223-582: Preset, factory, and “real-world” tests give excellent end-to-end coverage.

STANDARD and PERMISSIVE presets, createPreset, the Presets helper, and the real-world scenarios collectively validate loop policies, async policies, identifier lists, required-call semantics, argument validation, and customization hooks. This is a strong safety net for the preset system and its public API.

libs/ast-guard/src/presets/permissive.preset.ts (1)

45-88: Preset behavior looks consistent; double‑check severity and docs alignment

The preset wiring is coherent: NoEvalRule + optional DisallowedIdentifierRule / RequiredFunctionCallRule / CallArgumentValidationRule, with loops and async intentionally left unrestricted.

Two things worth verifying:

  1. The comment says “Unreachable code (as warning)” but the code relies on new UnreachableCodeRule() defaults. If that rule’s defaultSeverity is not WARNING, either update its default or adjust the comment to avoid misleading users.
  2. Since createPermissivePreset becomes part of the public presets API, ensure the new PERMISSIVE level and its behavior are documented under docs/draft/docs/** in line with the other presets.
libs/ast-guard/src/index.ts (1)

7-67: Public API barrel looks good; treat this surface as stable going forward

The exports are well-structured and give consumers a clear, centralized entry point (validator, interfaces, errors, built‑in rules, rule option types, and presets including createPermissivePreset).

Given how much is now publicly exported from here, future changes to these names/locations will be breaking. It’s worth:

  • Treating this file as the canonical API contract for semver.
  • Ensuring corresponding documentation clearly reflects all exported rules, option types, and preset factories.
libs/ast-guard/src/__tests__/errors.spec.ts (1)

1-159: Error hierarchy tests are comprehensive and aligned with implementations

The suite thoroughly exercises construction, codes, names, and prototype/instanceof behavior for all error types and the shared base, matching the implementations in errors.ts. No changes needed here.

libs/ast-guard/src/presets/secure.preset.ts (1)

47-147: Secure preset composition matches documented behavior

The rule set and options handling line up with the JSDoc: NoEvalRule + a strong (but slightly relaxed vs strict) disallowed identifier list, bounded‑loop defaults via ForbiddenLoopRule, async‑functions blocked but await allowed by default via NoAsyncRule, plus optional required‑call and argument‑validation rules. Use of ?? for options correctly preserves explicit false values. No functional issues from what’s visible here.

libs/ast-guard/src/__tests__/advanced-attack-vectors.spec.ts (1)

52-551: Advanced attack vector coverage is strong and well‑documented

Aside from the Unicode‑escape case above, the rest of the suite provides a solid set of edge‑case scenarios: property access chains, destructuring, tagged templates, class constructors, with, comma operator, logical assignment, generators/async generators, labels, and known static‑analysis limitations are all clearly encoded with expectations that match the described behavior. This is valuable documentation as much as it is regression coverage.

libs/ast-guard/src/presets/strict.preset.ts (1)

52-219: Strict preset semantics match the “bank‑grade” description

createStrictPreset wires up the rules in a deterministic order, with defaults that align with the docs:

  • NoEvalRule and a very aggressive DisallowedIdentifierRule list.
  • All loop types and async/await blocked by default, overridable via allowedLoops/allowAsync.
  • Optional required‑function and argument‑validation enforcement.
  • Unreachable code detection always on.

Use of ?? ensures explicitly providing false in options is respected. From the visible code, this preset matches the intended “maximum security” contract.

libs/ast-guard/project.json (1)

1-33: ---

No issues found—configuration is correct and consistent

Verification confirms:

  • scripts/strip-dist-from-pkg.js exists at the expected path and will execute correctly.
  • The publish target in libs/ast-guard/project.json follows the exact same pattern as all other publishable libraries in the monorepo (sdk, cli, adapters, plugins, json-schema-to-zod-v3, vectoriadb, mcp-from-openapi), indicating this is an intentional, standardized approach to publishing.

The build target chain (build-tscbuildpublish) is sound and ready for CI.

libs/ast-guard/src/rules/forbidden-loop.rule.ts (1)

7-83: ForbiddenLoopRule implementation matches intended configurable behavior

Config surface and implementation look solid: per-loop allow flags, sensible default message, and targeted handlers for each loop node type. This aligns with how presets and tests are using the rule.

libs/ast-guard/src/__tests__/rules.spec.ts (1)

1-497: Rule tests are comprehensive and consistent with rule semantics

The suite thoroughly exercises happy paths and error conditions for each rule (including config errors), and matches the current implementations’ codes/messages. This should give strong confidence in rule behavior.

libs/ast-guard/src/presets/types.ts (1)

1-73: PresetOptions and PresetLevel are well-structured and match preset usage

The configuration surface here lines up cleanly with how the strict/secure/standard/permissive presets consume these options, and the enum/docs clearly express the intended security levels.

libs/ast-guard/src/interfaces.ts (1)

1-135: Core validation interfaces look coherent and aligned with usage

The definitions for ValidationSeverity, ValidationIssue, ValidationContext, ValidationRule, RuleConfig, ValidationConfig, ValidationResult, and ValidationStats are consistent with how they’re used in the rules and JSAstValidator. No structural issues spotted here.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
libs/ast-guard/src/validator.ts (1)

165-190: Populate rulesExecuted in stats

rulesExecuted is still hardcoded to 0, so the metric is useless (same concern noted earlier). Please thread the actual number of executed rules into this function—e.g., pass a counter from validate and assign it here—instead of leaving this field at zero.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 402f50d and fb3de9f.

📒 Files selected for processing (4)
  • libs/ast-guard/CHANGELOG.md (1 hunks)
  • libs/ast-guard/src/__tests__/advanced-attack-vectors.spec.ts (1 hunks)
  • libs/ast-guard/src/__tests__/security.spec.ts (1 hunks)
  • libs/ast-guard/src/validator.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • libs/ast-guard/CHANGELOG.md
🧰 Additional context used
📓 Path-based instructions (1)
libs/**

⚙️ CodeRabbit configuration file

libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).

Files:

  • libs/ast-guard/src/validator.ts
  • libs/ast-guard/src/__tests__/advanced-attack-vectors.spec.ts
  • libs/ast-guard/src/__tests__/security.spec.ts
🧬 Code graph analysis (2)
libs/ast-guard/src/validator.ts (2)
libs/ast-guard/src/interfaces.ts (6)
  • ValidationRule (62-77)
  • ValidationConfig (94-103)
  • ValidationResult (108-117)
  • ValidationIssue (28-39)
  • ValidationContext (44-57)
  • ValidationStats (122-135)
libs/ast-guard/src/errors.ts (3)
  • ConfigurationError (37-43)
  • InvalidSourceError (59-65)
  • ParseError (15-21)
libs/ast-guard/src/__tests__/advanced-attack-vectors.spec.ts (3)
libs/ast-guard/src/validator.ts (1)
  • JSAstValidator (16-225)
libs/ast-guard/src/index.ts (2)
  • JSAstValidator (8-8)
  • Presets (59-59)
libs/ast-guard/src/presets/index.ts (1)
  • Presets (86-97)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
libs/ast-guard/src/validator.ts (1)

197-223: Severity-only rule overrides are still treated as “disable rule”

When config.rules[ruleName] is an object without an explicit enabled flag (e.g. { severity: WARNING }), this branch:

// If rule config is object
if (ruleConfig.enabled) {
  enabled.push(rule);
}

treats enabled: undefined as falsy and drops the rule, so severity-only overrides silently disable it. For a libs/** SDK, this breaks the public configuration contract. As per coding guidelines, rule configuration must actually affect which rules run and how.

You should only disable the rule when enabled === false, enable when enabled === true, and otherwise fall back to rule.enabledByDefault. For example:

  private getEnabledRules(config: ValidationConfig): ValidationRule[] {
    const enabled: ValidationRule[] = [];

    for (const rule of this.rules.values()) {
      const ruleConfig = config.rules?.[rule.name];

      // If rule is not configured, use its default enabled state
      if (ruleConfig === undefined) {
        if (rule.enabledByDefault) {
          enabled.push(rule);
        }
        continue;
      }

      // If rule config is boolean
      if (typeof ruleConfig === 'boolean') {
        if (ruleConfig) {
          enabled.push(rule);
        }
        continue;
      }

-      // If rule config is object
-      if (ruleConfig.enabled) {
-        enabled.push(rule);
-      }
+      // If rule config is object: respect explicit enabled flag, else fall back to default
+      const explicitlyEnabled =
+        typeof ruleConfig.enabled === 'boolean' ? ruleConfig.enabled : undefined;
+      const shouldEnable = explicitlyEnabled ?? rule.enabledByDefault;
+      if (shouldEnable) {
+        enabled.push(rule);
+      }
    }

    return enabled;
  }

This preserves backward-compatible defaults while making severity-only overrides work as intended.

As per coding guidelines, this should be fixed before publishing the library.

🧹 Nitpick comments (3)
CLAUDE.md (2)

48-59: Barrel exports example is clear but should reference actual file location.

The barrel exports documentation provides good guidance on the correct pattern. Consider adding a comment clarifying that developers should reference libs/ast-guard/src/index.ts (or the actual path) as the implementation example.


21-21: Add hyperlink to SECURITY-AUDIT.md for discoverability.

The documentation mentions SECURITY-AUDIT.md multiple times but doesn't provide a direct link. This would improve navigation for developers reviewing security considerations.

-#### ast-guard
-
-- **Type**: Helper library (independent, publishable)
-- **Purpose**: Bank-grade JavaScript validation using AST analysis
-- **Security Model**: Four-tier preset system (STRICT > SECURE > STANDARD > PERMISSIVE)
-- **Test Count**: 188 tests with 95.11% coverage
-- **Key Rules**: DisallowedIdentifier, NoEval, NoAsync, CallArgumentValidation, etc.
-- **Documentation**: SECURITY-AUDIT.md documents all 67 blocked attack vectors
+#### ast-guard
+
+- **Type**: Helper library (independent, publishable)
+- **Purpose**: Bank-grade JavaScript validation using AST analysis
+- **Security Model**: Four-tier preset system (STRICT > SECURE > STANDARD > PERMISSIVE)
+- **Test Count**: 188 tests with 95.11% coverage
+- **Key Rules**: DisallowedIdentifier, NoEval, NoAsync, CallArgumentValidation, etc.
+- **Documentation**: [SECURITY-AUDIT.md](../libs/ast-guard/SECURITY-AUDIT.md) documents all 67 blocked attack vectors

Also applies to: 87-95

libs/ast-guard/src/presets/strict.preset.ts (1)

52-219: Strict preset wiring is consistent and highly restrictive by design

Rule composition and option handling look correct: eval and a broad set of dangerous/global identifiers are blocked, all loops and async are denied by default but can be selectively relaxed via allowedLoops / allowAsync, and optional required-call and argument-validation rules are only added when configured. The resulting behavior matches the “bank-grade” description; just be aware that the disallowed identifier list is very aggressive (e.g., standard constructors and browser APIs) and should be clearly documented for consumers.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb3de9f and 0f384a0.

📒 Files selected for processing (10)
  • CLAUDE.md (1 hunks)
  • libs/ast-guard/CHANGELOG.md (1 hunks)
  • libs/ast-guard/README.md (1 hunks)
  • libs/ast-guard/src/interfaces.ts (1 hunks)
  • libs/ast-guard/src/presets/permissive.preset.ts (1 hunks)
  • libs/ast-guard/src/presets/secure.preset.ts (1 hunks)
  • libs/ast-guard/src/presets/standard.preset.ts (1 hunks)
  • libs/ast-guard/src/presets/strict.preset.ts (1 hunks)
  • libs/ast-guard/src/rules/unreachable-code.rule.ts (1 hunks)
  • libs/ast-guard/src/validator.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • libs/ast-guard/README.md
  • libs/ast-guard/src/presets/secure.preset.ts
  • libs/ast-guard/CHANGELOG.md
  • libs/ast-guard/src/interfaces.ts
  • libs/ast-guard/src/presets/standard.preset.ts
🧰 Additional context used
📓 Path-based instructions (1)
libs/**

⚙️ CodeRabbit configuration file

libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).

Files:

  • libs/ast-guard/src/presets/strict.preset.ts
  • libs/ast-guard/src/rules/unreachable-code.rule.ts
  • libs/ast-guard/src/presets/permissive.preset.ts
  • libs/ast-guard/src/validator.ts
🧠 Learnings (1)
📚 Learning: 2025-11-16T22:47:05.139Z
Learnt from: frontegg-david
Repo: agentfront/frontmcp PR: 50
File: docs/docs/v/0.1/getting-started/welcome.mdx:2-3
Timestamp: 2025-11-16T22:47:05.139Z
Learning: In the agentfront/frontmcp repository, the docs/docs/v/** directory governance rule prohibiting manual edits applies to already-frozen releases, but does not preclude initial setup and bootstrap commits that establish the versioned docs structure.

Applied to files:

  • CLAUDE.md
🧬 Code graph analysis (1)
libs/ast-guard/src/validator.ts (3)
libs/ast-guard/src/index.ts (11)
  • JSAstValidator (8-8)
  • ValidationRule (12-12)
  • ConfigurationError (29-29)
  • ValidationConfig (13-13)
  • ValidationResult (14-14)
  • InvalidSourceError (31-31)
  • ValidationIssue (16-16)
  • ParseError (27-27)
  • ValidationSeverity (22-22)
  • ValidationContext (15-15)
  • ValidationStats (17-17)
libs/ast-guard/src/interfaces.ts (6)
  • ValidationRule (62-77)
  • ValidationConfig (94-103)
  • ValidationResult (108-119)
  • ValidationIssue (28-39)
  • ValidationContext (44-57)
  • ValidationStats (124-137)
libs/ast-guard/src/errors.ts (3)
  • ConfigurationError (37-43)
  • InvalidSourceError (59-65)
  • ParseError (15-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (3)
CLAUDE.md (1)

126-140: Anti-patterns and do's sections are well-structured and actionable.

The guidance here is practical and specific, making it clear what behaviors are discouraged and encouraged. This supports consistent code quality across the monorepo.

libs/ast-guard/src/validator.ts (1)

116-145: Severity resolution and early-stop behavior look correct

The per-rule report closure now correctly applies severity precedence (issue.severity → config override → rule default → ERROR) and enforces stopOnFirstError / maxIssues after pushing the issue. This aligns the runtime behavior with the configuration model and previous review feedback.

libs/ast-guard/src/presets/permissive.preset.ts (1)

45-88: Permissive preset composition matches documented behavior

The preset wiring is coherent: always blocking eval, warning on unreachable code, and only adding identifier / required-call / argument rules when corresponding options are non-empty. Omitting loop/async restrictions aligns with the “permissive” description.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
libs/ast-guard/src/rules/unreachable-code.rule.ts (1)

54-80: LGTM: Terminal statement detection is correctly implemented.

The logic properly handles various terminal statement types:

  • Return/throw are always terminal
  • Break/continue correctly identify unreachable code within their block
  • IfStatement requires both branches to be terminal
  • BlockStatement's some() check is appropriate (any terminal statement means the block terminates from the parent's perspective)

Optional: Consider adding stronger TypeScript types to replace any:

import type { Node } from 'acorn';

// Then use Node type instead of any where applicable
private isTerminalStatement(node: Node): boolean {
  // ...
}

This would improve type safety and IDE support, though acorn's type definitions may require type assertions for specific node types.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f384a0 and f1ca51b.

📒 Files selected for processing (2)
  • libs/ast-guard/src/rules/unreachable-code.rule.ts (1 hunks)
  • libs/ast-guard/src/validator.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/ast-guard/src/validator.ts
🧰 Additional context used
📓 Path-based instructions (1)
libs/**

⚙️ CodeRabbit configuration file

libs/**: Contains publishable SDK libraries. Review for API correctness, breaking changes, and consistency with docs. When public APIs change, ensure there is a matching docs/draft/docs/** update (not direct edits under docs/docs/**).

Files:

  • libs/ast-guard/src/rules/unreachable-code.rule.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (2)
libs/ast-guard/src/rules/unreachable-code.rule.ts (2)

12-16: LGTM: Well-defined rule metadata.

The rule identity and defaults are appropriate. WARNING severity is a good default for unreachable code, and enabling by default helps catch common issues.


18-49: LGTM: Core detection logic is sound.

The validation method correctly identifies terminal statements and reports subsequent unreachable code. Both past review concerns have been addressed:

  • No duplicate reporting (removed extra ReturnStatement/ThrowStatement visitors)
  • Config-based severity override now works (no explicit severity in report call)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants