API keys and tokens in AI-generated code: risks and checks before deployment

API key e token nel codice AI: rischio grave nascosto

API keys, tokens, and secrets in AI-generated code: the most underestimated risk

An AI assistant can write code in minutes that connects to databases, payment APIs, cloud buckets, repositories, SaaS systems, email services, and deployment environments. However, to get everything working immediately, the shortest path often leads to a key pasted into a file, a variable printed in logs, a .env created on the fly, or a token copied into a chat during debugging.

The risk of secrets in AI-generated code goes beyond classic hardcoding. API keys, tokens, connection strings, and credentials can end up in prompts, chat histories, issues, build logs, artifacts, source maps, container images, tests, READMEs, temporary files, local configurations, and remote workspaces used by agents. The repository might look clean while a key remains exposed elsewhere.

For developers, technical founders, and DevOps, the concrete question before deployment is: what secrets has the AI seen, where were they saved, which ones reached the repository, which ones ended up in pipelines, and which ones must be rotated before the app touches real data or production services.

πŸ”΄ Web Application Penetration Testing: identify hidden risks and strengthen your security with a focused assessment by ISGroup specialists.

Why AI agents increase the risk regarding secrets

AI coding tools work within a broader context than a single file: they can read portions of a repository, generate configuration files, propose scripts, modify tests, run commands, explain errors, and help connect external services. In many workflows, especially with agent mode, terminal access, or remote environments, the assistant does not just suggest code but actively participates in the operational process.

This creates a new surface area for secrets. During a debugging session, a developer might paste a connection string to ask why the database isn’t responding; the agent might create an .env.local to make a test pass; a command might print environment variables to logs; a build might include a key in the frontend bundle. Speed makes the problem less visible: when the code finally works, the team tends to focus on the feature, but an exposed key can grant access to payments, cloud, databases, repositories, SaaS services, production systems, or customer data.

What counts as a secret

A secret is not just a password. In a modern project, the perimeter includes API keys, OAuth tokens, personal access tokens, JWT secrets, webhook secrets, private keys, certificates, .pem files, service accounts, database URLs, connection strings, session cookies, refresh tokens, deploy tokens, signing keys, GitHub or GitLab tokens, cloud credentials, SMTP passwords, Slack tokens, Stripe keys, and LLM provider keys.

Some keys seem “public” because they are used in the frontend or in provider documentation, but even in those cases, restrictions, scopes, and the potential for abuse must be understood. A Supabase anon key is not the same as a service role key, and a test token can still read staging data, send emails, consume credit, or open a path to internal systems.

Before publishing, every secret should have at least four pieces of information: what it is for, which environment it applies to, what privileges it grants, and where it is stored. If a key has no owner, expiration, or clear scope, it becomes difficult to decide what to do when it appears in an AI-generated diff.

Where secrets end up during “vibe coding”

The first place to check is the code itself: sources, configurations, tests, scripts, examples, and generated files. Agents can insert real values into config.ts, settings.py, docker-compose.yml, CI/CD workflows, migrations, seeds, fixtures, deploy scripts, or test files, turning a temporary example into a configuration that makes it to a commit.

The second place is the repository surrounding the code: .env files in various variants, backups, .pem files, keys downloaded from cloud providers, CLI credentials, hidden tool folders, debug output, and temporary files. An incomplete .gitignore is enough to turn a local shortcut into a permanent leak in the Git history.

The third place, often the most underestimated, is outside the repository: prompts, chats, tickets, issues, PR comments, CI/CD logs, artifacts, container images, source maps, test reports, screenshots, crash reporting, and observability systems. Deleting a key from a file does not remove the key from the chat where it was pasted or the log where it was printed.

Hardcoding: when code works immediately but exposes too much

The simplest pattern is also the most frequent: to connect a service, the AI suggests a key directly in the code or in a copyable example. In a local demo, it seems harmless, but in a PR, a shared repository, or an automatic deployment, it becomes real access. Common cases include database URLs in server-side files, API tokens in integration functions, payment keys in tests, SMTP passwords in configurations, hardcoded JWT secrets, webhook secrets copied into handlers, and service keys used to bypass an authorization issue.

The fix is not just “move to an environment variable.” The variable must be managed in a secret manager or the deployment system with correct permissions, separated by environment, not printed in logs, and not accessible to the frontend. If the key has been committed or shared, it must be rotated.

.env files, ignore files, and local configurations

.env files are useful for development, but they become risky when the AI creates or modifies them without a clear convention. An agent might generate .env.example with real values, suggest .env.production to simplify deployment, or insert a credentials file into the project because an SDK requires it.

It is important to check .gitignore, .dockerignore, the AI tool’s ignore files, and those used by the IDE or the agent, because in some workflows, you need to prevent local folders, .env files, private keys, build outputs, or configuration directories from entering the assistant’s context. The goal is not just to avoid the commit: it is to reduce what the agent can read and reuse.

A good pattern is to maintain .env.example with variable names and dummy values, document where to obtain real keys, and use secret managers or protected platform settings for staging and production. Every file with real values should remain outside the repository and outside of prompts.

Prompts, chats, and agent history

Many leaks do not originate from the code, but from the conversation. During debugging, it is easy to paste a complete error with headers, tokens, signed URLs, payloads, connection strings, or dashboard screenshots: the assistant responds, the chat remains saved, and the team forgets that the secret has left the project perimeter.

The operational rule is simple: do not paste secrets into prompts. When asking for help with an error, it is sufficient to replace tokens and keys with placeholders, use synthetic data, and reduce payloads to a minimum. If a real key has already been shared in chat, it must be treated as exposed: you need to verify the provider, rotate it, and check for anomalous access.

Privacy Mode, enterprise plans, or retention settings can reduce some risks, but they do not turn a secret pasted into a chat into a best practice. Even when data is not used for training, it can remain in history, logs, exports, support systems, or the tool’s operational context according to the service settings.

Build, test, and deploy logs

AI-generated scripts can print too much. A console.log(config), a printenv, an initialization error, a failed test, or a debug command can expose environment variables in CI/CD logs, which are often visible to more people than the repository, kept for weeks, or copied into artifacts.

It is worth checking GitHub Actions workflows, GitLab CI, Vercel, Netlify, Replit, Docker builds, npm scripts, test runners, and deployment systems, looking for output that shows configurations, headers, tokens, full URLs, connection strings, or payloads. It is also important to verify secret masking, because not all custom tokens are masked automatically and some transformations can bypass protections. Every change to builds, tests, and deployments should be reviewed as part of secret security, even when the AI only intervenes to “help with debugging.”

Artifacts, frontend bundles, and source maps

A secret can leak even after the build. If a private variable is used in client-side code, it can end up in the JavaScript bundle; if source maps are public, they can reveal details the team thought remained internal; if a container image includes .env files or credentials in previous layers, removing them in a subsequent step might not be enough.

This step is particularly important for apps generated with v0, Lovable, Bolt.new, Replit Agent, or other tools that quickly connect frontends, APIs, and deployments. In the frontend, you must precisely distinguish between public and private variables: prefixes like NEXT_PUBLIC_ or equivalents make a variable available to the browser, so if the AI moves a private key to a public variable to resolve an error, the deployment can expose it to anyone who opens DevTools.

Agents with terminal, filesystem, and MCP

When an agent can read files, execute commands, or use external tools, the nature of the risk changes. The problem is not that the agent “wants” to steal secrets, but that the operational context can include sensitive files and outputs: a command can read .env, an MCP tool can access repositories or tickets, a remote session can contain environment credentials.

Before giving an agent operational access, it is useful to separate runtime secrets from the development workspace, using dedicated environments, least-privilege credentials, exclusion files, approval for sensitive commands, and service accounts not reused in production. For MCP and external tools, you need to map which systems can be read or modified β€” repositories, issue trackers, databases, cloud, file storage, CI/CD, secret managers β€” because if a tool can access a secret, that secret must be governed as part of the agent’s perimeter.

Private repository does not mean protected secret

A private repository reduces exposure, but it is not a secret manager. Credentials in the code can be read by collaborators, internal forks, CI/CD, analysis tools, installed apps, backups, mirrors, agents, and compromised accounts. If the repository becomes public by mistake or is shared with a vendor, the secrets in the history immediately become critical.

The Git history problem is particularly relevant: even if you remove the key from the latest commit, it can remain in previous commits, branches, tags, pull requests, caches, or forks. Rewriting history can reduce visibility, but it does not guarantee that no one has already read the secret, so rotation remains necessary. Before opening a repository to new collaborators, publishing a template, sharing a demo, or connecting external agents, it is essential to perform a scan on history, branches, and tags, not just the working tree.

Secret scanning: necessary, not sufficient

Secret scanning and push protection are fundamental controls that block many errors before they reach the remote repository and help detect known keys already present in the codebase. GitHub, cloud providers, and various security tools offer useful checks on recognized patterns.

The limitation is that not every secret has a known signature: internal tokens, custom strings, broken credentials, composite secrets, encoded values, proprietary files, or keys generated by corporate systems can escape standard scanners. Even a real but expired token can signal a process problem, because if it got there once, it can happen again. For AI-generated projects, the most robust strategy combines automatic scanners, custom patterns, manual review, and output checks: a clean scanner is a good sign, not definitive proof.

Rotation: when deleting is not enough

If a key has been exposed, the question is not “did we remove it?” but “is it still valid?”. A secret committed, printed in a log, pasted in a chat, included in an artifact, or shared in a ticket must be considered compromised until it is rotated or revoked.

Rotation must follow an orderly sequence: identify the service, understand privileges and consumers, create a new key, update environments and pipelines, verify that the app works, revoke the old key, and check access logs for anomalous use. In critical systems, you must also verify if the secret granted access to customer data, payments, cloud, or repositories.

To reduce future impact, it is useful to use minimal scopes and separate keys for each environment: a development key should not be able to read production, a token used by a pipeline should not have global administrative privileges, and a webhook secret should not be reused across different services.

What to do when you find an exposed secret

When a key emerges in an AI-generated PR, in a log, or in a chat, the first question is not how to clean the file but what capability that credential grants: can it read a database, modify cloud and IAM, send payments or emails, deploy, or access repositories or customer data?

The next step is to delimit exposure by searching for the same value in the working tree, Git history, branches, tags, PRs, CI/CD logs, artifacts, container images, source maps, issues, tickets, prompts, and chats. If it appears in multiple places, the rotation must cover all consumers and the cleanup must include systems that keep copies.

The correct sequence is: create a new key with minimal scope, update the application and pipeline, verify that the service works, revoke the old key, and check the provider’s access logs. If the credential involved production, customer data, payments, repositories, or cloud, the finding should block the release until rotation is complete.

Even a “test” key must be verified, because many staging environments share data, webhooks, buckets, or service accounts that are broader than expected. Before classifying the incident as minor, you must check the environment, privileges, spending limits, accessible data, and connected integrations.

Cleanup checklist before deployment

Before publishing code generated or modified with AI, perform at least these checks:

  • Scan the repository, Git history, branches, tags, and pull requests.
  • Search for .env, .pem, .key, .p12 files, credential files, backups, and CLI configurations.
  • Check build, test, and deploy scripts and CI/CD workflows.
  • Verify recent logs, artifacts, container images, frontend bundles, and source maps.
  • Review prompts, chats, tickets, and issues used for debugging.
  • Separate dev, staging, and production keys.
  • Move secrets to a secret manager, vault, or protected platform variables.
  • Enable secret scanning and push protection where available.
  • Add custom patterns for internal tokens or proprietary formats.
  • Rotate every exposed, suspicious, or key passed into an unintended system.

This checklist must be executed even if the repo is private and even if the app is not yet public, because a secret can be exploited before go-live if it grants access to cloud, databases, payments, email, or repositories.

How ISGroup can verify secrets and configurations

ISGroup can support targeted verification of code generated or modified with AI, focusing on hardcoding, sensitive files, configurations, pipelines, logs, artifacts, dependencies, and the ways in which agents have interacted with the project. The goal is to understand if there are exposed credentials, if they need to be rotated, and what controls to insert before the next deployment.

If you find in an AI-generated project… Main risk Recommended control
API keys, tokens, .env files, connection strings, or sensitive files in the repository Direct credential exposure Code Review
Services, hosts, panels, or APIs reachable via suspicious credentials Exploitable surfaces or exposed configurations Vulnerability Assessment
Agent mode, CI/CD, build artifacts, secret scanning, and ungoverned merge processes Repeatable risk on subsequent releases Software Assurance Lifecycle
Cloud, buckets, databases, IAM, or service accounts linked to exposed keys Excessive privileges or cloud misconfiguration Cloud Security Assessment
Apps or APIs already online with a potentially compromised key Real-world abuse from the outside Web Application Penetration Testing

The choice of control depends on what the secret allows you to do: read data, modify cloud, send payments, access repositories, use external APIs, or publish deployments. Eliminating secrets from the code before release and reducing the potential damage in case of new exposure are the two concrete goals to achieve before go-live.

Evidence to prepare for a review

For an effective review, it is useful to prepare the repository, affected branches, AI-generated PRs, a list of tools used, CI/CD workflows, deployment systems, environments, ignore files, secret managers, a list of critical variables, and secret scanning alerts already received.

It is equally important to collect clues outside the code: chats where errors were pasted, debug tickets, build logs, artifacts, container images, source maps, screenshots, shared prompts, READMEs, and temporary scripts. If a key has been rotated, it is useful to keep track of when, by whom, where it was used, and which access logs were checked, because this information allows you to distinguish between a truly exposed secret, a false positive, a test key without privileges, a production credential to be revoked immediately, and a process problem to be corrected in the development cycle.

Decision before publication

Block the deployment if you find production keys in the repository, service role keys in the frontend, database URLs with real privileges, cloud tokens with broad scopes, secrets in public logs, downloadable artifacts with credentials, or tokens pasted in chats without rotation.

You can plan improvements with clear residual risk after the release: strengthening variable naming, adding custom patterns to scanners, completing documentation, reducing the scope of non-critical keys, or improving team onboarding. The rotation of an exposed key should never be postponed.

The final decision must be verifiable: which secrets were found, which were rotated, which scanners are active, which files are excluded, which logs were checked, and what process prevents the same error from returning in the next release.

Frequently Asked Questions

  • If the repository is private, do I still need to remove API keys?
  • Yes. A private repository is not a secret manager. Collaborators, CI/CD, agents, installed apps, backups, and compromised accounts can still access the credentials.
  • If I deleted the key from the code, do I need to rotate it?
  • Yes, if the key was committed, printed in logs, included in artifacts, or pasted into prompts. Deleting it from the file does not invalidate the secret.
  • Is secret scanning enough to be safe?
  • No. It is a necessary control, but it may not recognize custom tokens, partial secrets, internal formats, or credentials present outside the repository, such as logs and chats.
  • Can I put keys in the frontend if the framework allows it?
  • Only if they are keys designed to be public and limited. Service keys, private database URLs, administrative tokens, JWT secrets, and cloud credentials must not end up in the bundle.
  • What do I do if I pasted a key into an AI chat?
  • Treat it as exposed: rotate it, check the provider’s access logs, check where it was used, and update the team on how to share errors without real credentials.
  • Which secrets are most urgent to rotate?
  • Cloud keys, GitHub/GitLab tokens, service role keys, production database URLs, payment API keys, webhook secrets, JWT secrets, private keys, and tokens with access to customer data.

Protect your organisation with Web Application Penetration Testing.

Choose ISGroup for a practical, tailored engagement:

  • A focused assessment of your environment and requirements
  • Clear findings with a prioritised, actionable roadmap
  • Direct support from experienced specialists through remediation and implementation
Talk to an expert

Further reading