loki.secretfilter
EXPERIMENTAL: This is an experimental component. Experimental components are subject to frequent breaking changes, and may be removed with no equivalent replacement. To enable and use an experimental component, you must set the
stability.levelflag toexperimental.
loki.secretfilter receives log entries and redacts detected secrets from the log lines.
The detection relies on regular expression patterns, defined in the Gitleaks configuration file embedded within the component.
loki.secretfilter can also use a custom configuration file based on the Gitleaks configuration file structure.
Caution
Personally Identifiable Information (PII) isn’t currently in scope and some secrets could remain undetected. This component may generate false positives or redact too much. Don’t rely solely on this component to redact sensitive information.
Note
This component operates on log lines and doesn’t scan labels or other metadata.
Caution
Detecting secrets can be resource-intensive and can increase CPU usage significantly. Roll out this component gradually and monitor resource usage. Place
loki.secretfilterafter components that reduce log volume so it processes fewer lines.
Usage
loki.secretfilter "<LABEL>" {
forward_to = <RECEIVER_LIST>
}Arguments
You can use the following arguments with loki.secretfilter:
The gitleaks_config argument is the path to a custom Gitleaks TOML config file.
The file supports the standard Gitleaks structure (rules, allowlists, and [extend] to extend the default config).
If gitleaks_config is empty, the component uses the default Gitleaks configuration embedded in the component.
Note
The default configuration may change between Alloy versions. For consistent behavior, use an external configuration file via
gitleaks_config.
If you leave origin_label empty, the component sets the origin label on secrets_redacted_by_category_total to "".
Redaction behavior:
- If
redact_withis set, it is used as the replacement string for every detected secret. The supported placeholders are$SECRET_NAME(rule ID) and$SECRET_HASH(SHA1 hash of the secret). - If
redact_withis not set, redaction is percentage-based (Gitleaks-style).redact_percentcontrols how much of the secret is redacted. For example,80shows the first 20% of the secret followed by"...".100replaces the entire secret with"REDACTED". Whenredact_percentis 0 or unset, 80% redaction is used.
Sampling: The rate argument controls what fraction of log entries are processed by the secret filter.
Entries that Alloy does not select based on the sampling rate pass through unchanged, with no detection or redaction applied.
Use a value below 1.0, for example, 0.1 for 10%, to reduce CPU usage when processing high-volume logs.
Monitor loki_secretfilter_entries_bypassed_total to observe how many entries were skipped.
Origin metric: The origin_label argument specifies the Loki label the component uses as the origin dimension in secrets_redacted_by_category_total.
You can track how many secrets were redacted per source or environment.
When origin_label isn’t set, the origin label on secrets_redacted_by_category_total defaults to an empty string.
Processing timeout: The processing_timeout argument sets a maximum duration for processing each log entry.
When the timeout is exceeded, the loki_secretfilter_lines_timed_out_total metric is incremented.
By default (drop_on_timeout = false), Alloy forwards the line and redacts any secrets it detected before the timeout, so no log lines are lost.
When drop_on_timeout = true, entries that exceed the timeout are dropped and the loki_secretfilter_lines_dropped_total metric is incremented.
Set label_timed_out = true to add secretfilter="timed-out" to any entry that Alloy forwards after a timeout.
You can then query timed-out lines in Loki, for example, with {secretfilter="timed-out"}.
Alloy applies this label only to forwarded entries.
Caution
Setting
drop_on_timeout = truemeans log lines can be silently dropped. A dropped line can’t be recovered, whereas an unredacted line containing a secret can still be detected and mitigated later. Use this option only when dropping lines is preferable to forwarding potentially unredacted data.
Blocks
The loki.secretfilter component doesn’t support any blocks. You can configure this component with arguments.
Exported fields
The following fields are exported and can be referenced by other components:
Component health
loki.secretfilter is only reported as unhealthy if given an invalid configuration.
Debug metrics
loki.secretfilter exposes the following Prometheus metrics:
Use a custom Gitleaks configuration
By default, the component detects secrets with the upstream Gitleaks default ruleset.
To change which secrets the component detects, set the gitleaks_config argument to the path of a custom Gitleaks TOML file.
The recommended way to write a custom configuration is to extend the default rules rather than replace them.
Add an [extend] block with useDefault = true so your file starts from the complete set of built-in rules, then layer your own changes on top.
title = "Extended Gitleaks config"
[extend]
useDefault = true
# Add your own rule in addition to the built-in ones.
[[rules]]
id = "secret-internal-token"
description = "Secret internal service token"
regex = '''secret_tok_[0-9a-zA-Z]{32}'''
keywords = ["secret_tok_"]Try to set keywords on custom rules.
Alloy uses them as a prefilter and only evaluates the rule’s regex on lines that contain one of its keywords, so a rule without keywords runs against every line.
Refer to Manage performance for details.
Point the component at this file:
loki.secretfilter "secret_filter" {
forward_to = [loki.write.local_loki.receiver]
gitleaks_config = "/etc/alloy/gitleaks.toml"
}When useDefault = true, redefining a [[rules]] block with the same id as a built-in rule merges your changes into that rule instead of replacing it.
This lets you add allowlists or tune fields without losing the detection logic for that rule.
To turn off a built-in rule entirely rather than adjust it, list its id in disabledRules.
Disabling a rule stops it from detecting anything, so to keep a rule but ignore specific values, use an allowlist instead.
Adjust built-in rules with allowlists to reduce false positives, as shown in Handle false positives.
For the full set of configuration options, such as global allowlists, the condition field, stopwords, and path-based matching, refer to the Gitleaks configuration documentation.
Note
Setting
useDefault = false, or omitting the[extend]block, means only the rules you define yourself are used. The built-in rules are not loaded, so most secrets go undetected unless you redefine them.
Handle false positives
Because detection is regular expression-based, loki.secretfilter sometimes redacts values that aren’t secrets, such as identifiers, UUIDs, or hashes that happen to look like an API key.
When this happens, identify which rule is firing, then add an allowlist to that rule so the matching values are ignored.
To find the responsible rule, inspect the rule label on the loki_secretfilter_secrets_redacted_by_category_total metric.
For example, the built-in generic-api-key rule can produce false positives because it matches high-entropy strings broadly.
Start by raising the entropy value.
For more precise control, keep the rule enabled and allowlist only the specific values that cause false positives.
Allowlist false positives by extending the same configuration from the previous section.
Redefine the offending rule by id and add one or more [[rules.allowlists]] blocks.
Each allowlist uses regexTarget to choose what its regexes are tested against:
regexTarget = "match"tests against the surrounding matched text, which is useful for allowlisting by field name, such as ignoring anything that looks liketoken_id=....regexTarget = "secret"tests against the captured secret value itself, which is useful for allowlisting by value shape, such as ignoring UUIDs. This is the default whenregexTargetis omitted.
A finding is ignored when it matches any allowlist on the rule.
title = "Extended Gitleaks config"
[extend]
useDefault = true
[[rules]]
id = "secret-internal-token"
description = "Secret internal service token"
regex = '''secret_tok_[0-9a-zA-Z]{32}'''
keywords = ["secret_tok_"]
# Reduce false positives from the built-in generic-api-key rule.
[[rules]]
id = "generic-api-key"
# Raise the generic-api-key entropy threshold above its default.
entropy = 4.0
# Allowlist by matched text: ignore findings around known non-secret fields.
[[rules.allowlists]]
description = "Ignore token identifiers"
regexTarget = "match"
regexes = [
"(?i)token_?id",
]
# Allowlist by secret value: ignore when the captured value is a UUID.
[[rules.allowlists]]
description = "Ignore UUID values"
regexTarget = "secret"
regexes = [
'''^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$''',
]With this configuration, generic-api-key still detects real secrets, but it no longer redacts log lines such as token_id=a1B2c3D4e5F6g7H8i9J0 or values shaped like the UUID 8f14e45f-ceea-167a-9c2b-1f0a3e4d5c6b.
Manage performance
Secret detection scans every log line, so CPU cost rises with your log volume and the number of active rules.
To avoid running every rule against every line, Alloy first applies a fast keyword prefilter and only evaluates a rule’s regular expression when one of the rule’s keywords appears in the line.
The following options help you control that cost.
Reduce the number of lines processed.
Place loki.secretfilter after components that filter or drop logs, such as loki.process, so it only scans the lines you care about.
Fewer lines in means less work for the component.
Sample high-volume streams with rate.
Set rate to a value below 1.0 to process only a fraction of entries, for example, 0.1 to scan 10% of lines.
Entries that Alloy doesn’t select are forwarded unchanged, so this reduces CPU usage at the cost of leaving some lines unscanned.
Monitor loki_secretfilter_entries_bypassed_total to see how many entries were skipped.
Bound per-line work with processing_timeout.
Large lines can take longer to scan, so set processing_timeout to cap how long the component spends on any single entry.
By default, a timed out line is forwarded, and Alloy redacts any findings returned before the timeout, so the line is not dropped.
Set drop_on_timeout to true to drop timed out lines instead.
Monitor loki_secretfilter_lines_timed_out_total and loki_secretfilter_lines_dropped_total, and use loki_secretfilter_processing_duration_seconds to track overall processing time.
Add keywords to custom rules.
The keyword prefilter can only skip a rule that declares keywords.
A custom rule without keywords runs its regular expression against every line, which is much slower than the built-in rules.
Try to set keywords that must be present for the secret to match, as shown in Use a custom Gitleaks configuration.
Detect fewer secrets. Every active rule runs its own regular expression against each matching line, so disabling rules you don’t need lowers CPU usage. Refer to Use a custom Gitleaks configuration to disable or tune rules.
[extend]
useDefault = true
# Disable generic-api-key rule
disabledRules = ["generic-api-key"]
...Example
This example uses loki.secretfilter to redact secrets from log lines before forwarding them to a Loki receiver. It uses a custom redaction template with $SECRET_NAME and $SECRET_HASH.
Optional arguments are supported, several of which are listed below:
- Omit
redact_withto use percentage-based redaction, which defaults to 80% redacted. - Set
redact_percentto100for full redaction. - Set
gitleaks_configto point to a custom Gitleaks TOML configuration file. - Set
rateto a value below1.0to sample entries and reduce CPU usage; entries not selected are forwarded unchanged.
For a full list of arguments, refer to Arguments.
local.file_match "local_logs" {
path_targets = "<PATH_TARGETS>"
}
loki.source.file "local_logs" {
targets = local.file_match.local_logs.targets
forward_to = [loki.secretfilter.secret_filter.receiver]
}
loki.secretfilter "secret_filter" {
forward_to = [loki.write.local_loki.receiver]
redact_with = "<ALLOY-REDACTED-SECRET:$SECRET_NAME:$SECRET_HASH>"
// optional: gitleaks_config = "/etc/alloy/gitleaks.toml"
// optional: redact_percent = 100 // use when redact_with is not set
}
loki.write "local_loki" {
endpoint {
url = "<LOKI_ENDPOINT>"
}
}Replace the following:
<PATH_TARGETS>: The paths to the log files to monitor.<LOKI_ENDPOINT>: The URL of the Loki instance to send logs to.
Compatible components
loki.secretfilter can accept arguments from the following components:
- Components that export Loki
LogsReceiver
loki.secretfilter has exports that can be consumed by the following components:
- Components that consume Loki
LogsReceiver
Note
Connecting some components may not be sensible or components may require further configuration to make the connection work correctly. Refer to the linked documentation for more details.


