Steampunk Spotter

Spotter Custom Policies 102: Detecting Sensitive Data in Variables and Beyond

January 22, 2025 - Words by  Nejc Slabe - 6 min read

Card image caption

In our first post, Spotter Custom Policies 101 , we explored how Steampunk Spotter’s custom policies empower teams to tailor their automation checks. Today, we’re diving deeper into a critical use case—detecting potential sensitive data across not just playbooks, but also variable files, and other related content.

Modern IT environments are rich with automation, but they also pose unique security challenges. Ansible, as powerful as it is, doesn’t inherently prevent sensitive information from slipping into places it shouldn’t. Enter Spotter, with its ability to catch these vulnerabilities before they reach production.

A Story of Automation Excellence: Meet Sarah

Sarah, a security compliance officer at a global enterprise, was tasked with auditing logs and preventing misconfigurations across the company’s infrastructure. One of Sarah’s focus areas was ensuring Ansible playbooks adhered to strict compliance and security standards. While the company used tools with pre-built checks, they weren’t sufficient to address the specific compliance needs of Sarah’s organization. When Sarah discovered the power of custom policies in Steampunk Spotter, her workflow transformed.

This series follows Sarah’s journey as she harnesses the potential of custom policies to tackle misconfigurations and compliance challenges head-on.

Why Sensitive Data Detection Matters

Sarah’s team relies heavily on automation to manage their infrastructure, but during a routine review, she noticed something alarming—a sensitive API key had been hardcoded into a variable file and committed to their repository. It was a wake-up call.

Despite the robust automation tools at her disposal, Sarah realized they lacked a mechanism to catch such oversights. By creating a tailored sensitive data detection policy, Sarah was able to proactively safeguard her team’s automation workflows and prevent future incidents.

Imagine this: a company name, API key, or password inadvertently makes its way into a variable file. It’s not in the playbook itself, so conventional Ansible linting or scanning tools miss it. Now it’s exposed to anyone who accesses your automation. The risk? Unauthorized access, compliance violations, or even reputational damage.

With Spotter’s custom policies, you can proactively scan for sensitive data in all ansible-related content—not just playbooks.

AWS Compliance examples

Here we have an Playbook example that will create a Security Group on AWS and spin up and EC2 instance, then with the help of two custom policies we will check the Playbook if there are some potencial security issues inside.

---
- hosts: all
  connection: local
  gather_facts: false

  tasks:
    - name: Create security group.
      amazon.aws.ec2_security_group:
        name: "web-app-sec"
        description: "Sec group for app web-app"
        region: "eu-west-1"
        access_key: "sdafrgeg3wfw"  ## Acess Key as plaintext
        rules:
          - proto: tcp
            from_port: 22
            to_port: 22
            cidr_ip: 0.0.0.0/0
          - proto: tcp
            to_port: 80
            cidr_ip: 0.0.0.0/0
      register: result_sec_group

    - name: EC2 instance create.
      amazon.aws.ec2_instance:
        name: "VM_for_demo"
        vpc_subnet_id: subnet-5ca1ab1e
        instance_type: t2.micro
        key_name: "prod-ssh-key"
        security_group: "default" ## Default Security Group
        volumes:
          - device_name: /dev/sda1
            ebs:
              volume_size: 64
              delete_on_termination: true
        image_id: ami-08c947c038321a605
        network:
          assign_public_ip: true
        tags:
          demo: VM

Access key as plaintext detection for AWS

package Spotter

# Check if the access key is not written as plain text.
SpotterPolicy[result] {
  task := input.tasks[i]
  task_args := task.task_args["amazon.aws.ec2_security_group"].access_key
  regex.match("{{.*}}", task_args) == false # Regex to check if there is a variable structure.

  result := {
	"correlation_id": task.task_id,
	"check_type": "TASK",
   "subcode": "PlainText_Variable",
	"message": "Access key should be written as a variable, not plain text! Use Ansible Vault insted."
	}
}

This policy ensures access keys are stored securely as variables or vault entries instead of being hardcoded. Spotter not only flags the issue but also provides actionable recommendations to remediate these security gaps, helping teams protect sensitive credentials from potential exposure.

AWS EC2 instance in DEFAULT security group

package Spotter

# Check if value of Security group for EC2 instance is not set to default.
SpotterPolicy[result] {
  task := input.tasks[i]
	task_args := task.task_args["amazon.aws.ec2_instance"].security_group

  task_args = "default"

  result := {
	"correlation_id": task.task_id,
	"check_type": "TASK",
	"subcode": "DefaultSecurityGroup",
	"message": "Instances shouldn't be in default security groups."
	}
}

This policy helps enforce best practices by ensuring instances are assigned to custom security groups with well-defined access rules. Spotter identifies these issues early, giving teams the opportunity to adjust configurations and prevent security oversights.

Spotter output

After running spotter scan playbook.yml on a playbook, the following output was generated:


(venv) nejcslabe@ns-ubuntu:~.../spotter-examples$ spotter scan playbook.yml 

Scanning...success. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00

Check results:
playbook.yml:2:3: HINT: [H1601] Plays should always be named using the name parameter.
playbook.yml:7:7: ERROR: [E2300::PlainText_Variable] Access key should be written as a variable, not plain text!.
playbook.yml:23:7: ERROR: [E2300::DefaultSecurityGroup] Instances shouldn't be in default security groups.

Quite nice if you ask me :) Now lets tackle Sarah’s problem.

Creating a Sensitive Data Policy

Let’s look at how we can create a policy to detect sensitive data, such as a company name, in variable files, Play’s, taks’s or other configurations.

Example Ansible Playbook

Sensitive information can often appear in unexpected places, such as variable in var files. For example, consider the following var:

xlab_public_ip: 54.32.31.117

In this example, the term “xlab” is used which could inadvertently expose sensitive or internal information. With Steampunk Spotter’s custom policies, you can detect and flag the use of such terms.

Policy for checking sensitive data

Here’s a sample Rego policy you can implement:

package sensitive_data

import rego.v1

# list of sensitive keywords that one wants to check for
volatile_words := ["xlab", "spotter", "my_company_name"]

# helper functions
_is_volatile_word(volatile_keyword, value) := volatile_keyword if {
	is_string(value)
	escaped = sprintf("(?i)%s", [volatile_keyword])
	regex.match(escaped, value)
}

_is_volatile_value(volatile_keyword, path, value) := result if {
	volatile_word = _is_volatile_word(volatile_keyword, value)
	full_path = concat(".", path)
	result = [full_path, volatile_word]
}

_is_volatile_key(volatile_keyword, path) := result if {
	value = array.reverse(path)[0]
	volatile_word = _is_volatile_word(volatile_keyword, value)
	full_path = concat(".", path)
	result = [full_path, volatile_word]
}

_generate_result(check_type, subcode, correlation_id, message) := {
	"check_type": check_type,
	"subcode": subcode,
	"correlation_id": correlation_id,
	"message": message,
}

_unpack_item(item, args, correlation_id, check_type) := {
	"args": item[args],
	"correlation_id": item[correlation_id],
	"file": item.spotter_metadata.file,
	"check_type": check_type,
}

# Rules for var keys or values
check_var_values contains result if {
	item = _unpack_item(input.variables[_], "variable_args", "variable_id", "VAR")
	[path, value] := walk(item.args) # The "walk" function returns all key-paths and their associated values from "item.args".

	[full_path, volatile_word] := _is_volatile_value(volatile_words[_], path, value)
	message = sprintf("Insecure keyword '%s' used inside %s '%s'.", [volatile_word, "variable", full_path])
	result = _generate_result(item.check_type, "VOLATILE_VALUE", item.correlation_id, message)
}

check_var_keys contains result if {
	item = _unpack_item(input.variables[_], "variable_args", "variable_id", "VAR")
	[path, _] := walk(item.args)

	[full_path, volatile_word] := _is_volatile_key(volatile_words[_], path)
	message = sprintf("Insecure keyword '%s' used inside %s '%s'.", [volatile_word, "variable_name", full_path])
	result = _generate_result(item.check_type, "VOLATILE_KEY", item.correlation_id, message)
}

This policy demonstrates how you can configure Spotter to identify sensitive keywords—whether in a variable name, a value. But we have an extended version of this policy, in our public custom policies library .

Including Ansible variables

Ansible automation encourages reuse of playbooks through allowing to bring variables out of playbooks and storing them in variable files. Use the --include-vars CLI option to include these files in scans of your projects and to send the variables and their values to the Steampunk Spotter backend server.


Use Spotter --include-variables

spotter scan path/to/folder --include-variables

Link to the Docs .

Real-World Applications


1. Project Variable Auditing

Using this custom policy, Spotter can scan variable files for sensitive terms. No more accidental API key or other sensitive data leaks!


2. Variable File Compliance

Many teams maintain Ansible variables in separate YAML files. Spotter ensures that these files don’t include hardcoded sensitive data.


3. CI/CD Pipeline Integration

Extend this policy into your CI/CD workflows to block risky commits at the gate, maintaining security hygiene at every step.


Proactive Security with Spotter

Detecting sensitive data isn’t just about avoiding mistakes — it’s about building trust. With Spotter, you can rest easy knowing your Ansible environment is protected by robust, customizable checks that adapt to your organization’s needs.

Want to try this out? Start by defining your own sensitive keywords. Then, implement the policy in Spotter and see how it elevates your automation security.

Did you miss the first post in this series? Read it here . Ready to take the next step? Get started with Spotter .

Additional Resources

For more details on how to create and manage custom policies in Spotter, check out the following resources:


Found this post useful?

Get our monthly newsletter.

Thank you for subscribing!

Please wait

Processing, please wait...

Keep up with what we do on our social media.