Skip to content

feat: kotlin (Spring + Ktor) structural support#93

Merged
boorad merged 2 commits into
mainfrom
feat/kotlin-structural
May 29, 2026
Merged

feat: kotlin (Spring + Ktor) structural support#93
boorad merged 2 commits into
mainfrom
feat/kotlin-structural

Conversation

@boorad
Copy link
Copy Markdown
Collaborator

@boorad boorad commented May 29, 2026

Summary

Adds Kotlin to the structural scanner — eight rules covering Spring Security and Ktor, the tree-sitter-kotlin-ng grammar wired through the parser, and .kt/.kts discovery.

Changes

  • Parser & discovery: tree-sitter-kotlin-ng = 1.1 added; Language::Kotlin wired through get_language, detect_language, and detect_language_for_deep; .kt + .kts extensions resolve to Kotlin.
  • Rules (rules/kotlin/, 8 rules, all confidence = "high"):
    • Spring Security — @PreAuthorize, @Secured, @RolesAllowed, hasRole/hasAuthority call, user.role == "...", user.roles.contains(...)
    • Ktor — authenticate("name") { ... } / authenticate { ... } route guards (middleware), install(Authentication) / install(Sessions) plugin registration (middleware)
    • All Spring rules use (^|\.)Annotation$ regex on a single user_type capture to handle both bare and fully-qualified annotation forms in one rule (Kotlin's tree-sitter flattens dotted annotation paths).
  • Embedded rules (src/rules/embedded.rs): all 8 Kotlin rules registered in the embedded set.
  • Tests: 17 new matcher tests + 1 dedup test for multi-string @Secured("A", "B"); 18 new inline rule-TOML tests. Full suite green: 442 lib tests + 424 inline rule tests pass.
  • Corpus: docs/corpus/kotlin.mdktor-samples (commit c89f051e, 204 .kt/.kts files, 12,254 LOC) yields 13 structural findings (7 authenticate {}, 6 install()) with no false positives. Spring-Kotlin rules need a separate corpus target.
  • Docs: README.md, AGENTS.md, docs/DESIGN.md updated to reflect Kotlin shipping in v0.2 (was previously listed as planned).

Testing

cargo build --release
cargo test --all-features
cargo run -- rules test          # 424 inline rule tests
cargo clippy --all-features -- -D warnings
cargo fmt --check

Manual corpus reproduction:

git clone https://github.com/ktorio/ktor-samples /tmp/ktor-samples
git -C /tmp/ktor-samples checkout c89f051e
cargo run --release -- scan /tmp/ktor-samples --format json | jq '.findings | length'   # 13

Notes

  • Plain feat: per CLAUDE.md's versioning table — this rolls into the next 0.2.x patch (not a 0.2.0 cut). Use feat!: when cutting 0.2.0 deliberately.

Closes #84

Summary by CodeRabbit

  • New Features

    • Kotlin is now supported for structural security scanning: Spring Security annotations, RBAC role checks, and Ktor authentication middleware are detected.
  • Documentation

    • Updated supported-languages and design docs to list Kotlin v0.2, added a Kotlin corpus guide and sample findings.

Review Change Stack

@boorad boorad self-assigned this May 29, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

📝 Walkthrough

Walkthrough

Adds structural Kotlin support: wires tree-sitter-kotlin, recognizes .kt/.kts, registers Kotlin RBAC/Ktor rules, expands matcher tests, and updates docs/corpus and release-status references.

Changes

Kotlin Structural Scanner Support

Layer / File(s) Summary
Language infrastructure and scanner wiring
Cargo.toml, src/scanner/parser.rs, src/scanner/discovery.rs
Tree-sitter-Kotlin dependency added; Language::Kotlin mapped in parser; .kt and .kts extensions recognized by structural discovery; parser and discovery tests updated to include Kotlin.
Spring Security annotation rules
rules/kotlin/spring-preauthorize.toml, rules/kotlin/spring-secured.toml, rules/kotlin/roles-allowed.toml
Three rules detect Spring-Kotlin access-control annotations (@PreAuthorize, @Secured, @RolesAllowed) with tree-sitter queries capturing role values and emitting Rego/Cedar policy templates; embedded tests included.
RBAC method-call and property-check rules
rules/kotlin/has-role-call.toml, rules/kotlin/role-equals-check.toml, rules/kotlin/role-collection-contains.toml
Rules detect idiomatic role checks: hasRole()/hasAuthority() calls, equality expressions like user.role == "admin", and collection membership user.roles.contains(...), with policy templates and tests.
Ktor middleware authentication rules
rules/kotlin/ktor-authenticate-block.toml, rules/kotlin/ktor-install-authentication.toml
Detects Ktor authenticate { ... } route guards and `install(Authentication
Rule registration and matcher tests
src/rules/embedded.rs, src/scanner/matcher.rs
Embeds Kotlin TOML rules in EMBEDDED_RULES; adds parse_and_match_kotlin helper and comprehensive matcher tests for Spring/Ktor/RBAC patterns.
Documentation and release status updates
docs/corpus/kotlin.md, docs/corpus/README.md, docs/DESIGN.md, README.md, AGENTS.md, src/deep/candidate.rs
Adds Kotlin corpus calibration (ktorio/ktor-samples); updates DESIGN priority and README/AGENTS language support to reflect structural Kotlin support; adjusts deep-pass commentary.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • EnforceAuth/zift#50: Both PRs modify src/rules/embedded.rs’s EMBEDDED_RULES registry to embed newly added rule TOMLs (main: Kotlin rules; retrieved: Go/TS/Python/Java rules), so the changes are code-level related.
  • EnforceAuth/zift#29: Both PRs extend the same structural-scanning pipeline by wiring a new language into src/scanner/discovery.rs::detect_language, src/scanner/parser.rs::get_language, rule registration in src/rules/embedded.rs, and corresponding matcher tests (src/scanner/matcher.rs), so the changes are code-level related.
  • EnforceAuth/zift#69: Both PRs modify the same core language-detection/parsing paths—detect_language/get_language in src/scanner/discovery.rs and src/scanner/parser.rs, plus embedded-rule registration in src/rules/embedded.rs—but for different languages (Kotlin vs C#).

Poem

🐰 A rabbit hops through Kotlin code,
Spring guards and Ktor's auth in sight,
Tree-sitter sings the syntax true,
Structural rules now catch the light.
Roles and guards align tonight.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: kotlin (Spring + Ktor) structural support' accurately summarizes the main objective: adding Kotlin structural scanner support with Spring and Ktor framework coverage.
Linked Issues check ✅ Passed All coding-related requirements from issue #84 are met: tree-sitter-kotlin integrated, 8 Kotlin rules added (Spring & Ktor patterns), language detection updated, Rego/Cedar templates included, corpus documentation added, README updated.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #84 objectives. No out-of-scope modifications detected; changes focus exclusively on Kotlin structural support implementation.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/kotlin-structural

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

Copy link
Copy Markdown

@amazon-q-developer amazon-q-developer Bot left a comment

Choose a reason for hiding this comment

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

Summary

This PR successfully adds Kotlin structural support to the scanner with comprehensive coverage of Spring Security and Ktor frameworks. The implementation is thorough and well-tested.

Key Additions:

  • ✅ Parser integration with tree-sitter-kotlin-ng v1.1
  • ✅ File discovery for .kt and .kts extensions in both structural and deep scan modes
  • ✅ 8 high-confidence Kotlin rules covering Spring Security (@PreAuthorize, @secured, @RolesAllowed, hasRole/hasAuthority calls, role checks) and Ktor (authenticate blocks, plugin installation)
  • ✅ All rules properly embedded in src/rules/embedded.rs
  • ✅ Comprehensive test coverage: 17 matcher tests + 1 dedup test, 18 inline rule-TOML tests
  • ✅ Real-world corpus validation (ktor-samples: 13 findings, 0 false positives)

Implementation Quality:
The Kotlin integration follows established patterns from Java/C# language additions. The annotation handling using (^|\.)Annotation$ regex on user_type captures is a clever solution to handle both bare and fully-qualified annotation forms in a single rule, avoiding duplicate matches. Tests demonstrate proper handling of edge cases like multi-string @Secured("A", "B") with deduplication.

No blocking issues found. The code is ready to merge.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rules/kotlin/role-equals-check.toml`:
- Around line 10-17: The matcher currently captures any binary_expression with a
navigation_expression identifier (`@prop`) and a string_literal (`@role_value`) but
doesn't constrain the operator, causing false positives for !=; update the query
in rules/kotlin/role-equals-check.toml to require the equality operator by
adding an operator constraint to the binary_expression (e.g. specify operator:
"==") so the pattern only matches expressions using == (keep the existing
navigation_expression/identifier `@prop` and string_literal `@role_value` bindings).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6c88411b-5c97-411e-aaa2-a781d1324780

📥 Commits

Reviewing files that changed from the base of the PR and between 9371b5d and d091b12.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • AGENTS.md
  • Cargo.toml
  • README.md
  • docs/DESIGN.md
  • docs/corpus/README.md
  • docs/corpus/kotlin.md
  • rules/kotlin/has-role-call.toml
  • rules/kotlin/ktor-authenticate-block.toml
  • rules/kotlin/ktor-install-authentication.toml
  • rules/kotlin/role-collection-contains.toml
  • rules/kotlin/role-equals-check.toml
  • rules/kotlin/roles-allowed.toml
  • rules/kotlin/spring-preauthorize.toml
  • rules/kotlin/spring-secured.toml
  • src/deep/candidate.rs
  • src/rules/embedded.rs
  • src/scanner/discovery.rs
  • src/scanner/matcher.rs
  • src/scanner/parser.rs

Comment thread rules/kotlin/role-equals-check.toml
boorad added 2 commits May 28, 2026 22:17
Adds Kotlin to the structural scanner: tree-sitter-kotlin-ng grammar,
discovery for .kt/.kts, and eight rules covering Spring Security
(@PreAuthorize, @secured, @RolesAllowed, hasRole/hasAuthority calls,
inline role equality, role-collection membership) plus Ktor
(authenticate {} blocks and install() of auth-adjacent plugins).

Includes a ktor-samples corpus run in docs/corpus/kotlin.md (13
structural findings, no false positives).
Without the operator constraint, the binary_expression query matched
any operator (==, !=, ===, etc.), causing false positives on
user.role != "admin". Pin the field to == and add negative tests
for the !=  case at both the rule-TOML and matcher layer.
@boorad boorad force-pushed the feat/kotlin-structural branch from d091b12 to eacb96b Compare May 29, 2026 02:22
Copy link
Copy Markdown

@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.

🧹 Nitpick comments (1)
rules/kotlin/spring-secured.toml (1)

46-71: ⚡ Quick win

Add a multi-role @Secured test to lock in the behavior described in comments.

Lines 7-11 describe handling multi-role annotations (e.g., @Secured("A", "B")), but current tests only cover single-role inputs. Add one test with multiple role strings so this behavior doesn’t regress silently.

Suggested test addition
 [[rule.tests]]
 input = """
 class UserController {
     `@org.springframework.security.access.annotation.Secured`("ROLE_ADMIN")
     fun deleteUser(id: Long) { }
 }
 """
 expect_match = true
 
+[[rule.tests]]
+input = """
+class UserController {
+    `@Secured`("ROLE_ADMIN", "ROLE_AUDITOR")
+    fun deleteUser(id: Long) { }
+}
+"""
+expect_match = true
+
 [[rule.tests]]
 input = """
 class UserController {
     `@Override`
     fun deleteUser(id: Long) { }
 }
 """
 expect_match = false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rules/kotlin/spring-secured.toml` around lines 46 - 71, The test suite for
the Secured rule lacks a case covering multi-role annotations, so add a new
[[rule.tests]] block in rules/kotlin/spring-secured.toml containing an input
that uses `@Secured` with multiple role strings (e.g., `@Secured`("ROLE_A",
"ROLE_B")) and set expect_match = true to lock in the described multi-role
handling; place it alongside the existing [[rule.tests]] entries that use
`@Secured` and fully-qualified `@org.springframework`...Secured to ensure the rule
continues to match multi-role annotations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@rules/kotlin/spring-secured.toml`:
- Around line 46-71: The test suite for the Secured rule lacks a case covering
multi-role annotations, so add a new [[rule.tests]] block in
rules/kotlin/spring-secured.toml containing an input that uses `@Secured` with
multiple role strings (e.g., `@Secured`("ROLE_A", "ROLE_B")) and set expect_match
= true to lock in the described multi-role handling; place it alongside the
existing [[rule.tests]] entries that use `@Secured` and fully-qualified
`@org.springframework`...Secured to ensure the rule continues to match multi-role
annotations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 10a8faf0-fa4b-4183-b90d-69d14d22c016

📥 Commits

Reviewing files that changed from the base of the PR and between d091b12 and eacb96b.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • AGENTS.md
  • Cargo.toml
  • README.md
  • docs/DESIGN.md
  • docs/corpus/README.md
  • docs/corpus/kotlin.md
  • rules/kotlin/has-role-call.toml
  • rules/kotlin/ktor-authenticate-block.toml
  • rules/kotlin/ktor-install-authentication.toml
  • rules/kotlin/role-collection-contains.toml
  • rules/kotlin/role-equals-check.toml
  • rules/kotlin/roles-allowed.toml
  • rules/kotlin/spring-preauthorize.toml
  • rules/kotlin/spring-secured.toml
  • src/deep/candidate.rs
  • src/rules/embedded.rs
  • src/scanner/discovery.rs
  • src/scanner/matcher.rs
  • src/scanner/parser.rs
✅ Files skipped from review due to trivial changes (5)
  • AGENTS.md
  • src/deep/candidate.rs
  • docs/DESIGN.md
  • README.md
  • docs/corpus/kotlin.md
🚧 Files skipped from review as they are similar to previous changes (13)
  • Cargo.toml
  • docs/corpus/README.md
  • rules/kotlin/role-collection-contains.toml
  • rules/kotlin/ktor-install-authentication.toml
  • rules/kotlin/role-equals-check.toml
  • rules/kotlin/ktor-authenticate-block.toml
  • rules/kotlin/has-role-call.toml
  • src/scanner/parser.rs
  • src/rules/embedded.rs
  • rules/kotlin/roles-allowed.toml
  • rules/kotlin/spring-preauthorize.toml
  • src/scanner/matcher.rs
  • src/scanner/discovery.rs

@boorad boorad merged commit b853bc0 into main May 29, 2026
2 checks passed
@boorad boorad deleted the feat/kotlin-structural branch May 29, 2026 02:27
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.

Structural scanner support for Kotlin

1 participant