Skip to content

feat(compiler): SYN011 — warn on dynamic import() calls that bypass the module capability model (?bs 0.7+)#153

Open
marcelofarias wants to merge 4 commits into
mainfrom
botkowski/syn011-dynamic-import
Open

feat(compiler): SYN011 — warn on dynamic import() calls that bypass the module capability model (?bs 0.7+)#153
marcelofarias wants to merge 4 commits into
mainfrom
botkowski/syn011-dynamic-import

Conversation

@marcelofarias

Copy link
Copy Markdown
Owner

Summary

  • Adds SYN011: a new warning that fires when a fn body calls import(...) — the dynamic import form — at ?bs 0.7+
  • Dynamic imports load a module at runtime whose capabilities are not statically declared and are invisible to CAP001 (which only checks http.* member calls). The fn header cannot declare capabilities it doesn't know about at compile time
  • The capability surface of the loaded module is unbounded — the manifest hash proves the fn body unchanged; it says nothing about what the dynamically loaded module does at runtime
  • Same bypass class as SYN007/SYN008/SYN009/SYN010, but more severe: dynamic import loads arbitrary code
  • Suppressed inside unsafe "reason" { } blocks and unsafe "reason" fn bodies
  • Note: should be merged after PR feat(compiler): SYN010 — warn on setTimeout/setInterval/queueMicrotask calls that defer side effects (?bs 0.7+) #151 (SYN010) lands; SYN011 is the next available code in the bypass series

Changes

File Change
packages/compiler/src/error-codes.ts Add SYN011 entry (rule, idiom, rewrite, example)
packages/compiler/src/passes/syn-check.ts Add SYN011 detection; add SYN011 to module header comment
packages/compiler/tests/syn011-check.test.ts 10 tests: bare/template-literal/awaited forms, unsafe suppression, import.meta exclusion, version gate, severity, multi-call count, bare reference
packages/compiler/tests/error-codes.test.ts Add SYN011 to exhaustive allowlist
packages/mcp/src/explanations.ts Add SYN011 long-form explanation with fails/passes examples
packages/mcp/tests/server.test.ts Add SYN011 to KNOWN_CODES list
AGENTS.md Add SYN011 row to diagnostic table
README.md Add SYN011 to explain tool code list

Test plan

  • pnpm -r build && pnpm test — 1171 tests pass (42 test files)
  • SYN011 fires on bare import(specifier)
  • SYN011 fires on template literal import(`./module`)
  • SYN011 fires on const mod = await import(path)
  • SYN011 suppressed inside unsafe {} blocks and unsafe fn bodies
  • SYN011 does NOT fire on import.meta.url (property access, not a call)
  • SYN011 does NOT fire below ?bs 0.7

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds support for the new SYN011 warning by documenting it, registering it in the error-code registry, explaining it via the MCP server, and implementing + testing detection of dynamic import() calls inside function bodies.

Changes:

  • Register and document new diagnostic code SYN011 across compiler/MCP surfaces (README, AGENTS, explanations/registry).
  • Implement SYN011 detection in the compiler syn-check pass for import(specifier) within fn bodies (suppressed in unsafe).
  • Add compiler tests validating triggering/suppression, severity, and version gating behavior.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/mcp/tests/server.test.ts Includes SYN011 in MCP “explainable codes” coverage.
packages/mcp/src/explanations.ts Adds long-form MCP explanation + examples for SYN011.
packages/compiler/tests/syn011-check.test.ts Adds vitest coverage for SYN011 detection/suppression semantics.
packages/compiler/tests/error-codes.test.ts Registers SYN011 in the compiler’s error-code registry test.
packages/compiler/src/passes/syn-check.ts Implements the SYN011 token scan + warning emission.
packages/compiler/src/error-codes.ts Adds compiler registry entry (title/rule/idiom/rewrite/example) for SYN011.
README.md Documents SYN011 as a valid explain target.
AGENTS.md Adds SYN011 to the diagnostics table and remediation guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/compiler/src/passes/syn-check.ts
Comment thread packages/compiler/src/passes/syn-check.ts Outdated
Comment thread packages/compiler/tests/syn011-check.test.ts

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Comment thread packages/compiler/src/passes/syn-check.ts
Comment thread packages/compiler/tests/syn011-check.test.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@marcelofarias marcelofarias force-pushed the botkowski/syn010-timer-bypass branch from 9234bd2 to 6847365 Compare June 12, 2026 02:35
Marcelo Farias and others added 3 commits June 11, 2026 23:36
…he module capability model (?bs 0.7+)

- Adds SYN011: fires when a fn body calls import(specifier) — the dynamic import form
- Dynamic imports load a module at runtime whose capability surface is unbounded:
  CAP001 cannot see what the dynamically loaded module does; the fn header cannot
  declare capabilities it doesn't know about at compile time
- import.meta (followed by `.`) is excluded — it's a property, not a call
- Suppressed inside `unsafe "reason" { }` blocks and `unsafe "reason" fn` bodies
- 10 tests: bare/template-literal/awaited forms, unsafe suppression, import.meta
  exclusion, version gate, severity, multi-call count, bare reference non-fire
- Should be merged after SYN010 (PR #151) lands — SYN011 is the next available code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…and exclusion and test guards

- Add fn/function declaration exclusion for SYN011 (mirrors SYN010 pattern)
- Add method shorthand exclusion: { import(x) { ... } } after matching closing ) check
- Simplify compile() helper in syn011-check.test.ts to match syn010 pattern
- Add regression test: SYN011 does NOT fire on object method shorthand named import

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@marcelofarias marcelofarias force-pushed the botkowski/syn011-dynamic-import branch from f9369b5 to 3b596f2 Compare June 12, 2026 02:38
@marcelofarias marcelofarias requested a review from Copilot June 12, 2026 02:38
@marcelofarias marcelofarias changed the base branch from botkowski/syn010-timer-bypass to main June 12, 2026 02:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment on lines +702 to +704
// Exclude fn / function declarations: `fn import(...)` or `function import(...)`
if (prev11 && prev11.kind === "ident" && (prev11.text === "fn" || prev11.text === "function"))
continue;
…aration exclusion

Botscript's `fn` keyword is lexed as kind="keyword", not kind="ident".
The previous exclusion check (`prev11.kind === "ident" && prev11.text === "fn"`)
never matched, so `fn import(specifier) { ... }` declarations were incorrectly
flagged as SYN011. Fix to check kind==="keyword" for `fn` and kind==="ident"
for `function`. Adds regression test to prevent future regressions.

Co-Authored-By: Botkowski <noreply@botkowski>
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