AWS Access Key ID
AWS access key IDs are the most recognizable leaked credential. Every long-term key issued to an IAM user starts with the four letters AKIA, followed by sixteen uppercase letters and digits, and it always travels with a 40-character secret access key that grants the actual API access.1 Because AWS documents this prefix publicly, pattern-based scanners can spot a key ID with almost no false positives. Consequently, the Cloud Config Sanitizer flags any AKIA match as a critical finding the moment you paste a manifest. The key ID alone identifies the owning AWS account2, and wherever an ID is hardcoded, its paired secret is usually a few lines away in the same file. Redacting both before the manifest leaves your machine closes one of the most common cloud credential leak paths.
What is AKIA?
AKIA, while temporary credentials issued through AWS STS begin with ASIA.3 The ID identifies the caller and the secret signs each request. AWS also exposes a GetAccessKeyInfo API in STS that returns the owning account ID for any key ID you submit, which is how responders trace a leaked key back to its account.2How AKIA keys end up in manifests
Hardcoded AWS keys rarely start as a deliberate decision. A developer wiring up a Deployment needs S3 access working today, so the key pair goes into the env block of the pod spec with a mental note to move it later. From there the manifest gets committed, copied into a Helm values file, or pasted into a ticket for a teammate, and each copy multiplies the exposure. Terraform provider blocks are a second common source, since the aws provider accepts access_key and secret_key arguments inline even though environment variables and shared credential files are the documented alternatives.4 Consequently, the same key pair often exists in three or four files by the time anyone notices it. Scanning every manifest before it leaves your editor is the one point in that chain where the leak is still cheap to fix.
Where the exposure actually spreads
The mental note to move the key later rarely outlasts the next release, so what started as a quick fix silently becomes the credential the service depends on day to day once the deployment is live. Once a workload is wired to the inline key, removing it means a coordinated change rather than a one-line delete that anyone could make in a hurry.
Teams tend to keep postponing that cleanup until the same secret is copied everywhere at once and treated as completely normal in the codebase. A secret that has only ever lived on a local machine can be redacted in seconds, while one that has reached a remote repository needs rotation and history cleanup before it is safe.
What the sanitizer does with an AKIA match
Inside the rule engine, one pattern targets AWS keys directly: the literal prefix AKIA followed by sixteen uppercase letters or digits. When a string value matches, the sanitizer records a critical finding with the exact dotted key path, shows the first 40 characters of the value in the findings table, and swaps the value for a placeholder such as __REDACTED_AWS_ACCESS_KEY_1__ in the sanitized output. The counter matters; two AWS keys in the same document become _1_ and _2_ so they never collide during a later find and replace. Furthermore, the key name that held the value becomes an entry in the downloadable .env template, ready for you to fill with the real credential outside version control. Everything happens in your browser, so the key you paste never crosses the network.
What the redaction keeps usable
The redacted value keeps its exact key path and position, so the manifest still parses once the real secret is injected from the environment at deploy time without anyone rewriting the file. That lets you commit the shape of the config without committing the secret itself, which is what makes the sanitized file safe to share with teammates and reviewers alike.
The structure stays intact, so a colleague can validate the manifest without ever seeing a live credential during the review. Because the whole check runs locally in the browser, nothing about the match leaves your machine, and the redacted artifact is safe to drop into a chat thread or a support ticket for discussion.
The paired secret access key is the real prize
A key ID without its secret cannot sign requests. The 40-character secret access key carries no fixed prefix, so no provider rule can match it by shape alone. Yet the sanitizer still has a net for it: any string of 16 or more characters whose Shannon entropy reaches 4.5 bits per character is flagged as a high-severity finding5, and a randomly generated AWS secret is exactly the kind of dense, mixed-alphabet value that crosses this threshold. Because the two halves of the pair usually sit within a few lines of each other, a critical AKIA finding should prompt you to inspect the neighboring high-entropy findings rather than dismissing them as noise. Treat the pair as a unit when you redact, and treat it as a unit again when you rotate.
Why the secret and the ID travel together
The 40-character secret is random by design, which is precisely what pushes its Shannon entropy past the threshold the detector uses to flag high-severity findings as critical rather than low-priority noise. A human-chosen password rarely reaches that density, so the rule naturally filters out weak strings instead of flagging every value it encounters in the file.
When an AKIA ID and a high-entropy string appear a few lines apart, redact both at once rather than chasing them separately through the document and risking a miss. Rotation follows the same logic, because a new key pair replaces the old one together, so neither half of the exposed credential stays valid on its own afterward.
Rotating a leaked AWS key correctly
Redaction is not rotation, so if an AKIA key has already reached a shared channel, a git remote, or a pasted snippet, you must assume it is compromised and replace it before anyone else can use it. The safe rotation sequence in the IAM console keeps your workloads alive while you move everything to a fresh pair without a gap.
The rotation sequence that avoids outages
Create a second access key for the same user in the IAM console, deploy the new pair everywhere the old one was used, then deactivate the old key and watch for failures before you delete anything.6 Deleting first risks breaking a workload that still references the old credential at the worst possible moment during an incident.
During an incident, GetAccessKeyInfo tells you which account a found key belongs to, which helps when a key surfaces in a file with no other context to explain it. Building on this, the sanitized manifest and the .env template give you a clean artifact to redeploy with the rotated credentials while the exposed pair is being retired for good.
Try in the tool
What to look for
- AWS access key ID shape AKIA + 16 uppercase letters/digits
- Paired secret length 40 characters
- High-entropy trigger >=4.5 bits/char over 16+ characters
A critical AKIA match should prompt you to inspect nearby high-entropy findings for the paired secret.
Open the Cloud Config Sanitizer tool to try this yourself.
Open the tool →- 1.
AWS, "Manage access keys for IAM users," docs.aws.amazon.com, accessed July 2026. https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html
- 2.
AWS, "GetAccessKeyInfo," docs.aws.amazon.com, accessed July 2026. https://docs.aws.amazon.com/STS/latest/APIReference/API_GetAccessKeyInfo.html
- 3.
Aidan Steele, "AWS Access Key ID formats," awsteele.com, September 2020. https://awsteele.com/blog/2020/09/26/aws-access-key-format.html
- 4.
HashiCorp, "Provider configuration," developer.hashicorp.com, accessed July 2026. https://developer.hashicorp.com/terraform/language/providers/configuration
- 5.
Yelp, "detect-secrets: High Entropy Strings Plugin," github.com, accessed July 2026. https://github.com/Yelp/detect-secrets/blob/master/detect_secrets/plugins/high_entropy_strings.py
- 6.
AWS, "How to Rotate Access Keys for IAM Users," aws.amazon.com, accessed July 2026. https://aws.amazon.com/blogs/security/how-to-rotate-access-keys-for-iam-users/
The ID alone cannot sign API requests, so AWS does not classify it as a secret the way it does the secret access key. It still identifies your account and confirms a credential pair exists, which is valuable reconnaissance. The sanitizer treats any AKIA match as critical because a hardcoded ID almost always means the paired secret is nearby.
The AWS prefix rule targets long-term AKIA identifiers specifically. Temporary key IDs from AWS STS begin with ASIA and do not match that rule, but the session token and secret that accompany them are long, random strings that typically trigger the high-entropy detector at 4.5 bits per character. Review high-severity findings when you sanitize a file containing temporary credentials.
Each match becomes a placeholder like __REDACTED_AWS_ACCESS_KEY_1__ with a counter that increments for every additional AWS key in the same document. The placeholder preserves the key path and position so the manifest still parses once real values are injected. The matching key also appears in the downloadable .env template for you to fill in.
No. CapyToolkit doesn't upload, log, or transmit anything you paste; parsing, matching, and redaction all run as JavaScript in your browser. You can confirm this by opening the Network tab in DevTools while you work. Closing the tab discards the parsed document and every finding along with it.
Rotate first, clean up second. Create a replacement key in IAM, deploy it, then deactivate and delete the exposed one. Removing the key from the file in a new commit does not remove it from git history, so a shared repository also needs a history rewrite with a tool like git filter-repo, plus a review of forks and clones.
GitHub Personal Access Token
GitHub redesigned its token formats in 2021 for one reason: detectability. Classic personal access tokens now begin with ghp_, OAuth tokens with gho_, and installation tokens with ghs_, so a scanner can identify a leaked GitHub credential from the prefix alone.1 A classic PAT is the ghp_ prefix followed by 36 characters, and that exact shape is what the Cloud Config Sanitizer matches as a critical finding. Tokens of this kind leak through CI configuration, git credential helpers baked into container images, and clone URLs embedded in manifests. Yet a PAT is often more dangerous than a password, because it can carry repo, workflow, or admin scopes across every repository its owner can reach. Finding one in a config file deserves the same urgency as finding a private key.
What is ghp_?
Where GitHub tokens hide in config files
Clone URLs are the classic hiding spot. A remote of the form https://[email protected]/org/repo.git embeds the token directly in the URL, and that URL then lands in CI variables, submodule configs, and deployment manifests that fetch private repositories at build time. Beyond URLs, tokens surface in Kubernetes ConfigMaps that hold .netrc or git-credentials content for in-cluster jobs, and in workflow YAML where someone hardcoded a token instead of referencing a stored secret. Because each of these files looks harmless at a glance, the token travels further than a password ever would. Pasting the file into the sanitizer before you share it surfaces every ghp_ match with its exact key path, so you know precisely which line to fix at the source.
Why clone URLs leak the most
A remote written with the token baked into the connection string exposes the credential the moment the repository link is shared with anyone who can clone. That URL then lands in CI variables, submodule configs, and deployment manifests that fetch private repositories at build time without anyone ever typing the secret again.
Beyond URLs, tokens also surface in Kubernetes ConfigMaps that hold netrc or git-credentials content for in-cluster jobs, and in workflow YAML where someone hardcoded a token instead of referencing a stored secret. Because each of these files looks harmless at a glance, the token travels much further than a password ever would through normal review.
How the ghp_ rule and redaction work
For classic tokens, the rule engine matches the ghp_ prefix followed by exactly 36 letters and digits. On a match, the sanitizer records a critical finding, displays the dotted key path and a 40-character snippet in the findings table, and replaces the value with __REDACTED_GITHUB_TOKEN_1__ in the sanitized output. The counter increments for each additional token in the same document. Furthermore, the redacted key is added to the .env template download, which lists every critical and high finding as an empty KEY= line ready for real values. Nothing is transmitted at any point; the matching runs entirely in your browser, so checking a token-bearing file does not itself create a new exposure.
What the sanitized file keeps intact
On a match, the sanitizer records a critical finding, displays the dotted key path and a 40-character snippet in the findings table, and replaces the value with __REDACTED_GITHUB_TOKEN_1__ in the sanitized output. The counter increments for each additional token in the same document, so two leaks become clearly distinct placeholders rather than a single ambiguous one.
The redacted key is also added to the dotenv template download, which lists every critical and high finding as an empty KEY= line ready for real values. Nothing is transmitted at any point, because the matching runs entirely in your browser, so checking a token-bearing file does not itself create a new exposure for attackers to find.
Fine-grained tokens and the fallback nets
Fine-grained personal access tokens use the github_pat_ prefix and a longer body, so they do not match the classic ghp_ rule. Two fallback layers still catch most of them. First, any string of 16 or more characters with Shannon entropy at or above 4.5 bits per character is flagged high severity, and fine-grained token bodies are long and random enough to cross that line.3 Second, if the value sits under a key named exactly token, secret, or another name on the suspicious-key list, the medium-severity key-name rule fires even when the value itself looks unremarkable. Conversely, a fine-grained token stored under an innocuous key with low-entropy padding could slip through, which is why the findings list is a review aid rather than a guarantee.
Why two fallback layers matter
Fine-grained personal access tokens use the github_pat_ prefix and a longer body, so they do not match the classic ghp_ rule on their own in the engine. The first fallback flags any string of 16 or more characters whose Shannon entropy reaches the high-severity threshold,3 and fine-grained token bodies are long and random enough to cross that line without trouble.
The second fallback fires when the value sits under a key named exactly token, secret, or another name on the suspicious-key list, even when the value itself looks unremarkable to a human reviewer. A fine-grained token stored under an innocuous key with low-entropy padding could still slip through, which is why the findings list is a review aid rather than a guarantee.
Responding to a leaked GitHub token
Revocation beats deletion every time. Removing the token from a file does nothing if the value has already been pushed, so start by revoking it under Developer settings in your GitHub account, then audit the security log for actions taken with it. On public repositories, GitHub's own secret scanning detects its token formats and revokes exposed tokens automatically,45 but private repositories and files shared outside GitHub receive no such protection. When you reissue, prefer a fine-grained token scoped to the specific repositories and permissions the job needs, with an expiration date. Building on this, run the replacement manifest through the sanitizer once more before it goes anywhere, confirming the new token is referenced from the environment rather than pasted inline.
Try in the tool
What to look for
- Classic PAT shape ghp_ + 36 base62 characters
- Other GitHub prefixes gho_ (OAuth), ghs_ (installation), ghr_ (refresh), github_pat_ (fine-grained)
Only the classic ghp_ shape matches the dedicated rule; other prefixes rely on the entropy and suspicious-key fallbacks.
Open the Cloud Config Sanitizer tool to try this yourself.
Open the tool →- 1.
GitHub Engineering, "Behind GitHub's new authentication token formats," github.blog, April 2021. https://github.blog/engineering/platform-security/behind-githubs-new-authentication-token-formats/
- 2.
GitHub, "GitHub credential types reference," docs.github.com, accessed July 2026. https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/github-credential-types
- 3.
Veritensor, "Generic API Key Detection: Information Theory vs. Unknown Unknowns," guide.veritensor.com, accessed July 2026. https://guide.veritensor.com/docs/threats/generic-api-key-entropy-detection
- 4.
GitHub, "Token expiration and revocation," docs.github.com, accessed July 2026. https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/token-expiration-and-revocation
- 5.
GitHub, "Securing the open source supply chain by scanning for package registry credentials," github.blog, June 2021. https://github.blog/security/supply-chain-security/securing-open-source-supply-chain-scanning-package-registry-credentials/
The dedicated GitHub rule targets classic ghp_ tokens. OAuth gho_ tokens, installation ghs_ tokens, and refresh ghr_ tokens do not match it, but their long random bodies usually trigger the high-entropy detector, and values stored under key names like token trip the suspicious-key rule. Check high and medium findings for these variants.
Not by the prefix rule, which matches the classic 36-character ghp_ shape. Fine-grained tokens are longer and typically exceed the 4.5 bits per character entropy threshold, so they surface as high-severity findings instead. Treat any high-entropy match near GitHub-related keys as a probable token and redact it before sharing the file.
A classic PAT with repo scope grants access to every repository the owner can reach, not just one system, and it bypasses two-factor authentication because it authenticates directly over the API. Workflow scope even permits modifying CI definitions. A password grants one login that is usually protected by additional factors; a scoped token is standing access.
The value becomes __REDACTED_GITHUB_TOKEN_1__, with the counter rising for each further token in the document. The key path stays intact so the file still parses and the placeholder is easy to find and replace during deployment. The same key appears in the .env template download so the real token can live outside version control.
Yes. CapyToolkit doesn't send your input anywhere; the parser and every detection rule run locally in your browser, and reloading the page discards all state. The token is only as exposed after the check as it was before it. That said, a token that has already reached a shared repository or channel should be revoked regardless.
Slack Token
A leaked Slack token reads your workspace like an open book. Bot tokens beginning with xoxb- and user tokens beginning with xoxp- authenticate directly against the Slack Web API1, and depending on their scopes they can read channel history, post messages, and enumerate members. Slack tokens land in config files because chat integrations are everywhere: alerting sidecars in Kubernetes, notification steps in CI, and webhook bridges all want a token in their environment. The Cloud Config Sanitizer matches the xox prefix family as a critical finding and swaps each token for a placeholder before you share the file. Furthermore, security reporting shows chat platforms are now a leak destination in their own right2, so a manifest pasted into Slack for debugging can leak a token for Slack itself.
What is xoxb?
What a Slack token actually grants
Scopes decide the blast radius. A bot token with chat:write can only post as the bot, while one with channels:history and users:read can read conversations and map your organization's people; a user token can carry anything the installing user approved, which often includes files:read across years of shared documents. Because integrations request generous scopes during setup and few teams audit them later, the practical assumption for any leaked token is that it reads more than you expect. Consequently, treating an exposed xoxb- or xoxp- string as a low-priority chat credential understates the risk. The token authenticates silently against the Web API from anywhere on the internet, with no second factor and no device check standing in the way.
How Slack tokens reach config files
Alerting is the usual entry point. A Prometheus Alertmanager config, a Kubernetes CronJob that posts nightly reports, or a GitHub Actions step that announces deploys each need a Slack credential, and the fastest path is pasting the token straight into the YAML. From there the file spreads through commits, code review, and copy-paste into tickets. In the sanitizer, any string matching the xox prefix rule is flagged critical with its dotted key path, so a token buried four levels deep in an Alertmanager receiver block is as visible as one at the top level. The sanitized download replaces it with __REDACTED_SLACK_TOKEN_1__, and the .env template lists the owning key so the real value can be injected at deploy time instead.
Why pasting the token is the fastest path
Alerting is the usual entry point, because a Prometheus Alertmanager config, a Kubernetes CronJob that posts nightly reports, or a GitHub Actions step that announces deploys each need a Slack credential to function. The fastest path is pasting the token straight into the YAML, which feels harmless until the file spreads through commits and code review.
From there the file travels through copy-paste into tickets and shared documents where the token keeps working long after the task is done. In the sanitizer, any string matching the xox prefix rule is flagged critical with its dotted key path, so a token buried four levels deep in a receiver block is as visible as one at the top level.
The chat-platform leak loop
GitGuardian's State of Secrets Sprawl 2026 report found that 28 percent of secret incidents now originate entirely outside code repositories, in tools like Slack, Jira, and Confluence2, and that those non-code leaks are more likely to be critical than the ones found in code. This creates an ironic loop: an engineer pastes a manifest into a Slack channel to get help, and the manifest contains a Slack token that now sits in message history readable by everyone in the channel. Message retention keeps it there long after the thread is forgotten. Sanitizing before you paste breaks the loop at its cheapest point, because the placeholder version carries all the structure a helper needs without carrying the credential.
How a help request becomes a leak
GitGuardian's State of Secrets Sprawl 2026 report found that 28 percent of secret incidents now originate entirely outside code repositories, in tools like Slack, Jira, and Confluence that teams use every day. Those non-code leaks are more likely to be critical than the ones found in code, which makes the chat channel a real exposure surface rather than a side note.
This creates an ironic loop, because an engineer pastes a manifest into a Slack channel to get help, and the manifest contains a Slack token that now sits in message history readable by everyone in the channel. Message retention keeps it there long after the thread is forgotten, so sanitizing before you paste breaks the loop at its cheapest point.
Revoking and reissuing a Slack token
Slack tokens do not expire on their own unless rotation is enabled3, so an exposed token stays live until you act. For an app token, regenerating it from the app's settings on api.slack.com invalidates the old value; the auth.revoke API method also revokes a token programmatically3, which is useful in incident scripts. After revocation, reinstall or update the integration with the new token delivered through an environment variable or a secrets manager rather than a hardcoded string. Building on this, run the corrected manifest through the sanitizer once more before it re-enters your repository, confirming the only Slack-shaped string left is a placeholder and the real token now lives in your .env file or secret store.
The revocation steps that actually work
Slack tokens do not expire on their own unless rotation is enabled4, so an exposed token stays live until you act on it deliberately. For an app token, regenerating it from the app's settings on api.slack.com invalidates the old value, and the auth.revoke API method also revokes a token programmatically, which is useful inside incident response scripts that run automatically.
After revocation, reinstall or update the integration with the new token delivered through an environment variable or a secrets manager rather than a hardcoded string in the config.5 Building on this, run the corrected manifest through the sanitizer once more before it re-enters your repository, confirming the only Slack-shaped string left in the file is a placeholder and the real token now lives in your dotenv file or secret store.
Try in the tool
What to look for
- Matched prefixes xoxb-, xoxp-, xoxr-, xoxs-
- Not matched by this rule xapp- (caught by the entropy fallback instead)
Slack tokens do not expire by default; assume a leaked one is still live until revoked.
Open the Cloud Config Sanitizer tool to try this yourself.
Open the tool →- 1.
Slack, "Tokens," docs.slack.dev, accessed July 2026. https://docs.slack.dev/authentication/tokens/
- 2.
GitGuardian, "The State of Secrets Sprawl 2026," blog.gitguardian.com, March 2026. https://blog.gitguardian.com/the-state-of-secrets-sprawl-2026/
- 3.
Slack, "Using token rotation," docs.slack.dev, accessed July 2026. https://docs.slack.dev/authentication/using-token-rotation/
- 4.
Nango, "How to get Slack user access token OAuth," nango.dev, accessed July 2026. https://nango.dev/blog/how-to-get-slack-user-access-token-oauth/
- 5.
The Twelve-Factor App, "Config," 12factor.net, accessed July 2026. https://12factor.net/config
The rule matches strings starting with xoxb-, xoxp-, xoxr-, or xoxs-, covering bot tokens, user tokens, and related legacy forms. App-level tokens with the xapp- prefix do not match this rule, but their long random bodies typically cross the high-entropy threshold and surface as high-severity findings instead.
Usually, but only by degree. A bot token is limited to the scopes granted to the app's bot user, while a user token can act with the installing user's full approved permissions. Either can read message history if the scopes allow it. Judge the risk by the scopes on the token, not by its prefix.
Not by default. Standard bot and user tokens remain valid until they are revoked or the app is uninstalled. Slack offers optional token rotation for apps that opt in, which issues short-lived access tokens plus refresh tokens. If your leaked token came from an app without rotation enabled, assume it is still live and revoke it.
It becomes a placeholder like __REDACTED_SLACK_TOKEN_1__ at the same key path, and the key is listed in the downloadable .env template. CapyToolkit doesn't transmit the original value anywhere during this process; detection and replacement run entirely in your browser, so the paste itself adds no exposure.
Revoke the token first, either by regenerating it in the app settings or calling auth.revoke. Then delete the message if you can, while assuming retention or exports may have preserved it. Finally, reissue the integration with the new token injected from the environment and share only sanitized manifests from that point on.
Stripe API Key
Test mode and live mode are separated by one word inside the key. Stripe issues secret keys with the sk_live_ and sk_test_ prefixes1, and the difference between them is the difference between a harmless sandbox credential and a string that can create charges, issue refunds, and read customer records on a production account2. Config files blur that line constantly: a docker-compose file starts with a test key, someone swaps in the live key to debug a webhook, and the file gets committed with production access inside. The Cloud Config Sanitizer includes a dedicated Stripe rule at critical severity, with the entropy detector as a second net for long random key bodies. Redacting before you share is far cheaper than explaining a payment-account exposure afterwards.
What is sk_live_?
What a leaked live secret key can do
Full API control is the honest answer. With an sk_live_ key, a caller can list customers, read payment method metadata, create charges, issue refunds, and modify products and webhooks on the account2, all without any additional login step. Stripe applies its own fraud monitoring, yet monitoring is reactive by nature, and the window between leak and detection belongs to the attacker. Because the key authenticates the account rather than a user, there is no second factor to intercept the misuse. Consequently, a live secret key in a shared manifest is a payment-infrastructure incident, not a code-hygiene footnote. The only proportionate responses are rolling the key immediately and tracing where the file traveled.
Test keys deserve redaction too
Engineers routinely wave off sk_test_ leaks, and the dismissal is only half right. A test key cannot move real money, but it exposes the shape of your integration: product catalogs, webhook endpoints, metadata conventions, and the account structure an attacker would want to understand before targeting the live mode1. Furthermore, files that contain a test key demonstrate a workflow where keys are hardcoded, which predicts a live key sitting in a sibling file or an earlier commit. In the sanitizer, both modes are treated as findings worth redacting, so the sanitized output ships with placeholders regardless of mode. Keeping the habit uniform means nobody has to make a judgment call under deadline pressure about which prefix is safe to share.
Why test mode still leaks signal
Engineers routinely wave off sk_test_ leaks, and the dismissal is only half right because a test key cannot move real money but still exposes the shape of your integration. Product catalogs, webhook endpoints, metadata conventions, and the account structure an attacker would want to understand all sit in that file once it is shared.
Furthermore, files that contain a test key demonstrate a workflow where keys are hardcoded, which predicts a live key sitting in a sibling file or an earlier commit. In the sanitizer, both modes are treated as findings worth redacting, so the sanitized output ships with placeholders regardless of mode and nobody has to decide which prefix is safe under pressure.
How detection and the entropy net interact
Prefix rules and entropy analysis cover different failure modes. The dedicated Stripe rule targets the documented secret-key shape at critical severity, while the entropy detector independently flags any string of 16 or more characters that reaches 4.5 bits per character, which the long random body of a modern Stripe key comfortably exceeds. This layering matters when key formats evolve; Stripe has lengthened its key bodies over time3, and a shape-based rule tuned to an older format can miss a newer one that the entropy net still catches. Building on this, a value stored under a key named exactly key or api_key also trips the medium-severity suspicious-key rule. Review all three severity bands before declaring a payments manifest clean.
Why both layers earn their place
Prefix rules and entropy analysis cover different failure modes, so neither alone is enough to call a payments manifest clean with confidence. The dedicated Stripe rule targets the documented secret-key shape at critical severity, while the entropy detector independently flags long random strings that reach the high-severity threshold on their own without needing a recognizable prefix.
This layering matters when key formats evolve, because Stripe has lengthened its key bodies over time and a shape-based rule tuned to an older format can miss a newer one that the entropy net still catches. Review all three severity bands before declaring a payments manifest clean, since a finding in any band can point to a real exposure.
Rolling a Stripe key without downtime
Stripe supports rolling a secret key from the Dashboard's API keys page, and the flow is built for zero-downtime rotation: you can generate the new key while choosing to keep the old one valid for a grace window up to 7 days4, giving your deployments time to pick up the replacement. Roll first, then update the environment variables or secret manager entries your services read,5 and let the grace period absorb the propagation delay. After the window closes, the exposed key is dead everywhere. Conversely, deleting a key outright drops live traffic immediately, which turns a security fix into an outage. Once rotated, keep the key out of files entirely and let the sanitized manifest's .env template define which variables need real values at deploy time.
The graceful rotation sequence
Stripe supports rolling a secret key from the Dashboard's API keys page, and the flow is built for zero-downtime rotation that most providers do not offer. You can generate the new key while choosing to keep the old one valid for a grace window up to 7 days4, giving your deployments time to pick up the replacement without dropping requests in the middle of a deploy.
Roll first, then update the environment variables or secret manager entries your services read, and let the grace period absorb the propagation delay across every environment. After the window closes, the exposed key is dead everywhere, whereas deleting a key outright drops live traffic immediately and turns a security fix into an outage that users notice.
Try in the tool
What to look for
- Live secret key prefix sk_live_
- Test secret key prefix sk_test_
- Grace window for rolling a key up to 7 days
Test-mode keys are redacted too; both modes still expose the integration shape an attacker would study.
Open the Cloud Config Sanitizer tool to try this yourself.
Open the tool →- 1.
Stripe, "API keys," docs.stripe.com, accessed July 2026. https://docs.stripe.com/keys
- 2.
Stripe, "Event permissions reference," stripe.com, accessed July 2026. https://stripe.com/docs/stripe-apps/reference/event-permissions
- 3.
Stripe, "Why are new API keys longer than existing keys?", support.stripe.com, accessed July 2026. https://support.stripe.com/questions/new-api-keys-are-longer-than-existing-keys
- 4.
Stripe, "How do I roll/change/update my Stripe API key?", support.stripe.com, accessed July 2026. https://support.stripe.com/questions/how-do-i-roll-change-update-my-stripe-api-key
- 5.
The Twelve-Factor App, "Config," 12factor.net, accessed July 2026. https://12factor.net/config
The prefix encodes both role and mode. sk_ keys are secret keys with full API access, pk_ keys are publishable keys safe for client-side use, and rk_ keys are restricted keys with permissions you choose. The live or test segment tells you the mode. Only secret and restricted keys need redaction, but the sanitizer errs toward flagging key-like values broadly.
Generally no. Publishable keys are designed to appear in browsers and mobile apps, where anyone can read them, and they can only perform limited client-side operations. A pk_ value in a manifest is not a leak by itself. Focus your response on any sk_ or rk_ value in the same file, since those carry real API authority.
Immediately, using the Dashboard's roll option with a grace period if your services need propagation time. The exposed key remains fully capable until the roll completes, and there is no way to know who copied a shared file. Rolling with a short grace window balances urgency against downtime; deleting the key outright breaks live traffic at once.
Detection does not depend on the key name for the prefix and entropy rules; a Stripe secret in a field called webhook_helper is flagged the same as one under api_key. The key name only matters for the medium-severity suspicious-key rule, which adds coverage when a value has no recognizable shape.
No. CapyToolkit doesn't send your manifest to a server; parsing and every rule run in your browser, and nothing persists after you close the tab. The sanitized download and .env template are generated locally too, so the only copies of your key remain the ones you already had.
PEM Private Key
PEM is the textual armor around most private keys in production. RFC 7468 defines the format: a line reading BEGIN followed by a label such as PRIVATE KEY, a body of base64-encoded key material, and a matching END line.1 Because the format is plain text, it pastes cleanly into YAML block scalars, which is exactly how TLS keys, SSH keys, and service-account keys end up inside Kubernetes manifests and Helm values files.2 A private key is the credential other credentials depend on. Consequently, the Cloud Config Sanitizer treats any BEGIN PRIVATE KEY header as a critical finding and redacts the entire value, whether the label says PRIVATE KEY, RSA PRIVATE KEY, or EC PRIVATE KEY. Sharing a manifest with a key block inside is equivalent to handing over the key file itself.
What is PEM?
How private keys land inside YAML
Multi-line strings are the gateway. YAML's block scalar syntax, the pipe character followed by indented lines, lets a whole PEM file sit inside a manifest as an ordinary value, and Kubernetes TLS Secrets,2 cert-manager resources,4 and SSH deploy-key ConfigMaps5 all use it. A developer debugging an ingress copies the Secret to a ticket to show the structure, forgetting that tls.key contains the live private key rather than a reference to one. From there the key exists in the ticket system's database and every notification email it generated. Pasting the manifest into the sanitizer first replaces the block with a placeholder while preserving the surrounding structure, so the ingress problem is still debuggable without the key going along for the ride.
Why one leaked key outranks a leaked password
A private key is an identity, not just an access grant. The TLS key for a domain lets its holder impersonate the server to any client until the certificate is revoked or expires; an SSH key authenticates to every host that lists the public half in authorized_keys;5 a service-account signing key mints tokens that downstream systems accept as genuine. Yet revocation for keys is harder than resetting a password, because trust in the public half is distributed across clients, hosts, and caches you do not fully control.6 Consequently, key leakage response means reissuing key pairs and redeploying the public halves everywhere, a process measured in hours or days. Preventing the leak with a redaction pass costs seconds by comparison.
An identity rather than a grant
A private key is an identity, not just an access grant, which is what makes its exposure so much more serious than a leaked password. The TLS key for a domain lets its holder impersonate the server to any client until the certificate is revoked, an SSH key authenticates to every host that lists the public half, and a signing key mints tokens that downstream systems accept as genuine.
Yet revocation for keys is harder than resetting a password, because trust in the public half is distributed across clients, hosts, and caches you do not fully control.6 Key leakage response means reissuing key pairs and redeploying the public halves everywhere, a process measured in hours or days, so preventing the leak with a redaction pass costs seconds by comparison.
What the critical finding looks like
On a match, the findings table shows the dotted path to the field, the PEM Private Key type label, and the first 40 characters of the value, which is typically the BEGIN boundary itself. The sanitized output replaces the whole block with __REDACTED_PEM_PRIVATE_KEY_1__, and the owning key name is added to the .env template download. One subtlety is worth knowing: in a Kubernetes Secret, key material under .data or .stringData is flagged critical by the dedicated Secret rule before the PEM pattern even runs, because everything in those maps is redacted unconditionally. Furthermore, base64-encoded PEM inside .data does not look like a BEGIN block at all, which is exactly why the unconditional Secret rule exists as the outer layer of defense.
What the critical finding exposes
On a match, the findings table shows the dotted path to the field, the PEM Private Key type label, and the first 40 characters of the value, which is typically the BEGIN boundary itself. The sanitized output replaces the whole block with __REDACTED_PEM_PRIVATE_KEY_1__, and the owning key name is added to the dotenv template download for later use.
One subtlety is worth knowing, because in a Kubernetes Secret, key material under data or stringData is flagged critical by the dedicated Secret rule before the PEM pattern even runs. Everything in those maps is redacted unconditionally, and base64-encoded PEM inside data does not look like a BEGIN block at all, which is exactly why that outer layer of defense exists.
After a key block has leaked
Reissue, redeploy, revoke, in that order of thought. Generate a new key pair for the affected system, deploy the new public half or certificate everywhere it is trusted, then invalidate the old one: revoke the certificate with your CA, remove the old public key from authorized_keys files, or rotate the signing key identifier your services accept. For TLS specifically, certificate revocation checking is unreliable across clients, so reissuing quickly matters more than revoking formally. Building on this, audit where the leaked manifest traveled, since a key block in git history persists through ordinary deletes and requires a history rewrite to remove.7 The sanitized manifest gives you a safe artifact to share while that cleanup proceeds.
The correct rotation order
Reissue, redeploy, revoke, in that order of thought, because doing it backward can leave a window where the old key still works after you think it is gone. Generate a new key pair for the affected system, deploy the new public half or certificate everywhere it is trusted, then invalidate the old one with the CA or the authorized keys list.
For TLS specifically, certificate revocation checking is unreliable across clients, so reissuing quickly matters more than revoking formally before the exposure spreads. Audit where the leaked manifest traveled, since a key block in git history persists through ordinary deletes and requires a history rewrite to remove,7 and the sanitized manifest gives you a safe artifact to share while that cleanup proceeds.
Try in the tool
What to look for
- Matched boundary -----BEGIN <=30 chars PRIVATE KEY-----
- Labels covered PRIVATE KEY, RSA PRIVATE KEY, EC PRIVATE KEY, ENCRYPTED PRIVATE KEY
Base64 key material inside a Kubernetes Secret's data/stringData is redacted unconditionally by a separate rule, even with no visible BEGIN line.
Open the Cloud Config Sanitizer tool to try this yourself.
Open the tool →- 1.
IETF, "RFC 7468: Textual Encodings of PKIX, PKCS, and CMS Structures," datatracker.ietf.org, April 2015. https://datatracker.ietf.org/doc/html/rfc7468
- 2.
Kubernetes, "Secrets," kubernetes.io, accessed July 2026. https://kubernetes.io/docs/concepts/configuration/secret/
- 3.
IETF, "RFC 5958: Asymmetric Key Packages," datatracker.ietf.org, August 2010. https://datatracker.ietf.org/doc/html/rfc5958
- 4.
cert-manager, "Certificate resource," cert-manager.io, accessed July 2026. https://cert-manager.io/docs/usage/certificate/
- 5.
OpenBSD, "sshd(8): AUTHORIZED_KEYS FILE FORMAT," man.openbsd.org, accessed July 2026. https://man.openbsd.org/sshd.8
- 6.
Cloudflare, "High-reliability OCSP stapling and why it matters," blog.cloudflare.com, July 2017. https://blog.cloudflare.com/high-reliability-ocsp-stapling/
- 7.
Git, "Git Tools - Rewriting History," git-scm.com, accessed July 2026. https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History
The pattern matches a BEGIN boundary with up to 30 characters before the words PRIVATE KEY, so PRIVATE KEY, RSA PRIVATE KEY, EC PRIVATE KEY, and ENCRYPTED PRIVATE KEY headers all trigger it. Certificate blocks labeled BEGIN CERTIFICATE do not match, which is correct behavior because certificates are public material.
Yes. An ENCRYPTED PRIVATE KEY block is protected by a passphrase, but passphrases are frequently weak, reused, or stored in the same repository, and offline brute-force attempts face no rate limiting. Treat an encrypted key in a shared file as a leak with a time delay rather than a non-event, and reissue the key pair.
Values under a Secret's .data map are base64-encoded, so the BEGIN boundary is not visible as text. The sanitizer handles this with an unconditional rule: every value inside .data or .stringData of a document whose kind is Secret is flagged critical and redacted regardless of content, so the key is caught without decoding.
No. Detection is based on the BEGIN boundary, not on parsing the base64 body, so a truncated or corrupted key block is flagged the same as a valid one. That is the safe direction for a redaction tool: it never needs to load your key into a crypto library, and CapyToolkit doesn't transmit the block anywhere during analysis.
A reference, not a value. In Kubernetes, mount the key from a Secret managed outside the manifest, ideally synced from a secret manager by a tool like External Secrets Operator. The sanitized output's placeholder marks where the reference belongs, and the .env template records which variable the deployment pipeline must supply.
JWT in Config Files
That eyJ string in your manifest is readable by anyone. A JSON Web Token, defined in RFC 7519, is three base64url segments joined by dots: a header, a payload of claims, and a signature.1 Base64url is an encoding, not encryption, so the header and payload decode back to plain JSON in one step, exposing user identifiers, email addresses, roles, and expiry times to whoever sees the token. Worse, a token that has not reached its exp claim still authenticates against the service that issued it.2 JWTs land in config files as test fixtures, service-to-service credentials, and debugging leftovers. Consequently, the Cloud Config Sanitizer matches the three-segment eyJ shape as a critical finding and replaces the whole token before your manifest travels anywhere.
What is JWT?
Two distinct leaks in one string
A JWT in a shared file leaks twice. The first leak is informational: decoding the payload reveals whatever claims the issuer embedded, and real-world tokens carry user IDs, emails, tenant names, internal role vocabularies, and infrastructure hostnames in audience fields.1 That data is exposed permanently, even after the token expires. The second leak is access: until the exp timestamp passes, the token authenticates requests exactly as it did for its legitimate holder, and stateless verifiers accept it with no way to notice the swap.2 Yet teams routinely paste tokens into tickets and chat because the string looks like opaque noise. Reading the shape correctly, three dot-separated segments starting with eyJ, should trigger the same reflex as seeing a password in plain text.3
How JWTs settle into manifests
Static tokens are the root cause. Service-to-service authentication sometimes ships as a long-lived JWT placed in an environment variable, and long-lived means the token sits in the Deployment spec for months, surviving copies into staging configs and example files. Test fixtures are the second source; a captured token makes integration tests pass, so it gets committed alongside them. In the sanitizer, the JWT rule matches the segment structure itself, so tokens are caught no matter which key holds them, whether AUTH_HEADER, bearer_token, or a nested annotation. The finding shows the dotted path and a 40-character snippet, which is usually enough of the header segment to confirm what it is without exposing the payload in the findings table.
Where the static token lingers
Static tokens are the root cause, because service-to-service authentication sometimes ships as a long-lived JWT placed in an environment variable that the Deployment spec holds for months. Long-lived means the token survives copies into staging configs and example files long after the original need has passed, widening the blast radius of any single leak.
Test fixtures are the second source, since a captured token makes integration tests pass and so it gets committed alongside them without a second thought. In the sanitizer, the JWT rule matches the segment structure itself, so tokens are caught no matter which key holds them, whether that key is an auth header, a bearer token, or a nested annotation.
Redaction behavior and the signing-secret question
On a match, the sanitized output carries __REDACTED_JWT_1__ in place of the token, with counters separating multiple tokens in one document, and the .env template lists the owning keys for deploy-time injection. A related value deserves equal attention: the signing secret. Manifests that contain a JWT often also contain the HMAC secret or private key used to mint tokens, under names like jwt_secret or signing_key. The suspicious-key rule flags exact names like secret and private_key at medium severity, and a random signing secret of 16 or more characters trips the 4.5-bit entropy threshold at high severity. Building on this, a leaked signing secret outranks any single leaked token, because it lets an attacker forge unlimited tokens with arbitrary claims.6
The signing secret outranks the token
A related value deserves equal attention, because the signing secret is the part that truly matters once a JWT has leaked. Manifests that contain a JWT often also contain the HMAC secret or private key used to mint tokens, under names like jwt_secret or signing_key, and those names should set off the same alarm as the token itself.
The suspicious-key rule flags exact names like secret and private_key at medium severity, and a random signing secret of 16 or more characters trips the high-severity entropy threshold on its own. A leaked signing secret outranks any single leaked token, because it lets an attacker forge unlimited tokens with arbitrary claims rather than reuse one captured value.
Invalidating a leaked JWT
Expiry is not revocation, and revocation is not always available. A stateless verifier accepts any correctly signed token until exp, so your options depend on architecture: rotate the signing key to invalidate every outstanding token at once6, consult your identity provider's session or token revocation APIs if the token is tied to a session, or add the token's jti claim to a denylist if your verifiers check one. Rotating the signing key is the blunt but certain instrument, at the cost of logging out every current holder. Conversely, waiting out a short exp can be acceptable for low-privilege tokens. Whichever path fits, redact the token from the file and move future tokens out of static config entirely, issuing them at runtime instead.
Choosing the right invalidation path
Expiry is not revocation, and revocation is not always available, so your options depend entirely on the architecture you built around the token. A stateless verifier accepts any correctly signed token until its exp timestamp, which means simply waiting is rarely a safe response to a confirmed leak of a privileged credential in production.
Rotate the signing key to invalidate every outstanding token at once, or consult your identity provider's session or token revocation APIs if the token is tied to a session that supports it. Rotating the signing key is the blunt but certain instrument, at the cost of logging out every current holder, whereas waiting out a short exp can be acceptable for low-privilege tokens only.
Try in the tool
What to look for
- Matched shape three dot-separated base64url segments, header starting eyJ
- Suspicious key names for the signing secret secret, private_key, jwt_secret, signing_key
A leaked signing secret is worse than a leaked token: it lets an attacker mint unlimited tokens with arbitrary claims.
Open the Cloud Config Sanitizer tool to try this yourself.
Open the tool →- 1.
M. Jones, J. Bradley, and N. Sakimura, "JSON Web Token (JWT)," RFC 7519, IETF, May 2015. https://datatracker.ietf.org/doc/html/rfc7519
- 2.
Deepak Gupta, "JWT Explained," guptadeepak.com, accessed July 2026. https://guptadeepak.com/ciam-compass/guides/jwt-explained/
- 3.
Stack Overflow, "Why header and payload in the JWT token always starts with eyJ," stackoverflow.com, accessed July 2026. https://stackoverflow.com/questions/49517324/why-header-and-payload-in-the-jwt-token-always-starts-with-eyj
- 4.
M. Jones, J. Bradley, and N. Sakimura, "JSON Web Signature (JWS)," RFC 7515, IETF, May 2015. https://datatracker.ietf.org/doc/html/rfc7515
- 5.
M. Jones and J. Hildebrand, "JSON Web Encryption (JWE)," RFC 7516, IETF, May 2015. https://www.rfc-editor.org/rfc/rfc7516.html
- 6.
Darshan Turakhia, "How Rotating a JWT Secret Logged Out 34,000 Users," darshanturakhia.com, 2024. https://darshanturakhia.com/blog/jwt-secret-rotation-outage/
The first segment is the base64url encoding of the JOSE header, which is a JSON object that begins with an opening brace and a quoted key. Encoding that byte sequence always yields ey followed by J for typical headers. The sanitizer's pattern uses this stable prefix plus the dot-separated three-segment structure to identify tokens.
Yes, as a data leak. The payload decodes without any key, so user identifiers, emails, roles, and internal hostnames in the claims are exposed regardless of expiry. Only the replay risk ends at the exp timestamp. Redact expired tokens from shared files just as you would live ones, and check what their claims revealed.
No, and it does not try. Validity depends on the exp claim and the issuer's signing key, and checking either would mean decoding and processing the token. The tool's job is narrower: recognize the shape, flag it critical, and replace it with __REDACTED_JWT_1__ so the question of validity never has to be answered for a shared file.
Treat it as the more severe finding. A signing secret lets an attacker mint tokens with any claims, not just replay one. Random secrets of 16 or more characters are flagged by the entropy rule at high severity, and key names like secret or private_key trigger the suspicious-key rule. Rotate the secret if the file has already been shared.
No. CapyToolkit doesn't upload or store what you paste; the JWT pattern match and the redaction both run in your browser's JavaScript engine, and closing the tab discards everything. The sanitized download is generated locally, so the token never exists anywhere it did not already.
Database Connection String
One line of config can hold your entire database. Connection strings pack scheme, username, password, host, port, and database name into a single URI,1 following the generic syntax of RFC 3986 where credentials sit in the userinfo section before the at sign.2 The convenience is real: frameworks read a DATABASE_URL and connect with zero further setup, which is why the pattern is everywhere from docker-compose files to Kubernetes ConfigMaps. The cost is that the password travels with the hostname in every copy of the file. The Cloud Config Sanitizer flags postgres://, mysql://, mongodb://, and redis:// URIs as critical findings whenever credentials appear before the at sign. Furthermore, the finding pinpoints the exact key path, so you can fix the source file and not just the pasted copy.
What is postgres://?
postgres://localhost:5432/dev produces no finding.Why connection strings leak more than passwords alone
A bare password out of context is a puzzle; a connection string is a complete instruction. It names the scheme, so the attacker knows which client to use, the host and port, so they know where to point it, and the database name, so they know what they are looking at when they arrive. With managed databases exposed on reachable endpoints, a leaked string can mean immediate access rather than a stepping stone. Consequently, connection strings deserve a faster response than most credential leaks: the password rotates first, and the network exposure of the endpoint gets reviewed second. If the host was internal-only, the leak still matters, because internal reachability is one compromised pod away. Cloud security groups can restrict inbound access to a known range, yet misconfigured rules are common enough that isolation deserves regular verification rather than blind trust.
The detection rule and its deliberate limits
Precision keeps the findings list trustworthy. The rule fires on postgres, mysql, mongodb, and redis schemes followed by any non-whitespace characters and an at sign, which is the signature of embedded credentials, and it stays silent for URIs without userinfo. This means your local postgres://localhost/dev reference will not clutter the results, while postgres://app:[email protected]:5432/prod is flagged critical with the placeholder __REDACTED_DB_CONNECTION_STRING_1__ replacing the whole value. Yet the scheme list is finite by design; a JDBC-style jdbc:postgresql:// string or an unusual scheme will not match this rule. In those cases the entropy detector and the suspicious-key rule, which matches exact names like credentials, provide the fallback coverage worth reviewing in the medium and high bands.
Why the scheme list stays finite
Precision keeps the findings list trustworthy, because the rule fires on postgres, mysql, mongodb, and redis schemes followed by any non-whitespace characters and an at sign, which is the signature of embedded credentials. It stays silent for URIs without userinfo, so your local development reference will not clutter the results while a production string is flagged critical.
Yet the scheme list is finite by design, and a JDBC-style or unusual scheme will not match this dedicated rule on its own. In those cases the entropy detector and the suspicious-key rule, which matches exact names like credentials, provide the fallback coverage worth reviewing in the medium and high bands before you call the file clean of secrets.
ConfigMaps, compose files, and the copy problem
In Kubernetes, connection strings gravitate to ConfigMaps because ConfigMaps feel like the right place for configuration, and a DATABASE_URL is configuration until you notice the password inside it. Kubernetes documentation is explicit that ConfigMaps provide no confidentiality; the credential belongs in a Secret, and better still in a Secret synced from an external manager.3 Docker Compose files repeat the pattern in the environment block of each service. From either starting point, the string spreads through commits, PR diffs, and pasted troubleshooting snippets. Running a manifest through the sanitizer before each share breaks the chain, and the .env template it produces lists DATABASE_URL or the owning key as a variable to populate at deploy time instead.
ConfigMaps feel safe but are not
In Kubernetes, connection strings gravitate to ConfigMaps because ConfigMaps feel like the right place for configuration, and a database URL is configuration until you notice the password sitting inside it. Kubernetes documentation is explicit that ConfigMaps provide no confidentiality, so the credential belongs in a Secret rather than a config map that anyone can read.
Docker Compose files repeat the pattern in the environment block of each service, and from either starting point the string spreads through commits, pull request diffs, and pasted troubleshooting snippets. Running a manifest through the sanitizer before each share breaks the chain, and the dotenv template it produces lists the database URL or the owning key as a variable to populate at deploy time instead.
Rotating a leaked database credential
Rotate the user, not just the file. Change the password for the database role named in the string, or better, create a new role with least privileges and retire the exposed one, updating every consumer through environment injection rather than editing files. Managed platforms make this cheaper: RDS, Cloud SQL, and comparable services expose password resets through their APIs, and connection poolers absorb the switchover.45 During the same pass, check the database logs for connections from unexpected addresses since the leak window opened. Building on this, decide whether the endpoint should be network-reachable at all; a database that only accepts connections from your cluster's network turns a future leaked string from an immediate breach into a defense-in-depth story.
Rotate the role, not the file
Rotate the user, not just the file, because changing the password for the database role named in the string is what actually severs access for the leaked credential. Create a new role with least privileges and retire the exposed one, updating every consumer through environment injection rather than editing files by hand across the fleet one commit at a time.
Managed platforms make this cheaper, because RDS, Cloud SQL, and comparable services expose password resets through their APIs, and connection poolers absorb the switchover without downtime. During the same pass, check the database logs for connections from unexpected addresses since the leak window opened, and decide whether the endpoint should be network-reachable at all.
Try in the tool
What to look for
- Matched schemes postgres://, mysql://, mongodb://, redis://
- Trigger condition a userinfo section (user:password@) before the host
A credential-free URI like postgres://localhost:5432/dev produces no finding; the rule only fires when userinfo is present.
Open the Cloud Config Sanitizer tool to try this yourself.
Open the tool →- 1.
PostgreSQL, "The Connection URI Format," postgresql.org, accessed July 2026. https://www.postgresql.org/docs/current/libpq-connect.html
- 2.
T. Berners-Lee, R. Fielding, and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax," RFC 3986, IETF, January 2005. https://datatracker.ietf.org/doc/html/rfc3986
- 3.
Kubernetes, "ConfigMaps," kubernetes.io, accessed July 2026. https://kubernetes.io/docs/concepts/configuration/configmap/
- 4.
AWS, "ModifyDBInstance," docs.aws.amazon.com, accessed July 2026. https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBInstance.html
- 5.
Google Cloud, "Users: update," docs.cloud.google.com, accessed July 2026. https://docs.cloud.google.com/sql/docs/mysql/admin-api/rest/v1beta4/users/update
The dedicated rule covers postgres://, mysql://, mongodb://, and redis:// URIs that contain credentials before an at sign. Strings without userinfo, like postgres://localhost/dev, do not trigger it. Other schemes such as JDBC URLs fall back to the entropy and suspicious-key rules, so check high and medium findings for those.
Because it is a complete access recipe. Unlike a lone password, the string includes the protocol, host, port, and database name, so a holder needs no additional discovery to attempt a connection. Critical severity also ensures the key lands in the .env template download, which lists critical and high findings for deploy-time injection.
Yes. Internal-only reachability limits opportunistic abuse but not targeted abuse; any foothold inside your network, including one compromised pod, can reach the host. The credential also tends to be reused across environments. Rotate the password and treat the hostname exposure as useful reconnaissance you have handed out.
A Secret, at minimum, because Kubernetes ConfigMaps offer no confidentiality and are readable by anyone with get access to them. The stronger pattern keeps the password out of the URL entirely, assembling the connection string at runtime from a Secret-mounted password, or syncing the whole value from an external secrets manager.
Never. Detection is pure pattern matching on the text you paste, and CapyToolkit doesn't open network connections with your data or send the string anywhere. The redacted output and .env template are generated in your browser, so the credential's exposure surface is unchanged by the check itself.
High-Entropy String
Randomness is measurable, and secrets are random. Claude Shannon's 1948 paper defined entropy as the information content of a message, computed from the frequency distribution of its symbols, and that single idea powers the detection layer that catches secrets no prefix rule knows about.1 A custom session key, an opaque API token from a niche vendor, or a generated webhook signing secret has no recognizable shape, yet its characters are far more evenly distributed than any word or sentence. The Cloud Config Sanitizer measures every string value in your manifest and flags those of 16 or more characters scoring at least 4.5 bits per character as high-severity findings. Understanding what that threshold means, and what slips under it, makes the findings list far easier to act on.
What is Shannon entropy?
4.5 bits per character or more, a combination tuned to catch generated secrets while ignoring words, paths, and hostnames.2Why entropy catches what patterns miss
Prefix rules are a list, and lists are always incomplete. The engine's twelve provider patterns cover AWS, GitHub, Slack, Stripe, and other major formats, but the long tail of credentials has no registry: internal service tokens, HMAC signing secrets, license keys, and randomly generated passwords all lack a documented shape. Entropy sidesteps the whole problem by measuring the one property every machine-generated secret shares, statistical flatness. English prose hovers well below the threshold because letter frequencies are wildly uneven, and identifiers like image names or file paths reuse a small character set. Consequently, a 32-character base64 secret stands out from its surroundings mathematically, no matter what the vendor called it or which key stores it.3
Reading the 4.5-bit threshold correctly
The threshold has a shape worth internalizing. A string drawing evenly from the 64-symbol base64 alphabet can approach 6 bits per character, and mixed-case alphanumerics with digits approach 5.95, so genuinely random tokens in those alphabets clear 4.5 with room to spare once they are long enough for frequencies to even out.4 At the other end, hexadecimal strings max out at 4 bits per character, because only 16 symbols exist.5 This is the method's known blind spot: a purely hex-encoded secret can never reach 4.5, however random it is.2 The engine compensates where it can, since hex-shaped credentials like Twilio SIDs have their own prefix rule, and values under names like secret trigger the key-name rule. Reviewing hex-looking values manually remains a good habit.
Why the alphabet changes the score
The threshold has a shape worth internalizing, because the alphabet a string draws from determines how much information each character can carry. A string drawing evenly from the base64 alphabet can approach 6 bits per character, and mixed-case alphanumerics with digits approach nearly 6, so genuinely random tokens in those alphabets clear the threshold with room to spare once they are long enough.
At the other end, hexadecimal strings max out at 4 bits per character, because only 16 symbols exist in that alphabet. This is the method's known blind spot, because a purely hex-encoded secret can never reach the entropy line, however random it is, which is why the engine compensates with prefix rules for hex-shaped credentials and key-name rules for values under names like secret.
False positives and how to triage them
High severity means probably a secret, not certainly one. Content hashes, cache-busting fingerprints in asset filenames, UUIDs in dense formats, and compressed data snippets are all legitimately random and can cross the threshold, which is why entropy findings rank below the critical provider matches. Triage by context: a high-entropy value under a key named cdn_asset_fingerprint in a public chart is fine to leave, while the same score under connection_params deserves redaction. In the findings table, the dotted key path and the 40-character snippet give you exactly this context without leaving the page. Yet when a value is ambiguous and the file is heading somewhere public, redacting a false positive costs one placeholder; keeping a true positive costs an incident.
Judging a finding by its key path
High severity means probably a secret, not certainly one, because content hashes, cache-busting fingerprints, dense UUIDs, and compressed data snippets are all legitimately random and can cross the threshold. That is exactly why entropy findings rank below the critical provider matches rather than sitting at the top of the severity list.
Triage by context, since a high-entropy value under a key named for an asset fingerprint in a public chart is fine to leave, while the same score under connection parameters clearly deserves redaction. The dotted key path and the 40-character snippet give you exactly this context without leaving the page, and when a value is ambiguous and the file is heading somewhere public, redacting a false positive costs one placeholder while keeping a true positive costs an incident.
What happens to flagged strings
Redaction treats high-entropy findings like any other secret. The sanitized output replaces the value with __REDACTED_HIGH_ENTROPY_STRING_1__, counters keep multiple findings distinct, and the owning key joins the .env template alongside the critical findings, since the template includes both critical and high severities. The original value appears only as a 40-character snippet in the findings table on your screen, and nothing is transmitted or stored. Building on this, the ordering of the rule pipeline matters for interpretation: provider patterns run first, so a string flagged as high entropy specifically did not match any known format, telling you it is either a custom secret or benign randomness.6 That distinction, plus the key path, is usually all you need to decide in seconds.
What redaction and pipeline order tell you
Redaction treats high-entropy findings like any other secret, so the sanitized output replaces the value with __REDACTED_HIGH_ENTROPY_STRING_1__ and counters keep multiple findings distinct in the same file. The owning key joins the dotenv template alongside the critical findings, since that template includes both critical and high severities for deploy-time injection.
The ordering of the rule pipeline matters for interpretation, because provider patterns run first, so a string flagged as high entropy specifically did not match any known format. That tells you it is either a custom secret or benign randomness, and that distinction, plus the key path shown on screen, is usually all you need to decide in seconds without transmitting or storing anything.
Try in the tool
What to look for
- Minimum length checked 16 characters
- Entropy threshold 4.5 bits per character
- Known blind spot hex-only strings max out at 4 bits/char and never trigger this rule
Provider prefix rules run first; a high-entropy-only finding means the string matched no known credential shape.
Open the Cloud Config Sanitizer tool to try this yourself.
Open the tool →- 1.
Wikipedia, "A Mathematical Theory of Communication," wikipedia.org, accessed July 2026. https://en.wikipedia.org/wiki/A_Mathematical_Theory_of_Communication
- 2.
Yelp, "detect-secrets: High Entropy Strings Plugin," github.com, accessed July 2026. https://github.com/Yelp/detect-secrets/blob/master/detect_secrets/plugins/high_entropy_strings.py
- 3.
IETF, "RFC 4648: The Base16, Base32, and Base64 Data Encodings," rfc-editor.org, October 2006. https://www.rfc-editor.org/rfc/rfc4648.html
- 4.
IETF, "RFC 4648: The Base16, Base32, and Base64 Data Encodings," datatracker.ietf.org, October 2006. https://datatracker.ietf.org/doc/html/rfc4648
- 5.
Wikipedia, "Entropy (information theory)," wikipedia.org, accessed July 2026. https://en.wikipedia.org/wiki/Entropy_(information_theory)
- 6.
Truffle Security, "TruffleHog: Secret Scanner," github.com, accessed July 2026. https://github.com/trufflesecurity/trufflehog
Length is a stability requirement: entropy computed on very short strings is noisy, so anything under 16 characters is exempt from this rule. The 4.5 bits per character threshold then separates machine-generated randomness from natural text and identifiers. Both conditions must hold before the sanitizer reports a high-severity finding.
Yes. Hexadecimal secrets top out at 4 bits per character, human-chosen passwords are far from random, and short tokens fall under the length floor. The provider prefix rules and the suspicious key-name rule exist precisely to cover those cases, which is why the tool layers three detection methods instead of relying on entropy alone.
Because it is genuinely high entropy; the math cannot distinguish a random secret from a random identifier. Use the key path to decide: fingerprints and content hashes under clearly non-sensitive keys can stay, and you can keep the original value from your source file. The finding is a review prompt, not an accusation.
There is no standardized value; secret scanners choose thresholds balancing recall against noise, and 4.5 on strings of 16 or more characters is this tool's calibration. Lower thresholds flag more identifiers as noise, higher ones miss shorter or mixed secrets. The published rule lets you reason about exactly what will and will not be caught.
No. The frequency counting and logarithm math are trivial for a browser, and CapyToolkit doesn't transmit your input at any point; every value is measured locally in JavaScript. That design is what makes it safe to paste a file you suspect contains secrets in the first place.