Local Approval Settings in AI Coding Assistants Can Leak Secrets: Risks and Prevention
AI coding assistants often offer an "approve and don't ask again" option for shell commands. The approved command can be saved verbatim in a local project settings file. If that command contains a database password, access token, or cloud credential in plain text, the secret can end up in version control, especially in public repositories. This article explains how the problem happens, what public scans have found, why secret scanners miss some cases, and how to rotate exposed credentials, keep settings files out of repositories, and approve command patterns instead of full commands.
AI coding assistants are becoming a standard part of daily development. To reduce repeated confirmations for the same shell operations, many tools offer an “approve and don’t ask again” option. The trade-off is that a fully approved command may be written verbatim into a local configuration file inside the project directory. If that command includes a database password, access token, or cloud credential in plain text, the file becomes a store of secrets that can be searched in bulk once it reaches a repository, especially a public one.
Cloud-side documentation often stresses that the model cannot see plaintext keys. Local settings can still write those same keys into files that get committed. The two statements do not conflict. They cover different parts of the workflow. This article covers the mechanism, the scope of exposure, and practical safeguards. It does not focus on one product. It discusses a general problem that has repeatedly appeared across the industry.
Mechanism: Why Approval Records Turn Into Plaintext Secret Stores
Local agents usually need to run builds, tests, and dependency installs with restricted permissions. To avoid a permission prompt every time, tools persist the command strings that the user has explicitly allowed. The usual location is a settings file inside the project. The file name varies by tool, but its function is essentially a list of approvals for the local machine or repository.
By design, this file should exist only in the developer’s workspace. Some implementations add it to a machine-wide version control exclude list but do not add it to the repository’s own ignore file. As a result, the protection follows the machine, not the project. A collaborator who clones the repository does not have the same global exclude rule, so the file can easily be committed.
The problem is more serious because the full command is saved rather than abstracted into a pattern such as “allow npm scripts”. Once a user approves a command line that contains a password, the password appears in plain text in JSON or a similar structure.
This differs from cloud sessions, where keys are encrypted and hidden from the model. Cloud-side protections address the inference path. Local approval files affect configuration and version history. Deleting a file from the working tree does not remove committed history objects. Forks, backups, and mirror repositories keep copies of the same blob. The root cause combines three factors: convenient defaults, ignore rules that do not travel with the repository, and plaintext commands written to disk.
Exposure Patterns and Why Scanners Miss Some Cases
Large-scale scans of public code hosting platforms found tens of thousands of committed local settings files. Thousands of them contained at least one suspected secret, totaling thousands of distinct credentials. When the scope was widened to include commit history, files mistakenly treated as shared settings, agent run logs, and forks, the number of affected repositories and secrets increased further.
Direct database passwords made up more than one third of the leaked secrets. The rest included private key material for remote login and access keys for object storage and compute platforms. A significant share of repositories had exposed secrets on their default branch for periods on the order of half a year or longer. This pattern points to silent accumulation. A developer may believe that checking “don’t ask again” closes the matter. In practice, a one-time command becomes a long-term liability.
Generic secret scanners miss some of these samples. Common reasons include: the command is wrapped in a JSON string, the password is concatenated with parameters, the key name is unusual, or the credential format does not match common regular expressions. Automated scanning alone cannot close the gap. Teams also need to change what gets stored, where it gets stored, and how commands are approved.
Protective Practices: Rotate First, Then Cut the Propagation Paths
Treat any credential in pushed history as public, and rotate it. Any password, token, or certificate that appears in pushed history should be considered exposed. Prioritize rotating database accounts, cloud access keys, and third-party API tokens, and check whether they have been used abnormally. Deleting the file and pushing again will not remove old commits.
Untrack the file and add repository-level ignore rules. After rotation, use your version control commands to stop tracking the local settings file. You can keep the working copy if needed. Then explicitly exclude that type of path in the repository’s root ignore file. A global exclude protects only your own machine. It does not protect teammates, CI systems, or open source contributors.
Approve patterns, not full commands that contain secrets. Narrow permissions to reusable command templates, such as allowing a script prefix for a particular package manager or a test command prefix. Prevent connection strings that contain passwords from being saved in the persisted approval list. Passwords should come from environment variables, a secrets management service, or a local keyring, and be injected at runtime rather than placed in command-line arguments.
Govern history and detect leaks continuously. For public repositories, assess whether history must be rewritten in addition to rotation, weighing the cost to collaborators. Add secret scanning to the pipeline to cover the current snapshot and recent history. Create separate rules for JSON-embedded strings, log directories, and agent cache directories. Block merges when findings occur.
Set team conventions. Add review checklist items: Are local agent settings files committed? Are
.envfiles committed? Are secrets pasted into command lines? Preconfigure ignore rules in new repository templates. For open source projects, assume that everything will be crawled.
The following example shows environment variable injection, which is safer than plaintext arguments. It is a generic pattern, not syntax specific to any tool.
# Not recommended: the password appears in a command that can be loggedmigrate --url postgres://user:PASSWORD@host/db# Recommended: read at runtime from the environment or a secrets serviceexport DB_URLmigrate --url "$DB_URL"
The following repository-level ignore rules ship with the project. Adjust them to match the actual file names.
# Repository-level ignore rules, distributed with the project**/.agent/settings.local.json**/*settings.local.jsonagent-logs/
Implications for Product and Process Design
If an agent must persist approval information, it should write to the user’s home directory by default and never place that data in the project tree. If the data must live inside the project, the agent should add the file to the ignore rules during initialization. It should also refuse to save plaintext commands while the file remains unignored. Stored content should be hashed or structured as an allowed executable plus an argument pattern, rather than as whole shell lines.
Cloud-side key management, access control, and audit logs can complement local practices. Short-lived credentials, least-privilege roles, and alerts for unusual calls reduce the window in which a static password that has sat in a repository for months can be exploited.
Cloud designs focus on encryption and minimal visibility, which address the model and data transport. Local approval files affect developer experience. Both areas need to be handled correctly so that a secret does not become public after one click on “don’t ask again”. Deleting files does not fix history. A workable fix is a closed loop: rotate the credential, ignore the file, and approve command patterns instead of full commands.
