AI Coding Assistant Local Approval Files Can Leak Secrets

    When an AI coding assistant remembers an approved command, it may persist the full command string—including plaintext passwords, tokens, or key fragments—in a project-local settings file. This article explains how that file becomes a secret store once it enters version control, why ordinary secret scanners miss it, and how to rotate credentials, stop tracking the file, and approve command patterns instead of secret-bearing commands.

    AI coding assistants are now part of everyday development: they explain code, generate scripts, and run commands in the terminal. To cut down on repeated prompts, many tools offer a convenience option along the lines of “approve this and don’t ask again.” The downside is that the full command may be written, unchanged, into a local settings file under the project directory—often with database passwords, access tokens, or fragments of remote-login private keys in plaintext. Once that file enters a repository, especially a public one, the secret is no longer only on the local machine. It spreads with commits, branches, and forks. This article looks at the mechanism, the exposure, and practical response: how a local approval file becomes a “secret vault,” and how to stop the bleed systematically.

    Where the problem comes from

    Before running a command that might change the environment, reach the network, or read or write sensitive paths, an AI coding assistant usually asks for confirmation. If the user chooses “approve and don’t ask again,” the tool has to remember the shape of that command so it can allow it later. A common implementation writes the full command string into a local settings file inside the project (for example, a hidden config under the project directory) instead of recording only an abstract command pattern.

    The risk concentrates in three places. First, commands are often written as one-off scripts that put passwords and tokens directly in arguments rather than reading them from environment variables or a secrets manager. Second, the local file usually sits inside the project tree, so developers easily commit it along with other config. Even if the tool tries to add the path to a machine-wide ignore list, it typically does not rewrite the repository’s own ignore rules, so the protection does not travel with the project. Third, deleting the file from the working tree later does not erase it from version history, tags, forks, or backup mirrors. Removing the working copy is not the same as clearing history.

    Compared with a typical security model, a cloud session can store API keys encrypted so the model side never sees plaintext. A local approval file does the opposite: plaintext commands land on disk and in the repository. The two paths do not substitute for each other. The cloud story answers “can the model see the secret?” The local incident answers “has the repository become a channel that distributes the secret?”

    How wide the exposure is, and why routine scans miss it

    Public-repository scanning practice shows that once an approval file is committed, the scale can grow quickly: many repositories contain the same kind of local settings file, and some of those files include at least one recognizable secret. Secret types cover direct database passwords, remote-login credentials, and access keys for object storage and compute instances. A substantial share of those repositories have already exposed the file on the default branch for a long time, which means automated crawlers and mirror sync may already have taken copies.

    Conventional secret scanners rely on fixed rules and entropy heuristics. They do not fully recognize passwords embedded in long command lines, JSON-escaped, and tucked inside approval-record fields. The result is missed detections, and even two complementary rule sets still leave gaps. Widening the search to historical commits, shared settings, agent runtime logs, and forks pushes the count higher still. The point is not any single number. It is that once a full command enters version control, git’s immutability stretches the exposure window.

    Industry comparison also shows that not every coding agent writes “the full approved command” into a project file by default. Some record only a command pattern (for example, allowing a class of package-manager scripts). Others keep approval state in the user home directory and, by default, out of the repository. Writing plaintext commands into the project tree by default is the design choice that drives this class of incident—not a property of every assistant.

    Why deleting the file does not save history

    A version-control system stores each commit as a snapshot. After a file is removed from the latest tree, older commit objects remain intact. Full history beyond a shallow clone, pack files, and web or API fetches from the hosting platform can all restore the old content. Response order must therefore be: assume the secret is already leaked and rotate it, then clean up references—not delete the file first and decide later whether to rotate.

    A local global exclude list applies only on that machine. Fresh clones, continuous-integration environments, and colleagues’ machines do not inherit it automatically. Repository-level ignore rules must be added explicitly, and tracking must be stopped by removing the file from the index while keeping the working copy. For history that has already been pushed, teams also need to judge whether to rewrite public history (which affects collaboration), whether to rotate secrets that appear in forks, and whether to notify downstream users who may have downloaded the repository.

    Response and hardening

    Rotate first. Treat any database password, cloud access key, or remote-login credential that appeared in an approval file as public: revoke the old credential, issue a new one, and tighten network sources and least privilege. Do not treat “the scanner did not report it” as proof of safety.

    Stop tracking and ignore the path. Remove the local settings file from the version index and list that class of path in the repository ignore rules. Check whether shared settings, agent logs, or sample environment files were committed as well. For sensitive commits already in history, follow organizational policy: either rewrite history or accept that history is contaminated and rely on rotation.

    Approve patterns, not commands that contain secrets. Express “allow this class of build or test script” as a pattern match, not as approval of one full command with an embedded password. Passwords should enter the process only from environment variables, a secrets manager, or secret injection in continuous integration. They should not appear in command-line arguments, on-disk config, or chat transcripts.

    Development and collaboration habits. Before merging, check that hidden config was not added by mistake. Assume that every commit in a public repository can be searched. Inside an organization, periodically search for the same kind of local settings file and rotate on discovery. Scan rules should cover long command strings inside JSON fields, not only well-known secret filenames.

    What this implies for design

    Convenient confirmation reduces friction, but it treats “the full command” as a policy object that can be persisted. A sounder model persists capability boundaries—which programs are allowed, and which argument shapes—rather than the string of one successful run. Policy should live at user level, outside the repository by default. If something must live in the project, it should store only patterns that contain no secrets, and repository ignore rules should exclude secret-bearing overrides by default.

    Cloud and local paths need separate assessment. Encrypted API keys and a model that cannot see them do not imply that local disk and git are safe. Logs, session exports, approval caches, and debug dumps are all second landing places for secrets. Security review should put those landing places on the checklist, not only whether the main config is encrypted.

    For teams that use AI coding assistants heavily, “did an approval file enter the repo?” belongs in the release gate: scan assistant config inside the project in continuous integration, forbid plaintext-password patterns, and open a rotation ticket for repositories that have already leaked. Once a convenience option is treated as a vault, the cost is secrets sitting on the default branch for hundreds of days with no one noticing. Rotate before cleanup, approve patterns instead of secret-bearing commands, and prefer repository-level ignore over a machine-local exclude. Those three practices are the minimum that turns this class of incident from “bound to recur” into “manageable.”