Skip to content
  1. Home
  2. Articles
  3. Leaked Secrets in Repos and Pipelines: Detect, Rotate and What to Ask For at Handover
120
Enterprise

Leaked Secrets in Repos and Pipelines: Detect, Rotate and What to Ask For at Handover

Leaked Secrets in Repos and Pipelines: Detect, Rotate and What to Ask For at Handover

API keys, database passwords and tokens can end up in Git, chat, tickets and Docker images. This article summarizes OWASP and GitHub guidance and turns it into what a buyer can ask a developer to deliver, and the order to act in on the day a key leaks.

Suppose the team that built your system has just handed it over, and a new developer taking over opens the repository to read its change history. In a configuration file from several months ago, they find the production database password written in plain text. The original developer deleted that line long ago, but Git's history still keeps everything. Three questions follow. Does that password still work? Who has ever had access to this repository? And if the password has to change, will the system stop?

This article is written from the viewpoint of a team that designs and hands over systems, not as incident response specialists, and for the buyer who receives the system. We describe what OWASP's guidance, GitHub's documentation and one security vendor's report say, what that evidence does and does not show, and then translate it into a list of things you can ask a developer for at handover and the order to act in on the day a key actually leaks. Everything here is defensive guidance, not a method of attacking anyone.

What we mean by a secret

In software work, a secret is data that lets a program prove its identity to another system: an API key for an external service, a database password, a token used to call a cloud provider's API, or a key used for signing or encryption. Whoever holds it can do what that program can do, without knowing any person's password. A buyer should therefore not see it as a technical detail of the development team. It is the key to a system you own.

This is different from what "credential leak" usually means in Thailand: staff passwords exposed in someone else's data breach. That side already has services built for it, such as ThaiCERT's Credential Leak Management System, which organizations can apply to use to search for leaked user-account data by their own domain. The service scopes itself to user-account login data and does not mention API keys or tokens. This article is about the other side, where nobody types a password at login, so there is no MFA in the way, and there is often no clear owner.

What the sources say

The first source is OWASP's Secrets Management Cheat Sheet, a practice guide maintained by the application security community. It is not a law or a standard that binds anyone. The parts relevant to handover are these (see the OWASP document).

  • Secrets should be rotated regularly so that stolen credentials only work for a short time, and rotation should be automated where possible.

  • Storage, provisioning, auditing, rotation and management of secrets should be centralized, to control who reaches what and to limit leaks.

  • Engineers should not have access to every secret in the secrets management system, and access should be granular, secret by secret.

  • Who requested a secret, and when it was used, should be recorded, and those records should be protected from tampering or deletion.

  • Secrets should not be written into source code or into Docker ENV and ARG instructions. Use the CI/CD tool's secret store or a secrets manager instead.

  • CI/CD tooling should be run like a production system, pipeline output should not leak secrets, and detection tools such as detect-secrets should run before a commit.

  • When a secret leaks, revoke it immediately, rotate to a new one (ideally automatically), remove the leaked one from code, logs and other systems, and give incident responders access to that secret's usage history.

The second source is GitHub's documentation on secret scanning (see the GitHub documentation). It states that scanning covers the Git history of every branch, as well as issues, pull requests, discussions and wikis, which means a secret can leak in more places than the current code. It advises rotating the affected credential immediately when you receive an alert, and says that removing a secret from Git history is time-intensive and often unnecessary if you have already revoked the credential. That reverses the order many teams think in. Many start by trying to erase the history, when the first thing to do is make the leaked key stop working.

The third source is GitGuardian's report The State of Secrets Sprawl 2025, dated 11 March 2025 (see the GitGuardian report). Before reading the numbers, note that GitGuardian sells secret detection tools, so the figures are what that company's detectors found, not a survey of every organization. According to the report, 23.8 million secrets leaked on public GitHub in 2024, up 25 percent on the year before. Of the secrets that leaked in 2022, 70 percent were still valid when retested. Secrets were found in 35 percent of private repositories, against 4.6 percent of public ones. 2.4 percent of corporate Slack channels contained leaked secrets, 6.1 percent of Jira tickets exposed credentials, and of the secrets detected in Docker, 98 percent were in image layers.

GitGuardian has since published its 2026 edition. Its summary page reports that 32.2 percent of internal repositories contain at least one hardcoded secret, against 5.6 percent of public repositories, and that 64 percent of secrets confirmed valid in 2022 were still valid four years later. The direction matches the 2025 edition. The Slack, Jira and Docker figures above are from the 2025 edition, because we did not find those figures on the new edition's summary page.

What this evidence shows and does not show

These data point to two things that matter for handover. First, secrets are not only in code. The Slack, Jira and Docker image figures say they also sit in chat, tickets and artifacts built from the system. Second, private repositories are not as safe as people tend to assume, because the share with secrets is higher than for public repositories in GitGuardian's data. A plausible reason is that people feel a closed space is safe enough and put things there that they should not, but the report does not test that. It is only our observation.

What the data do not show is also clear. We do not know what share of Thai organizations have leaked secrets. The 70 percent figure does not mean every leaked key gets used in an attack. It only says that leaked keys are often not revoked and so still work, which is a discipline problem with rotation, not a measure of damage. And we did not check the report's own method, so please read all the figures as a picture of what one vendor sees.

Where secrets hide that teams do not think of

When we walk through a system one component at a time, secrets tend to be in places nobody thinks of when first asked. A sample configuration file that was copied into use and never had its values changed. A .env file that was committed once and deleted later. Pipeline log output that printed environment variables while someone was debugging. A project group chat where people sent each other a password because it was convenient. A ticket with a screenshot of a settings page attached. A database backup that contains connection settings. A Docker image built with values baked in at build time.

A spot buyers often overlook is the developer's own machine. If the real system's credentials sit on the personal computer of someone no longer on the project, rotation is the only way to be sure that copy no longer works. We wrote about handing over access when teams change in our article on who really holds the keys to your cloud account, and the same principle applies to every kind of secret.

A secrets inventory: the table you should receive at handover

The first thing we suggest asking for is a one-page table that answers what secrets the system has, without any real secret values in it. For each entry, it should record the following.

  • Name and purpose, for example the main system's database password or the email provider's API key, so a reader knows what it opens.

  • Where it really lives, such as the secrets manager that holds the real value, and where it is read at runtime.

  • The owner, a person or role responsible when it has to change, not the name of an individual who may move on.

  • Who can read it, following OWASP's point that access should be granular, secret by secret, and that nobody should reach everything.

  • When it was last rotated, and when it is next due.

  • How to rotate it, steps someone else can follow, including other services to update and whether the system will stop briefly.

  • Impact if it leaks, meaning which data or services it opens, so you can prioritize on the day you have to respond.

Keep this table with the system documentation and review it whenever an external service is added or the team changes. It follows the same idea as writing handover conditions that keep a system maintainable, which we covered in our article on conditions in a TOR.

What to ask the developer for at handover

Beyond the table, here is a list of items a buyer can put into the contract or the acceptance checklist.

  1. No secrets in source code or history. The developer confirms in writing that the full repository history has been scanned with a detection tool, and attaches the scan result with its date.

  2. Automated scanning in the pipeline. On every commit or merge, secrets are checked for before code reaches the main branch, in line with OWASP's point about running tools such as detect-secrets before a commit. If you use GitHub, turn on push protection, which blocks a push containing a secret before it reaches the repository, and state in the contract who may bypass the block. GitHub's documentation says that by default anyone with write access can bypass it by choosing a reason such as "I'll fix it later". Each bypass creates an alert and an audit log entry, so also name who reviews those alerts.

  3. An agreed secrets store. A secrets manager or the CI/CD tool's secret store, in an account owned by your organization, not in a developer's personal account.

  4. A rotation procedure that has been tried. The developer shows that at least one important secret was rotated successfully in a test environment, and records which services had to be updated.

  5. Controls that keep secrets out of logs. Pipeline output and system logs must not print secret values, in line with OWASP's warning about pipeline output. For how long logs are kept and keeping personal data out of them, see our article on log retention.

  6. A leak response plan that has been rehearsed. A short document saying who decides, who revokes, who notifies the people concerned, and what is recorded.

  7. Handing over access at the end of the work. When a developer leaves the project, every secret they could reach is rotated, and their access to the secrets store and repository is removed.

The last item relates to the risk of a provider disappearing, which we covered in our article on assessing the risk that a vendor goes away. If every secret sits in a store you own, a change of team becomes an ordinary rotation job, not a hunt for who knows what.

The day a key really leaks: what to do, in order

The order below is assembled from the OWASP and GitHub guidance we opened. It is not a procedure specific to any one system, so your team should adapt it to your system and rehearse it before the day.

  1. Revoke the leaked secret immediately. Make the one that got out stop working before anything else, because while it still works, erasing traces helps nothing. Restarting the application does not count as revocation, as OWASP states plainly. And if what leaked was a whole file, such as a .env file, treat every value in that file as leaked, not only the one somebody noticed.

  2. Issue a new one and update the services that use it. If an automated rotation procedure already exists, this step is faster and less error-prone than fixing things one place at a time.

  3. Look at the leaked secret's usage history. OWASP says incident responders should be able to see who used it and when, to check whether it was used by anything other than the system. If so, treat it as a data breach to be assessed further. And if your logs do not go back as far as the moment the value leaked, the honest conclusion is "we don't know", not "it wasn't used".

  4. Remove the leaked secret from code, logs and other systems, including chat, tickets and backups. Removing it from logs must preserve the integrity of the logs, as OWASP states.

  5. Consider rewriting Git history last. GitHub says it is hard and often unnecessary once the credential is revoked, so decide on actual risk, not because it feels like something that has to be done.

  6. Record the incident and find the cause, meaning how the secret got there and at which point you will stop it happening again.

If the leaked secret opens a path to personal data, this becomes a legal matter as well. Section 37(4) of Thailand's Personal Data Protection Act B.E. 2562 (2019) requires the data controller to notify the Office of the Personal Data Protection Committee (PDPC) of a breach without delay and, where feasible, within 72 hours of becoming aware of it, unless the breach is unlikely to result in a risk to people's rights and freedoms. If the risk is high, the data subjects must also be told, together with the remedial measures. The breach notification form can be downloaded from the PDPC's website. A leaked secret does not always mean personal data was breached, and we do not give legal advice in this article. But the assessment of whether it qualifies should start on the day you find out, not the day the log review is finished, so your legal counsel belongs in the response plan from the start.

What not to do

In our view, there are three common mistakes to avoid. The first is deleting the secret from the latest file and calling it done. Git history still keeps it, and GitHub's documentation says scanning covers the history of every branch, so as long as the key still works, anyone who finds it in the history can use it. The second is sending a secret through chat or email in a hurry, even meaning to delete it later. GitGuardian's Slack and Jira figures suggest this really happens. If you have to pass one on, use a secrets manager and share access, not the value. The third is changing values in production without going through the normal change process, because rotation affects every service that uses that secret and should be tested first, as we wrote in our article on release management in production. The exception is an emergency revocation, which should have a shortcut procedure that has already been rehearsed.

Limits we should state plainly

If your system is a content website that connects to no external service and has no database holding important data, the number of secrets may be very small. A one-page table is enough, and installing a separate secrets manager may be more than you need.

Also, we can only confirm what the documents cited in this article state. For GitGuardian, we read the 2025 report and the summary page of the 2026 edition, but not the full 2026 report, and we did not check the method of either. If you need to build this for real, have a security specialist read the full documents and assess your environment.

Finally, having a table and scanning does not mean no secret will ever leak. It means you see it sooner and respond sooner. Scanning can also miss formats the detector does not know, so it has to go together with discipline in rotation.

Objections we often hear

A common objection is that our repository is private and nobody can see it. That is true in the sense that outsiders cannot get in. But in GitGuardian's data the share of private repositories with secrets is higher than for public ones, and the people who can reach it include past developers, third-party tools and compromised accounts. Relying on privacy alone is not enough.

Another is that rotating a secret would take the system down, so we would rather not touch it. That is the best reason to rehearse first. If rotation takes the system down on a day with no incident, it will take it down harder on a day with one. A system that cannot rotate without stopping is one that ties the same secret into too many places, which is exactly what the inventory table will reveal.

Where to start

  1. Ask the developer to scan the full repository history and look at the result. If a secret that still works turns up, revoke and rotate it before anything else.

  2. Make the one-page secrets inventory, starting with the database, the email or SMS service, the payment provider and the cloud account, then fill it in system by system.

  3. Move secrets to a store in an account your organization owns, and remove access for people no longer on the project.

  4. Turn on scanning in the pipeline, so that new secrets are caught before they reach the main branch.

  5. Rehearse rotating one secret in a test environment, and record which services had to be updated and how long it took.

  6. Put these items in the contract and the acceptance checklist, so the next developer delivers them from the start.


Summary

OWASP's guidance says to centralize, limit access, rotate, and revoke immediately when a secret leaks. GitHub's documentation stresses that revocation comes before erasing history. And GitGuardian's data, from a vendor that sells detection tools, indicates that secrets end up in private repositories, chat, tickets and Docker images. If you take one thing from this article, ask the developer who runs your system for a one-page secrets inventory with no real values in it. That table tells you, on the day a key leaks, what to revoke, who does it, and how the system will be affected.

If you would like to talk through the details of a project, you can reach us at 088-983-9386 or [email protected]. Our office is in Bang Kapi, Bangkok. For organizations still drafting a scope of work, we are glad to arrange a conversation to understand the problem first, without needing complete documents. And if we find that the problem is not yet at the point of needing a new system, we will say so plainly, because starting a project at the wrong time costs more than waiting another quarter.

FAQ: Frequently Asked Questions about This Article

A collection of questions and answers to help you better understand the content of this article.

Tags:

secret leakAPI keysecrets managementkey rotationCI/CDsystem handoverOWASPGitHub secret scanningsystem securitysoftware outsourcing
Share:

Other Articles

Stay tuned for upcoming articles!