Skip to content

feat(compiler): SYN015 — warn on localStorage/sessionStorage access that bypasses the storage capability model (?bs 0.7+) - #162

Open
marcelofarias wants to merge 19 commits into
mainfrom
botkowski/syn015-localstorage-bypass
Open

feat(compiler): SYN015 — warn on localStorage/sessionStorage access that bypasses the storage capability model (?bs 0.7+)#162
marcelofarias wants to merge 19 commits into
mainfrom
botkowski/syn015-localstorage-bypass

Conversation

@marcelofarias

Copy link
Copy Markdown
Owner

Summary

  • Adds SYN015: warns when a fn body accesses localStorage.* or sessionStorage.* at ?bs 0.7+
  • Both globals are persistent same-origin storage invisible to botscript's capability model: reads {} / writes {} labels cover declared resource identifiers, not the Web Storage API globals. A fn that calls localStorage.getItem(key) has an undeclared persistent state dependency — no reads {} declaration covers it, callers cannot see it, and it outlives the fn invocation (visible across unrelated calls and tabs on the same origin).
  • Same detection architecture as existing SYN-series checks: single dispatch loop, unsafe-range suppression, fn/function declaration exclusion.

Changes

File Change
packages/compiler/src/error-codes.ts Add SYN015 entry (rule, idiom, rewrite, example)
packages/compiler/src/passes/syn-check.ts Add case "localStorage": case "sessionStorage": in dispatch loop — fires on any member access (. or ?.), excludes obj.localStorage.*, bare references, and fn declarations
packages/compiler/tests/syn015-check.test.ts 18 tests: both globals, setItem/getItem/removeItem/clear/.length, optional chaining, unsafe suppression, member-of-local exclusion, bare reference exclusion, fn declaration exclusion, multi-warning count, severity, message content
packages/compiler/tests/error-codes.test.ts Add SYN015 to exhaustive allowlist
packages/mcp/src/explanations.ts Add SYN015 long-form explanation
packages/mcp/tests/server.test.ts Add SYN015 to KNOWN_CODES list
AGENTS.md Add SYN015 row to diagnostic table
README.md Add SYN015 to explain tool code list

Test plan

  • pnpm -r build && pnpm test — 1300 tests pass (46 test files)
  • SYN015 fires on localStorage.getItem(key)
  • SYN015 fires on localStorage.setItem(key, val)
  • SYN015 fires on sessionStorage.getItem(key)
  • SYN015 fires on sessionStorage.setItem(key, val)
  • SYN015 fires on localStorage.removeItem(key)
  • SYN015 fires on localStorage.clear()
  • SYN015 fires on localStorage?.getItem(key) (optional chaining)
  • SYN015 fires on localStorage.length (property access, not method call)
  • SYN015 does NOT fire below ?bs 0.7
  • SYN015 does NOT fire inside unsafe {} blocks or unsafe "reason" fn bodies
  • SYN015 does NOT fire on obj.localStorage.getItem(...) (member of a local)
  • SYN015 does NOT fire on bare localStorage reference (no following .)
  • SYN015 does NOT fire on fn localStorage(...) botscript declarations
  • SYN015 fires twice when both globals are accessed in the same fn

🤖 Generated with Claude Code

Loading
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