feat(core): add asyncapi security-defined lint rule#2759
Conversation
🦋 Changeset detectedLatest commit: fff7322 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
vadyvas
left a comment
There was a problem hiding this comment.
I would suggest a slightly different approach:
- keep the AsyncAPI logic separate and do not reuse shared logic from the OAS rule
- use the same rule name,
security-defined, for AsyncAPI as well, and register the AsyncAPI implementation in the AsyncAPI ruleset - do not update the v1 docs in this PR
I think this would make the change smaller, clearer, and safer.
Thank you for the contribution, overall the PR looks good
vadyvas
left a comment
There was a problem hiding this comment.
left a few comments, could you take a look?
| 'info-contact': InfoContact as Async2Rule, | ||
| 'info-license-strict': InfoLicenseStrict as Async2Rule, | ||
| 'operation-operationId': OperationOperationId as Async2Rule, | ||
| 'security-defined': SecurityDefined, |
There was a problem hiding this comment.
Please add support for AsyncAPI 3 as well. Right now the rule only applies to AsyncAPI2
There was a problem hiding this comment.
The code uses the rule name security-defined, but the docs still say asyncapi-operation-security-defined
Can you update related changes?
| @@ -0,0 +1,83 @@ | |||
| # asyncapi-operation-security-defined | |||
There was a problem hiding this comment.
Please don’t add this rule to the v1 docs
Performance Benchmark (Lower is Faster)
|
|
Hey @DmitryAnansky , I have fixed all comments and failing e2e tests and PR is good to review again. Thanks ! |
| ); | ||
| }); | ||
|
|
||
| it('should call createTestContext for arazzo type using the spec form without `workflows` segment', async () => { |
There was a problem hiding this comment.
Why do we need those changes?
There was a problem hiding this comment.
I missed the existing check which was already present hence I agree with you and I should remove this.
|
Hey @Daryna-del , I have addressed all the comments left by you and cursor and also resolved the failing e2e tests. Can you review the recent changes again ? Thanks ! |
| location: itemLocation, | ||
| name, | ||
| refPointer, | ||
| resolved: resolved.node !== undefined, |
There was a problem hiding this comment.
This check treats a null-valued scheme entry as defined, am I right?
Seems that a scheme key with no value (half-finished YAML) silently passes.
There was a problem hiding this comment.
I guess you are correct and I didnt catch it. $ref to a key with a null value resolves to node === null and since null !== undefined was marked as defined and silently passed.
| operation: SecuredOperation | undefined, | ||
| resolve: UserContext['resolve'] | ||
| ): boolean { | ||
| if (operation?.security) return true; |
There was a problem hiding this comment.
This condition might be confusing.
Seems the function consider empty security (e.g. security: []) as Secured operation.
But it is actually public.
And have similar check that will result in opposite verdict:
serverHasSecurity.set(
key.toString(),
Array.isArray(server?.security) && server.security.length > 0
);
| if (rootOperations && rootLocation) { | ||
| const operationsLocation = rootLocation.child(['operations']); | ||
| for (const [opName, opRef] of Object.entries(rootOperations)) { | ||
| const operation = isRef(opRef) ? resolve<Async3Operation>(opRef).node : opRef; |
There was a problem hiding this comment.
Looks like only refs against the root document will be resolved here.
Please double check, but it seems that refs recorded relative to another file never resolve, producing false 'Every operation should have security defined' errors on multi-file docs.
Please check context.resolve functionality, maybe you need to handle this case as well.
| return { | ||
| Root: { | ||
| enter(root, { location }: UserContext) { | ||
| rootServers = root?.servers; |
There was a problem hiding this comment.
Could you please check if you handle the scenario with two files correctly:
# main.yaml
asyncapi: 3.0.0
info:
title: Test
version: 1.0.0
servers:
$ref: './servers.yaml' # ← map-level ref
channels:
myChannel:
address: user/signedup
operations:
sendUserSignedUp:
action: send
channel:
$ref: '#/channels/myChannel'
# servers.yaml — the server IS secured
prod:
host: example.com
protocol: kafka
security:
- type: apiKey
in: user
|
|
||
| function pointsToSecurityScheme(pointer: string): boolean { | ||
| return ( | ||
| pointer.startsWith(SECURITY_SCHEMES_POINTER) && |
There was a problem hiding this comment.
Seems external file references are not handled here.
The AsyncAPI 3.0 specification defines security requirements as an array of Security Scheme Objects, and states the general rule: any time a Schema Object can be used, a Reference Object can be used in its place, allowing referencing definitions instead of defining them inline. The Reference Object itself uses JSON Reference resolution — "For this specification, reference resolution is done as defined by the JSON Reference specification and not by the JSON Schema specification." JSON Reference allows the $ref value to be any URI, which includes relative file paths and remote URLs.
Please check the example. We able to bundle it with ref resolution but this new rule will produce false failure during file lint.
asyncapi: 3.0.0
info:
title: Async3 External Security Ref
version: 1.0.0
servers:
production:
host: broker.example.com
protocol: mqtt
security:
- $ref: './apiKey.yaml'
channels:
userSignups:
address: user/signedup
messages:
userSignedUp:
payload:
type: object
properties:
name:
type: string
operations:
sendUserSignups:
action: send
channel:
$ref: '#/channels/userSignups'
security:
- $ref: './apiKey.yaml'
apiKey.yaml =>
type: httpApiKey
name: api_key
in: header
description: API key security scheme defined in an external fileThere was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ffc7ef8. Configure here.
|
Hey @DmitryAnansky , I have addressed all your comments in my recent fix and I hope they address the issue. If not I'm still ready to improve further. Can you take a look again ? Thanks ! |

What/Why/How?
asyncapi-operation-security-definedrule for AsyncAPI 2.x and 3.x. both which reports when a security scheme referenced from an operation or serversecurityarray is not defined in ``components.securitySchemes.Reference
#2667
Testing
Screenshots (optional)
Check yourself
Security
Note
Medium Risk
Security-related lint logic is new and enabled at error severity in recommended rulesets, so existing AsyncAPI specs may start failing CI; behavior is validation-only with broad edge-case coverage (refs, traits, server applicability).
Overview
Introduces a
security-definedbuilt-in rule for AsyncAPI 2.x and 3.x, parallel to the existing OpenAPI rule. It is registered inasync2Rules/async3Rules, included in preset configs (errorinrecommended/all,warninminimal,offinspec), and covered by a changeset noting that recommended AsyncAPI lint may newly fail.AsyncAPI 2.x validates named schemes on operation/server
securityagainstcomponents.securitySchemes, and flags operations with no effective security when applicable root servers (respecting channel server bindings, traits, and skipping reusablecomponentschannels/servers) are not all secured.AsyncAPI 3.x validates
$ref-based security entries (local refs must target#/components/securitySchemes, unresolved or external refs are checked), resolves map-level$refs onservers/operations, and applies the same “operation must be secured” logic across channels, traits, and multi-file documents.Supporting changes add shared helpers in
rules/utils.ts, richer AsyncAPI typings and visitor nodes, extensive tests, docs/sidebar updates, and a small CLI split typing tweak forcomponents.Reviewed by Cursor Bugbot for commit fff7322. Bugbot is set up for automated code reviews on this repo. Configure here.