Repository: Checkmarx/kics (language: python)

Issue:
bug(ansible): not detecting yaml inventory since v1.7.11
Since Version 1.7.11 the yaml inventory files are not detected anymore and therefor not scanned.

### Expected Behavior
With v1.7.10 I get the expanded behavior
docker run -t -v /path/to/inventory:/path checkmarx/kics:v1.7.10 scan -p /path

`Scanning with Keeping Infrastructure as Code Secure v1.7.10


Preparing Scan Assets: Done
Executing queries: [---------------------------------------------------] 100.00%

Files scanned: 332
Parsed files: 329
Queries loaded: 292
Queries failed to execute: 0`

and e.g., secrets in them are correct detected
### Actual Behavior
With v1.7.11 no files are detected
docker run -t -v /path/to/inventory:/path checkmarx/kics:latest scan -p /path
`Scanning with Keeping Infrastructure as Code Secure v1.7.11


Files scanned: 0
Parsed files: 0
Queries loaded: 0
Queries failed to execute: 0`

### Steps to Reproduce the Problem
The inventory folder contains multiple yaml files with hosts:
group1.yml
```
---
# group1
group1:
  hosts:
    host1.tld
    host2.tld

# sub group
sub_group:
  hosts:
    host2.tld

groups:
  children:
    sub_group:
    group1:
```
and sub folders group_vars and host_vars with yaml files for vars
group_vars/sub_group.yml
```
---
mysql_innodb_large_prefix: 0
mysql_skip_name_resolve: true
mysql_root_password: 'insecure'
```
### Specifications
-   Version: v1.7.11
-   Platform: host Debian 12



Discussion / hints:
Hi @timo-fc ,

Thank you for your input!
We are checking the situation and we will provide a fix for it asap.
Hello @gabriel-cx sorry for the log delayed response.
The problem still exists in version 1.7.12 with my example playbook.
As fare as I can tell the detection relies on the hierarchy starting with "all:" which is possible but not necessary.

Even the official documentation isn't mentioning it:
https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html#inventory-basics-formats-hosts-and-groups

This file is detected and scanned in 1.7.12
```
---
all:
  children:
    subgroup:
      hosts:
        webserver1:
```
but the corresponding host_vars/webserver1.yml and group_vars/subgroup.yml are not scanned 

an inventory file without all: is not scanned
```
---
webserver:
  hosts:
    webserver1:
```

In Version 1.7.10 everything works as expected. All inventory files and the corresponding group_vars and host_vars files are checked.
Hi @timo-fc ,

Thanks for your input!
I will reopen the issue so we can check it.

Fix patch:
diff --git a/pkg/analyzer/analyzer.go b/pkg/analyzer/analyzer.go
index 8304f7c8f4b..133ed93d86e 100644
--- a/pkg/analyzer/analyzer.go
+++ b/pkg/analyzer/analyzer.go
@@ -1,6 +1,7 @@
 package analyzer
 
 import (
+	"fmt"
 	"os"
 	"path/filepath"
 	"regexp"
@@ -65,6 +66,7 @@ var (
 	cicdOnRegex                                     = regexp.MustCompile(`\s*on:\s*`)
 	cicdJobsRegex                                   = regexp.MustCompile(`\s*jobs:\s*`)
 	cicdStepsRegex                                  = regexp.MustCompile(`\s*steps:\s*`)
+	queryRegexPathsAnsible                          = regexp.MustCompile(fmt.Sprintf(`^.*?%s(?:group|host)_vars%s.*$`, regexp.QuoteMeta(string(os.PathSeparator)), regexp.QuoteMeta(string(os.PathSeparator)))) //nolint:lll
 )
 
 var (
@@ -105,7 +107,7 @@ var (
 		"hosts", "tasks", "become", "with_items", "with_dict",
 		"when", "become_pass", "become_exe", "become_flags"}
 	playBooks               = "playbooks"
-	ansibleHost             = "all"
+	ansibleHost             = []string{"all", "ungrouped"}
 	listKeywordsAnsibleHots = []string{"hosts", "children"}
 )
 
@@ -552,9 +554,17 @@ func checkYamlPlatform(content []byte, path string) string {
 	if checkForAnsibleHost(yamlContent) {
 		return ansible
 	}
+	// add for yaml files contained at paths (group_vars, host_vars) related with ansible
+	if checkForAnsibleByPaths(path) {
+		return ansible
+	}
 	return ""
 }
 
+func checkForAnsibleByPaths(path string) bool {
+	return queryRegexPathsAnsible.MatchString(path)
+}
+
 func checkForAnsible(yamlContent model.Document) bool {
 	isAnsible := false
 	if play := yamlContent[playBooks]; play != nil {
@@ -576,11 +586,13 @@ func checkForAnsible(yamlContent model.Document) bool {
 
 func checkForAnsibleHost(yamlContent model.Document) bool {
 	isAnsible := false
-	if hosts := yamlContent[ansibleHost]; hosts != nil {
-		if listHosts, ok := hosts.(map[string]interface{}); ok {
-			for _, value := range listKeywordsAnsibleHots {
-				if host := listHosts[value]; host != nil {
-					isAnsible = true
+	for _, ansibleDefault := range ansibleHost {
+		if hosts := yamlContent[ansibleDefault]; hosts != nil {
+			if listHosts, ok := hosts.(map[string]interface{}); ok {
+				for _, value := range listKeywordsAnsibleHots {
+					if host := listHosts[value]; host != nil {
+						isAnsible = true
+					}
 				}
 			}
 		}


Test patch:
diff --git a/pkg/analyzer/analyzer_test.go b/pkg/analyzer/analyzer_test.go
index b44a96ae212..3b45f736635 100644
--- a/pkg/analyzer/analyzer_test.go
+++ b/pkg/analyzer/analyzer_test.go
@@ -414,6 +414,19 @@ func TestAnalyzer_Analyze(t *testing.T) {
 			excludeGitIgnore:     false,
 			MaxFileSize:          3,
 		},
+		{
+			name:                 "analyze_ansible_by_path",
+			paths:                []string{filepath.FromSlash("../../test/fixtures/ansible_project_path")},
+			wantTypes:            []string{"ansible"},
+			wantExclude:          []string{},
+			typesFromFlag:        []string{""},
+			excludeTypesFromFlag: []string{""},
+			wantLOC:              54,
+			wantErr:              false,
+			gitIgnoreFileName:    "",
+			excludeGitIgnore:     false,
+			MaxFileSize:          -1,
+		},
 	}
 
 	for _, tt := range tests {
diff --git a/test/fixtures/ansible_project_path/group_vars/db_servers.yml b/test/fixtures/ansible_project_path/group_vars/db_servers.yml
new file mode 100644
index 00000000000..03074a7d813
--- /dev/null
+++ b/test/fixtures/ansible_project_path/group_vars/db_servers.yml
@@ -0,0 +1,3 @@
+---
+# group_vars/db_servers.yml
+db_port: 3306
diff --git a/test/fixtures/ansible_project_path/group_vars/web_servers.yml b/test/fixtures/ansible_project_path/group_vars/web_servers.yml
new file mode 100644
index 00000000000..a886f69717f
--- /dev/null
+++ b/test/fixtures/ansible_project_path/group_vars/web_servers.yml
@@ -0,0 +1,3 @@
+---
+# group_vars/web_servers.yml
+apache_port: 80
diff --git a/test/fixtures/ansible_project_path/playbook.yml b/test/fixtures/ansible_project_path/playbook.yml
new file mode 100644
index 00000000000..8b6a2a37fcc
--- /dev/null
+++ b/test/fixtures/ansible_project_path/playbook.yml
@@ -0,0 +1,13 @@
+---
+# playbook.yml
+- name: Configure web servers
+  hosts: web_servers
+  roles:
+    - common
+    - web
+
+- name: Configure database servers
+  hosts: db_servers
+  roles:
+    - common
+    - db
diff --git a/test/fixtures/ansible_project_path/roles/common/tasks/main.yml b/test/fixtures/ansible_project_path/roles/common/tasks/main.yml
new file mode 100644
index 00000000000..65052fc7d6f
--- /dev/null
+++ b/test/fixtures/ansible_project_path/roles/common/tasks/main.yml
@@ -0,0 +1,7 @@
+---
+# roles/common/tasks/main.yml
+- name: Update packages
+  package:
+    name: "*"
+    state: latest
+  become: yes
diff --git a/test/fixtures/ansible_project_path/roles/db/tasks/main.yml b/test/fixtures/ansible_project_path/roles/db/tasks/main.yml
new file mode 100644
index 00000000000..b4b6fa85883
--- /dev/null
+++ b/test/fixtures/ansible_project_path/roles/db/tasks/main.yml
@@ -0,0 +1,14 @@
+---
+# roles/db/tasks/main.yml
+- name: Ensure MySQL is installed
+  package:
+    name: mysql-server
+    state: present
+  become: yes
+
+- name: Ensure MySQL is running
+  service:
+    name: mysql
+    state: started
+    enabled: yes
+  become: yes
diff --git a/test/fixtures/ansible_project_path/roles/web/tasks/main.yml b/test/fixtures/ansible_project_path/roles/web/tasks/main.yml
new file mode 100644
index 00000000000..6f9db1738f3
--- /dev/null
+++ b/test/fixtures/ansible_project_path/roles/web/tasks/main.yml
@@ -0,0 +1,14 @@
+---
+# roles/web/tasks/main.yml
+- name: Ensure Apache is installed
+  package:
+    name: apache2
+    state: present
+  become: yes
+
+- name: Ensure Apache is running
+  service:
+    name: apache2
+    state: started
+    enabled: yes
+  become: yes