Skip to content

Add the queries-path flag to the scanner binary#205

Merged
barbiergaspard merged 2 commits into
mainfrom
gaspard.barbier/query-path-flag
Jun 29, 2026
Merged

Add the queries-path flag to the scanner binary#205
barbiergaspard merged 2 commits into
mainfrom
gaspard.barbier/query-path-flag

Conversation

@barbiergaspard

@barbiergaspard barbiergaspard commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Motivation

This PR allows the user to define a local directory from which the IaC rules are fetched. This is useful for testing purposes when changing the rules.

Changes

  • Added a --queries-path flag
  • Changed the values of QueriesPath and ChangedDefaultQueryPath scan parameters if the flag is used
  • Modified the README.md to reflect previous changes

Author Checklist

  • I have reviewed my own PR.
  • I have added or updated relevant unit tests where necessary. If no tests are added, I've explained why.
  • All new and existing tests pass.
  • I have tested my changes on staging (if applicable).
  • I have updated any relevant documentation (if applicable).

QA Instruction

  • Run a scan on your chosen repository
  • Clone the datadog-iac-scanner-default-rules
  • Either do some relevant changes to a rule, or choose a subdirectory from the rules repo (not containing every rules that flagged a violation in the first scan)
  • Rerun the scan using -q QUERYDIR
  • Verify that the findings are in line with the flag you just used

Blast Radius

This change impacts the query fetching of the IaC scanner

Additional Notes

If you need to share anything else along with your PR, please do it here.

I submit this contribution under the Apache-2.0 license.

barbiergaspard commented Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@datadog-prod-us1-6

datadog-prod-us1-6 Bot commented Jun 22, 2026

Copy link
Copy Markdown

🎯 Code Coverage (details)
Patch Coverage: 66.67%
Overall Coverage: 49.41% (+0.08%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 2510df1 | Docs | Datadog PR Page | Give us feedback!

@barbiergaspard
barbiergaspard force-pushed the gaspard.barbier/query-path-flag branch 5 times, most recently from 09919ca to fced47c Compare June 22, 2026 12:18
@barbiergaspard
barbiergaspard marked this pull request as ready for review June 22, 2026 12:26
@barbiergaspard
barbiergaspard requested a review from a team as a code owner June 22, 2026 12:26

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fced47cbb6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread cmd/scanner/scan.go
Comment on lines +173 to +177
queriesPath := c.StringSlice("queries-path")
changedDefaultQueryPath := len(queriesPath) > 0
if !changedDefaultQueryPath {
queriesPath = []string{"./assets/queries"}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate custom query paths before disabling defaults

When a user supplies -q with a mistyped or empty directory, this marks the scan as using a custom ruleset and later causes createQuerySource to bypass the Datadog rule source. The filesystem loader only logs missing/unreadable query paths and returns an empty query list, so the scan can complete with zero rules and no findings instead of failing. Please validate the supplied paths or fail when no local queries are discovered for a custom queries-path.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

True

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Just updated the branch to fix this. The scan will now fail in (one of) the provided path(s) is invalid or not a directory

@barbiergaspard
barbiergaspard force-pushed the gaspard.barbier/query-path-flag branch 2 times, most recently from c1a0cdc to ab97dfd Compare June 23, 2026 07:51
@barbiergaspard

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab97dfd288

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread pkg/engine/source/filesystem.go Outdated
var dirs []string
for _, src := range s.Source {
entries, err := os.ReadDir(src)
err := filepath.WalkDir(src, func(path string, d os.DirEntry, err error) error {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Follow symlinked query directories

When --queries-path points at a symlink to a directory, scan.go accepts it because os.Stat follows the symlink, but filepath.WalkDir does not follow symlinks and reports the root entry as non-directory. In that scenario no local rule directories are discovered, so the scan can proceed with zero custom queries and produce a false clean result; resolve the source path or handle a symlinked root before walking it.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As we discussed on slack, should fix

@whitemerch whitemerch left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It might be worth it overall some tests, either a table-driven test like in scan_test.go (or an E2E fixture similar to test/e2e/e2e_test.go) covering at least: valid dir, non-existent path, path-is-a-file, and symlink-to-dir. It's exhaustive, feel free to add more test gaps, but that's what code coverage is made for here, which is to make you assess if the changes you are introducing are safe enough

Comment thread cmd/scanner/scan.go

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

--queries-path paths are not resolved to absolute paths, which is wrong.

Maybe you could do like the other params, and do something like:

queriesPath, err = getAbsolutePaths(queriesPath) if err != nil { return errorWithExitCode(fmt.Errorf("invalid queries path: %w", err), constants.InvalidConfigErrorCode) }

Comment thread README.md
datadog-iac-scanner scan -p REPODIR -o OUTPUTDIR -q QUERYDIR
```
The rule directories in the QUERYDIR directory must contain a 'query.rego' and a 'metadata.json' file. You can also specify multiple paths:
```bash

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There should be a blank line between the paragraph and the fence

Comment thread pkg/engine/source/filesystem.go Outdated
var dirs []string
for _, src := range s.Source {
entries, err := os.ReadDir(src)
err := filepath.WalkDir(src, func(path string, d os.DirEntry, err error) error {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As we discussed on slack, should fix

@barbiergaspard
barbiergaspard force-pushed the gaspard.barbier/query-path-flag branch from ab97dfd to 8637be8 Compare June 24, 2026 13:39
evaluated, err := filepath.EvalSymlinks(src)
if err != nil {
contextLogger.Debug().Msgf("localQueryDirs: skipping %s: %v", src, err)
continue

@barbiergaspard barbiergaspard Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This part puzzled me. Apparently we used to just skip a directory if the path was invalid. To me, it makes more sense to stop there instead of just ignoring the directory, so I changed this part. Lmk if I should revert this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

With return nil, if you do -q path1 -q path2 and path1 fails EvalSymlinks, you lose all queries from path2 with no error propagated upward. That's the worst of both worlds: it silently drops valid sources without telling the caller anything failed

@barbiergaspard
barbiergaspard force-pushed the gaspard.barbier/query-path-flag branch from 8637be8 to fd6d7a5 Compare June 24, 2026 14:53
Comment thread cmd/scanner/scan.go
changedDefaultQueryPath := len(queriesPath) > 0
if !changedDefaultQueryPath {
queriesPath = []string{"./assets/queries"}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

validateQueriesPaths already calls getAbsolutePaths, then os.Stat on each result, then checks IsDir. The block immediately after in runScan repeats exactly those two checks on the already-validated queriesPath slice, so you are basically performing a second dead loop

Comment thread cmd/scanner/scan.go Outdated
queriesPath := c.StringSlice("queries-path")
queriesPath, err = validateQueriesPaths(queriesPath)
if err != nil {
return errorWithExitCode(fmt.Errorf("invalid queries path %q", err), constants.InvalidConfigErrorCode)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

err here is the error value returned by validateQueriesPaths, not a path string. %q formats its argument as a quoted Go string literal, so this would produce something like invalid queries path "invalid queries path "/some/path"", quoting the inner error message rather than wrapping it

evaluated, err := filepath.EvalSymlinks(src)
if err != nil {
contextLogger.Debug().Msgf("localQueryDirs: skipping %s: %v", src, err)
continue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

With return nil, if you do -q path1 -q path2 and path1 fails EvalSymlinks, you lose all queries from path2 with no error propagated upward. That's the worst of both worlds: it silently drops valid sources without telling the caller anything failed

Comment thread pkg/engine/source/filesystem.go Outdated
if err != nil {
contextLogger.Debug().Msgf("localQueryDirs: skipping %s: %v", src, err)
continue
contextLogger.Debug().Msgf("localQueryDirs: error evaluting %s: %v", src, err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

evaluating, not evaluting

Comment thread cmd/scanner/scan_test.go Outdated
assert.True(t, filepath.IsAbs(got[0]))
})
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Missing newline at EOF, and there is an error on the diff actually

Comment thread cmd/scanner/scan_test.go
}
}


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: keep it one line in between the func, it's the convention

@barbiergaspard
barbiergaspard force-pushed the gaspard.barbier/query-path-flag branch 3 times, most recently from fb2dff3 to 39aba83 Compare June 25, 2026 08:48

@whitemerch whitemerch left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We are almost there!

An existing but empty --queries-path disables default Datadog rules and completes successfully with zero rules. I reproduced this locally with scanner, it exited 0 with 0 rules found 0 violations. That can create false-clean scans when users point at the wrong directory or an empty checkout. Maybe the custom path flow should fail when discovery finds no valid rule directories

Comment thread pkg/engine/source/filesystem_test.go Outdated

source := NewFilesystemSource(ctx, src, []string{""}, []string{""}, "", true)

got, _ := source.localQueryDirs(ctx)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The new localQueryDirs tests discard the returned error, so invalid-path and mixed-path cases don’t actually assert the error propagation this PR relies on. Add wantErr assertions, ideally through GetQueries if you want to lock public behavior

@barbiergaspard
barbiergaspard force-pushed the gaspard.barbier/query-path-flag branch from 39aba83 to da03d70 Compare June 25, 2026 10:22
@whitemerch

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: da03d709ed

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cmd/scanner/scan.go
Comment on lines +209 to +213
QueriesPath: queriesPath,
ChangedDefaultQueryPath: changedDefaultQueryPath,
LibrariesPath: "./assets/libraries",
ReportFormats: []string{"sarif"},
Platform: selectPlatforms(c.StringSlice("type")),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve custom platforms when using local queries

When -q points at local rules whose metadata platform is supported by the engine but is not in pkg/platforms.Supported (for example OpenAPI, Pulumi, Buildah, or AzureResourceManager), the platform list here still goes through selectPlatforms, which intersects with only the published Datadog platform list and drops those values even if the user passes -t OpenAPI. Because ChangedDefaultQueryPath then switches the scan to FilesystemSource, those local rules are never loaded/scanned; preserve raw custom platform values or use the full parser/source platform set when local queries are selected.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thoughts on this @whitemerch ? Not sure this is relevant. It's not really in the scope of this PR, but we could use it to decide if we want to gate the platforms to only the ones WE support, or if we want to allow for arbitrary platform. I'd personally choose the former, but I'm not sure

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not relevant

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

QueriesPath: queriesPath,
ChangedDefaultQueryPath: changedDefaultQueryPath,
LibrariesPath: "./assets/libraries",
ReportFormats: []string{"sarif"},
Platform: selectPlatforms(c.StringSlice("type")),

P2 Badge Preserve custom platforms when using local queries

When -q points at local rules whose metadata platform is supported by the engine but is not in pkg/platforms.Supported (for example OpenAPI, Pulumi, Buildah, or AzureResourceManager), the platform list here still goes through selectPlatforms, which intersects with only the published Datadog platform list and drops those values even if the user passes -t OpenAPI. Because ChangedDefaultQueryPath then switches the scan to FilesystemSource, those local rules are never loaded/scanned; preserve raw custom platform values or use the full parser/source platform set when local queries are selected.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

This allows the user to choose a local query repository to test their
own rules.
@barbiergaspard
barbiergaspard force-pushed the gaspard.barbier/query-path-flag branch from da03d70 to f4324d9 Compare June 26, 2026 13:49
Change the createServices function to point to a directory containing queries.
The localQueryDirs function now returns an error if no queries directory is found.

Remove a capital letter from an error message

Create custom error in localQueryDirs so that tests are not susceptible to os
differences.
@barbiergaspard
barbiergaspard force-pushed the gaspard.barbier/query-path-flag branch from 05001e3 to 2510df1 Compare June 26, 2026 15:02
@barbiergaspard
barbiergaspard merged commit 728e9a8 into main Jun 29, 2026
19 checks passed
@barbiergaspard
barbiergaspard deleted the gaspard.barbier/query-path-flag branch June 29, 2026 06:58
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