Skip to content

🎉🎉🎉 v13 🎉🎉🎉#6511

Merged
arlimus merged 29 commits intomainfrom
v13
Feb 19, 2026
Merged

🎉🎉🎉 v13 🎉🎉🎉#6511
arlimus merged 29 commits intomainfrom
v13

Conversation

@arlimus
Copy link
Copy Markdown
Member

@arlimus arlimus commented Jan 29, 2026

Welcome to cnquery v13 / cnspec v13

Note: I'm writing out the description as things evolve, please ask questions below.

Timeline

  • Feb 02, 2026 - Pre-release starts, all breaking changes happen here. We continue to release v12 and keep this branch open.
  • Feb 16, 2026 - Release candidates starts. v13 is rebased on the latest v12. Only non-breaking changes are introduced now. All features are now pushed to this v13 branch as well, so we can avoid rebases
  • Mar 02, 2026 - Release of v13 into main

User-facing changes

👋 cnquery, 🤗 mql

What's going on: We have a ton of confusion between cnquery and cnspec, explaining both CLIs over and over again.

Let's simplify things: Cnquery will be renamed to MQL, since it's at the core of the querying engine anyway. The providers and all their data are tighly connected to MQL as well. The only element not part of MQL is the execution of querypacks.

We will move querypacks over to cnspec, which already contains policies (and frameworks) anyway. By moving it out, this entire project focuses on data-collection and querying only.

Internal changes

  • Massively improve the recording handling + add recording provider to interact with recordings (kudos @preslavgerchev )

Post v13 cleanup

Stretch goals

breaking (pre-release only)

  • new resources/fields in providers all have a hardcoded minimum version set => use the correct provider version instead
  • codify cross-provider calling
  • lightweight object storage model in MQL
  • sensitive data flagging in MQL
    • sensitive data ingestion from Terraform
  • deprecate mql fields natively + track maturity
    • deprecate all those e.g. gcp.**.projectID fields
  • structured errors in cnquery
    • aws errors with Is400AccessDeniedError need proper error handling, otherwise results appear incorrect

non-breaking (at any point)

  • bug: attaching functions in where-clauses isn't correctly recognized without _. prefix, see https://github.com/mondoohq/server/pull/14241
  • shell:
    • multi-line history
    • up/down to work with history and multiline
  • private MQL calls need to fail linting
    • adjust claude.md to not use private method calls
    • if using a chain where we have both a caller and a resource sharing the name (eg: x { field } and x.field being the resource) then it cannot be private (it has to be public)

Other changes that happened in latest v12, that are now streamlined in v13

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 29, 2026

Test Results

5 091 tests   - 49   5 087 ✅  - 49   2m 22s ⏱️ +9s
  409 suites  -  9       4 💤 ± 0 
   31 files   ± 0       0 ❌ ± 0 

Results for commit 4992f43. ± Comparison against base commit 2a02a86.

This pull request removes 5140 and adds 5091 tests. Note that renamed tests count towards both.
go.mondoo.com/cnquery/v12 ‑ TestFeatureFlags
go.mondoo.com/cnquery/v12 ‑ TestGetLatestVersion
go.mondoo.com/cnquery/v12/apps/cnquery/cmd ‑ TestLoginCmd_AllFlags
go.mondoo.com/cnquery/v12/apps/cnquery/cmd ‑ TestLoginCmd_AllFlags/annotation
go.mondoo.com/cnquery/v12/apps/cnquery/cmd ‑ TestLoginCmd_AllFlags/api-endpoint
go.mondoo.com/cnquery/v12/apps/cnquery/cmd ‑ TestLoginCmd_AllFlags/name
go.mondoo.com/cnquery/v12/apps/cnquery/cmd ‑ TestLoginCmd_AllFlags/providers-url
go.mondoo.com/cnquery/v12/apps/cnquery/cmd ‑ TestLoginCmd_AllFlags/splay
go.mondoo.com/cnquery/v12/apps/cnquery/cmd ‑ TestLoginCmd_AllFlags/timer
go.mondoo.com/cnquery/v12/apps/cnquery/cmd ‑ TestLoginCmd_AllFlags/token
…
go.mondoo.com/mql/v13 ‑ TestFeatureFlags
go.mondoo.com/mql/v13 ‑ TestGetLatestVersion
go.mondoo.com/mql/v13/apps/mql/cmd ‑ TestLoginCmd_AllFlags
go.mondoo.com/mql/v13/apps/mql/cmd ‑ TestLoginCmd_AllFlags/annotation
go.mondoo.com/mql/v13/apps/mql/cmd ‑ TestLoginCmd_AllFlags/api-endpoint
go.mondoo.com/mql/v13/apps/mql/cmd ‑ TestLoginCmd_AllFlags/name
go.mondoo.com/mql/v13/apps/mql/cmd ‑ TestLoginCmd_AllFlags/providers-url
go.mondoo.com/mql/v13/apps/mql/cmd ‑ TestLoginCmd_AllFlags/splay
go.mondoo.com/mql/v13/apps/mql/cmd ‑ TestLoginCmd_AllFlags/timer
go.mondoo.com/mql/v13/apps/mql/cmd ‑ TestLoginCmd_AllFlags/token
…
This pull request removes 4 skipped tests and adds 4 skipped tests. Note that renamed tests count towards both.
go.mondoo.com/cnquery/v12/providers-sdk/v1/vault/gcpberglas ‑ TestGcpBerglas
go.mondoo.com/cnquery/v12/providers/github/connection ‑ TestGithubNeedsFix
go.mondoo.com/cnquery/v12/providers/nmap/resources ‑ TestRawNmap
go.mondoo.com/cnquery/v12/providers/os/resources/sshd ‑ TestParser/key_quoted_arg_with_equal_sign
go.mondoo.com/mql/v13/providers-sdk/v1/vault/gcpberglas ‑ TestGcpBerglas
go.mondoo.com/mql/v13/providers/github/connection ‑ TestGithubNeedsFix
go.mondoo.com/mql/v13/providers/nmap/resources ‑ TestRawNmap
go.mondoo.com/mql/v13/providers/os/resources/sshd ‑ TestParser/key_quoted_arg_with_equal_sign

♻️ This comment has been updated with latest results.

@arlimus arlimus changed the title 🚧🚧🚧 🏗️ v13 🚧🚧🚧 🏗️ v13 🚧 🚧 🚧 Jan 29, 2026
@arlimus arlimus changed the title 🏗️ v13 🚧 🚧 🚧 🏗️ v13 🚧🚧🚧 Jan 30, 2026
@LittleSalkin1806
Copy link
Copy Markdown
Contributor

LittleSalkin1806 commented Jan 30, 2026

Hey @arlimus is this feature list the final one or will in the two weeks from 02.02-16.02 more idears/changes be collected ?

Saw it by accident and am just curious

@arlimus
Copy link
Copy Markdown
Member Author

arlimus commented Jan 30, 2026

Hey @arlimus is this feature list the final one or will in the two weeks from 02.02-16.02 more idears/changes be collected ?

Saw it by accident and am just curious

The doors are open!! We can collect any other breaking features until the 16th :)

Of course we can also add more features after and make them afterwards, it's really just the crazy breaking changes that we can finally make in these 2 weeks

@arlimus
Copy link
Copy Markdown
Member Author

arlimus commented Jan 30, 2026

I added the companion v13 for cnspec here and to the description above: mondoohq/cnspec#2057

@LittleSalkin1806
Copy link
Copy Markdown
Contributor

LittleSalkin1806 commented Jan 30, 2026

I can only point to this where fuzzy search is still missing
#6428
You can argue about all the changes but my main point is.
Case insensitive match / fuzzy matching makes mql safer with an quite easy implementation.

Best Regards!

@arlimus
Copy link
Copy Markdown
Member Author

arlimus commented Jan 30, 2026

I can only point to this where fuzzy search is still missing #6428 You can argue about all the changes but my main point is. Case insensitive match / fuzzy matching makes mql safer with an quite easy implementation.

I have some other input regards aws organization rollout with our 1800 accounts. But i heared you have some topics for that on the board and will probably formulate it after team internal allignements and over kaistierl.

Best Regards!

I got you covered! I flagged it above as "optional chaining of resources" as a todo item for v13 :) We will run down all the policies next week because we need to update/measure the impact of this change. It's tough to do it all in one quick change and keep things stable, but so far I'm optimistic we can get it tackled. I'll share the spec next week, so far I'm thinking optional chaining as seen in ts to make it explicit when users want chaining and error otherwise (as you would in js/ts)

@arlimus
Copy link
Copy Markdown
Member Author

arlimus commented Jan 30, 2026

Let me explicitly call out fuzzy above

@LittleSalkin1806
Copy link
Copy Markdown
Contributor

I know that we will have some allignement calls soon. Without naming this feature requests as they will go over kai. I am just asking as our team is curious if these things are already there or planned. So dont take this as a feature request yet :)

Is there a yaml schema to validate syntax/structure?

Is there a possibility to share/inherit props (variables) between "policies" and global "queries" (planned)?

Which possibilities of automated tests does Mondoo offer? There is a mock provider, but no documentation for it

@arlimus
Copy link
Copy Markdown
Member Author

arlimus commented Jan 30, 2026

Is there a possibility to share/inherit props (variables) between "policies" and global "queries" (planned)? Currently we need to be very repetitive and cant variablize very good.

Is this problem clear or do i need to be explicit ?

Yeah, I think if we add it it is something we can just do on top, since it wouldn't be breaking change. let me track it as a stretch idea, if we hit the v13 great and if not we just do it after

@arlimus
Copy link
Copy Markdown
Member Author

arlimus commented Jan 30, 2026

I know that we will have some allignement calls soon. Without naming this feature requests as they will go over kai. I am just asking as our team is curious if these things are already there or planned. So dont take this as a feature request yet :)

Is there a yaml schema to validate syntax/structure?

Is there a possibility to share/inherit props (variables) between "policies" and global "queries" (planned)?

Which possibilities of automated tests does Mondoo offer? There is a mock provider, but no documentation for it

  • props: Right now we have shared props on the level of the policies and then there is a breakdown into individual queries since every query should be able to stand on their own. But we should discuss if this works for all use-cases and I feel this may not cover everything, which is why I want to learn more
  • we have a validate command in cnspec: cnspec policy lint and also there is a way to require providers now in policies so it won't download every provider. I'm adding a gate to prevent downloading all providers in case the require statement is missing
  • mock: We are pushing a major change in v13 to how recordings work, after that let's improve the docs so you can use it too. We use recordings/mock extensively for testing ourselves, that's the best path, but the docs are crap on it right now

@LittleSalkin1806
Copy link
Copy Markdown
Contributor

LittleSalkin1806 commented Jan 30, 2026

We are in the beginning phase of writing custom policies so i cant give the full picture yet. This needs some more weeks.

We would try to be as modular as we can be and merge the Policy either on CI or reference on the bigger policy file from other smaller policy files (checks or queries).

One reason why we want to be modular is because of git. To avoid MR conflicts when more people work on the same file.
We have one policy file per hyperscaler (GCP, Azure, AWS) etc. then later one framework file.
But this is another topic!

We planned to write and try to write policies similar to what you already shown on your policies

queries can be written under policies.groups.checks.queries or queries

But we find it much more readable to see the whole structure at top under policies and put all the query logic under queries: at the root level of the yaml we name it global queries.

The cnspec policy init command sadly does not give a file with every possibility as example therefore we need to test a lot.

So we said that we define all queries on purpose on the global level part.

Which you also did in your policies for gcp and aws atleast.

For example we have a query which checks for specific tags aws.s3.bucket.tags.where(key.downcase == props.specificTag).all(value.downcase.in([props.speificTagValues]))

This check we will not only use for s3 but for all of them under us + to be continued:

            "AWS::ApiGateway::RestApi",
            "AWS::DynamoDB::Table",
            "AWS::EC2::Instance",
            "AWS::EC2::SecurityGroup",
            "AWS::ElasticLoadBalancingV2::LoadBalancer",
            "AWS::EFS::FileSystem",
            "AWS::RDS::DBInstance",
            "AWS::S3::Bucket",
            "AWS::Elasticsearch::Domain",
            "AWS::OpenSearch::Domain",

To avoid hardcoded values and to enable parameterize logic for different customers we want to define these props once per policy file for the global queries and not on every check.

Currently we either have to hardcode the value, define the props in every 11 checks for just this one requirement or use props under policy.props as they get inherited in every policy.groups.checks.queries which is worse for developer readability with big files.

Summary:

  • shared props for queries and policies

@LittleSalkin1806
Copy link
Copy Markdown
Contributor

We are missing this feature described in the documentation props: under root level are working is working how we want it. Atleast for global queries.
and its in the documentation when you lint you will find the following

 bundle-global-props-deprecated  error    test.mql.yaml  168   Defining global properties in a policy bundle is deprecated. Define properties within individual policies and queries instead. 

So we did not plan with it as we thought it will be potentially removed soon.

  1. We can define props under policies which get inherited under each check of that policy policy.groups.checks.queries
    But not for queries on root level

The other way around we can define props on root level but they are not inherited on quecks under policies.
On top there is a deprecation warning.

Hope this sums it up

philipbalinov and others added 8 commits February 18, 2026 14:54
Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
This introduces optional chaining in MQL. It also changes the behavior
so that by default we do not blindly chain elements anymore but instead
print errors when an element in the chain is `null`.

**Background**

Since MQL and cnspec are often used for security and compliance
policies, we have to create a careful balance between user-comfort and
precision. This means that e.g. a comparison like `user.id == 123` will
work perfectly well, even if we compare strings and numbers, because the
users intention is understood.

However, when chaining calls, we have so far sided on the side of
comfort - maybe a bit too much. The current behavior - which is
optional chaining by default - can lead to cases where the user
intent is misunderstood. It's ok if an AI hallucinates (not really, but
you get the point), but it's not ok for a query/policy engine to lead to
such negative unexpected behaviors.

You can see a full example on display here:
#6428

**Action**

The system makes all chaining mandatory non-null by default. This means
that if you have json like this:

```json
{
  "a": {
    "b": "c"
  }
}
```

and called it with:

```
> parse.json('example.json').params.d.b
```

it would now produce an error:

```
> parse.json('example.json').params.d.b == "c"
[failed] parse.json.params.d.b == "c"
  error: cannot access field "b", parent element is null
```

This errors is new. It's becase the field `d` doesn't exist in this
JSON.

This is where **optional chaining** comes back into the picture: It
allows you to say "please don't print an error, just see if you can get
the value" and thus use the previous behavior of MQL:

```
> parse.json('example.json').params.d?.b == "c"
[failed] parse.json.params.d.[]? == "c"
  expected: == "c"
  actual:   _
```

This is also in line with behaviors in JavaScript and TypeScript.
tldr: Introduce `having` on lists/maps, which acts like a `where` filter that also checks that the resulting list is not empty.

```coffee
my.collection.having( some condition ).all( ... )
```

**Problem**

As explained by @LittleSalkin1806 in #6633 (comment)

> If the bucket has no tags at all, the where clause will return an empty list, the values will take values from no existing key (empty list) and the all function will evaluate to true because there are no elements that violate the condition. This can lead to false positives in the compliance checks.

I ran into this same problem way too often myself! I've been working on a function to address this problem.

The `where` clause behaves like a traiditional `filter` in JS/TS and is close to SQL, so we wanted to keep their behavior/meaning. However, there is clearly a need for the combination, because this pattern happens way too often:

```coffee
collection.where( condition ) != empty
collection.where( condition ).otherCalls...
```

Using @LittleSalkin1806 's example:

```coffee
aws.s3.bucket.tags.where(key.downcase == 'dtit:sec:infosecclass') != empty
aws.s3.bucket.tags.where(key.downcase == 'dtit:sec:infosecclass').values.map(downcase).in([...])
```

**Solution**

This PR introduces the `having` keyword. It acts like `where` that also makes sure that the list is not empty:

```coffee
collection.having( condition ).otherCalls...
```

or with the above example:

```coffee
aws.s3.bucket.tags.having(key.downcase == 'dtit:sec:infosecclass').values.map(downcase).in([ ... ])
```

If the filtered list is empty, the query fails. If it is non-empty, it
uses the filtered values and looks at the next condition.

Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
- Add prerelease: true to goreleaser-unstable config
- Print github.ref, github.ref_name, and github.event_name for debugging

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
We plan to move to new IDs in v14, but we need this release to make it possible, since cross-provider calls are codified from now on.

Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
@github-actions

This comment has been minimized.

@arlimus arlimus changed the title 🏗️ v13 🚧🚧🚧 🎉🎉🎉 v13 🎉🎉🎉 Feb 19, 2026
@arlimus arlimus marked this pull request as ready for review February 19, 2026 03:31
@github-actions

This comment has been minimized.

Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
@arlimus arlimus merged commit d867d96 into main Feb 19, 2026
11 checks passed
@arlimus arlimus deleted the v13 branch February 19, 2026 06:41
@github-actions github-actions bot locked and limited conversation to collaborators Feb 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants