Skip to main content
Prowler empowers users to extend and adapt cloud security coverage by making checks configurable through the use of the audit_config object. This approach enables customization of checks to meet specific requirements through a configuration file.

Understanding the audit_config Object

The audit_config object is a dictionary attached to each provider’s service client (for example, <service_name>_client.audit_config). This object loads configuration values from the main configuration file (prowler/config/config.yaml). Use audit_config to make checks flexible and user-configurable.

Using audit_config to Configure Checks

Retrieve configuration values in a check by using the .get() method on the audit_config object. For example, to get the minimum number of Availability Zones for Lambda from the configuration file, use the following code. If the value is not set in the configuration, the check defaults to 2:
Always provide a default value in .get() to ensure the check works even if the configuration is missing the variable.

Example: Security Group Rule Limit

ec2_securitygroup_with_many_ingress_egress_rules.py

Required File Updates for Configurable Variables

When adding a new configurable check to Prowler, update the following files:
  • Configuration File: Add the new variable under the relevant provider or service section in prowler/config/config.yaml.
  • Provider Schema: Add the typed field to the provider’s Pydantic schema in prowler/config/schema/<provider>.py. This is required: the loader validates user configs against these schemas and the shipped config.yaml must round-trip with zero warnings. See Adding a Parameter to the Provider Schema below.
  • Test Fixtures: If tests depend on this configuration, add the variable to tests/config/fixtures/config.yaml.
  • Documentation: Document the new variable in the list of configurable checks in Configuration File (docs/user-guide/cli/tutorials/configuration_file.mdx).
For a complete list of checks that already support configuration, see the Configuration File Tutorial.
Because a configurable check’s verdict depends on the audit_config value it reads, a compliance requirement can lose meaning if the scan ran with a looser threshold than the control demands. Compliance frameworks can guard against this with configuration guardrails: a requirement declares the strictest configuration it tolerates and is forced to FAIL when the scan’s config falls short. See Configuration Guardrails for Requirements.

Adding a Parameter to the Provider Schema

Most providers have a typed Pydantic schema in prowler/config/schema/, registered in prowler/config/schema/registry.py. When a config is loaded and the provider has a registered schema, validate_provider_config checks each user-supplied key against it, logs a warning, and drops any field that fails validation. The consumer’s .get(key, default) then falls back to the built-in default. Providers without a registered schema are passed through unchanged. This catches typos in a value (for example, 0.2 typed as 20, or "medium" for an enum that expects "MEDIUM"). It does NOT catch typos in a key name: disalowed_regions (one l missing) is treated as an unknown key and passes through untouched, because third-party check plugins legitimately rely on unknown keys being preserved. Reviewers should still check that any new key the YAML adds is named exactly the same as the field on the schema.

Where to Add the Field

  1. Open prowler/config/schema/<provider>.py (for example, aws.py).
  2. Add a field on the provider’s schema class. Always make it Optional[...] = None so the absence of the key is valid.
  3. Apply the tightest type the value allows. Examples below.
If you are introducing an entirely new provider rather than a new parameter, also add an entry mapping the provider name to its schema class in prowler/config/schema/registry.py. The loader uses that registry to find the schema for the provider it is loading.

Choosing the Right Type

Prefer Literal[...] over str whenever the value is one of a known set. Prefer Field(gt=0) over int whenever zero or negative would be nonsensical. The point of the schema is to catch real-world mistakes that previously passed silently.

Custom Validators (Only When Needed)

If the value has structural rules beyond type and range, add a field_validator. Examples already in aws.py:
  • _validate_port_range rejects ports outside 0..65535.
  • _validate_account_ids rejects anything that isn’t a 12-digit AWS account ID.
  • _validate_trusted_ips rejects entries that aren’t a valid IP or CIDR.
Raise ValueError from the validator. The framework converts the error into a warning and drops the offending key.

Example: Adding a New Parameter

Say a new check needs max_iam_role_session_hours, a strictly positive integer that defaults to 12 in code.
  1. Schema (prowler/config/schema/aws.py):
  2. Shipped config (prowler/config/config.yaml):
  3. Consumer (the check):
  4. Tests in tests/config/schema/aws_schema_test.py:
    • one test for a valid value that round-trips,
    • one test for an invalid value (zero, negative, wrong type) that is dropped.

What the Loader Guarantees

  • Unknown keys pass through. Third-party check plugins can introduce arbitrary keys without schema edits; they will not be filtered.
  • Invalid values never crash the run. They produce a single warning per field and the key is dropped.
  • Coerced values are normalized. A YAML-quoted "180" for an int field arrives downstream as the integer 180.
  • The shipped config.yaml must round-trip cleanly. The integration test test_shipped_default_config_loads_without_warnings will fail if a key is added to the YAML without a matching schema field, so the two stay in sync.

Configuration Value Limits

Configurable thresholds enforce hard limits. A value outside the documented range is dropped with a warning and the check falls back to its built-in default (the same as if the key were absent). These bounds are intentionally conservative: they are not the absolute service maxima but the range that still produces a meaningful security check. Use this section as the reference when upgrading an existing config: if a value you set is being rejected, it is outside the range below. Only fields with a numeric range, a fixed value set, or a length cap are listed. Fields typed as free-form strings or lists (for example disallowed_regions, secrets_ignore_patterns, trusted_account_ids) have no range limit — they are validated for shape only (a 12-digit account ID, a valid IP/CIDR, a dotted version string), not for magnitude.

AWS

Azure

GCP

Kubernetes

M365

GitHub

Cloudflare

MongoDB Atlas

Vercel

These bounds live in the provider schemas under prowler/config/schema/; each field’s Field(ge=..., le=...) (or field_validator) is the source of truth and the descriptions there carry the full rationale. This approach ensures that checks are easily configurable, making Prowler highly adaptable to different environments and requirements.