Skip to content
Insights · Engineering

Which secret did that alert name?

Name the secret that alert named: the number, the type, and the state. A different number can share a repository. Another repository omits it.

Scroll
EngineeringOct 30, 202612 min readBy Salman Naqvi, Founder & CEO
Which secret did that alert name?

A client says the key was leaked, or says the alert is gone. Tonight, three proofs, in a repository the agency or the client can open. Name the secret that alert named: the alert number, the secret type, and the state. If the response stored no secret because the call hid it, write that, and do not invent a token to fill the hole. Show a different alert whose number, or whose type, is not this one. Show another client's repository that does not list this alert. If any of the three needs a dashboard you cannot open, you have not named the secret. You have a scanner slide and a guess.

This is one secret scanning alert. It is not the alert a dependency raised. Which alert did that dependency raise? is a Dependabot number, a package, and an advisory. A dependency alert can be open while this secret alert is a different number, and a package name is not a secret type. It is not the invite a repository sent. Which invite did that repository send? is an invitation id and a permission. An invitation can be open while no secret alert names the repository. It is not the key a repository trusted. Which key did that repository trust? is a deploy key. A key id is not this alert's number. It is not the tax id a customer stored. Which tax id did that customer store? is a tax id and a value. It is not the file a batch wrote. Which file did that batch write? is a batch id. A leaked token is none of those.

None of what follows is a finding for this client's tree, and none of it is legal advice. The fields below are the published examples of a secret scanning alert and of the locations on one. The examples that share a repository do not share an alert number. The figures below that are a count of other people's pushes. A billion pushes is not the alert the repository opened tonight.

GitHub's list example prints alert number 2, and the number is also the user id of the person who resolved it. created_at is 2020-11-06T18:48:51Z. state is resolved. resolution is false_positive. 14 characters. resolved_at is 2020-11-07T02:47:13Z. The gap is 28,702 seconds: 7 hours, 58 minutes, and 22 seconds. The example does not print that gap. resolved_by.login is monalisa. resolved_by.id is 2, the same integer as the alert number. node_id is MDQ6VXNlcjI=. 12 characters. secret_type is adafruit_io_key. 15 characters. secret_type_display_name is Adafruit IO Key. Also 15 characters, and not the same string. secret is aio_XXXXXXXXXXXXXXXXXXXXXXXXXXXX. 32 characters. 32 is not 15. The url is 72 characters. The html url is 64 characters. 72 minus 64 is 8. The page does not print 8. repository.id on that example is 1296269. The repository node id is MDEwOlJlcG9zaXRvcnkxMjk2MjY5. 28 characters. The owner id is 1. The owner node id is MDQ6VXNlcjE=. Also 12 characters, and not MDQ6VXNlcjI=. Alert number 2 is not repository id 1296269, and it is not owner id 1. A sample that reuses the integer 2 for the alert and for the resolver is not your client's alert (GitHub, REST API endpoints for secret scanning).

The single-alert example is a different number, and it is still open. The number is 42. created_at is 2020-11-06T18:18:30Z. 42 is not 2. The created times are 1,821 seconds apart: 30 minutes and 21 seconds. The page does not print 1,821. state is open. resolution is null. resolved_at is null. resolved_by is null. secret_type is mailchimp_api_key. 17 characters. secret_type_display_name is Mailchimp API Key. Also 17 characters, and not the same string. secret is XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2. 36 characters. 36 is not 32, the length of the other sample's secret, and 36 is not 17. push_protection_bypassed is false. validity is unknown. 7 characters. publicly_leaked is false. multi_repo is false. metadata holds one pair, owner_email and owner@example.com. The address is 17 characters, the same length as mailchimp_api_key, and not that string. One metadata pair is not a secret type. An open alert with a null resolution is not alert 2 with resolution false_positive, even though both examples sit on owner/private-repo.

Updating that same number 42 does not keep the open state, and it does not keep the nulls. The update response sets state to resolved and resolution to used_in_tests. 13 characters. 13 is not 14, the length of false_positive. resolved_at is 2020-11-16T22:42:07Z. From the get example's created time, that gap is 879,817 seconds: 10 days, 4 hours, 23 minutes, and 37 seconds. The page does not print 879,817. resolved_by is monalisa again, id 2 again. secret_type is still mailchimp_api_key. The secret string is still 36 characters. A resolution you can patch is not a new alert number. 42 stayed 42. Do not paste false_positive from alert 2 onto this update because both responses are resolved.

The words the list filter accepts are not the words the update schema stores. The list query says the resolutions are false_positive, wont_fix, revoked, pattern_edited, pattern_deleted, or used_in_tests. Six names. The schema enum on resolution is false_positive, wont_fix, revoked, used_in_tests, or null. Four names, plus null. pattern_edited and pattern_deleted are in the filter sentence and not in that enum. pattern_edited is 14 characters, the same length as false_positive, and not the same string. pattern_deleted is 15 characters, the same length as adafruit_io_key, and not the same string. wont_fix is 8. revoked is 7. 8 is not 7. State on the same schema is open or resolved. Two names. validity on the list query is active, inactive, or unknown. Three names. unknown as a validity is not null as a resolution, and it is not state open. per_page defaults to 30 and the maximum is 100. 30 is not 100. 2 and 42 are alert numbers in the examples. Neither is a page size. hide_secret defaults to false. The get example still prints a 36-character secret. A default of false is not a reason to paste that string into a client's ticket.

The locations example is a third object, and its column span is not either secret. It prints 13 location types: commit, wiki_commit, issue_title, issue_body, issue_comment, discussion_title, discussion_body, discussion_comment, pull_request_title, pull_request_body, pull_request_comment, pull_request_review, and pull_request_review_comment. The schema enum lists the same 13. Two code locations and three issue locations and three discussion locations and five pull-request locations. 2 plus 3 plus 3 plus 5 is 13. The commit location sets end_column to 64 and start_column to 1. 64 minus 1, plus 1 if the span is inclusive, is 64. The alert 2 secret is 32 characters. The alert 42 secret is 36 characters. 64 is not 32, and 64 is not 36. 64 minus 32 is 32. 64 minus 36 is 28. The page does not print 28, and it does not say the location example is alert 2 or alert 42. Both code locations reuse blob sha af5626b4a114abcb82d63db7c8082c3c4756e51b. 40 characters. 40 is not 64. The commit sha is a different 40-character string. The wiki commit sha is a third. The issue locations point at issue 1347. 1347 is not 2, and 1347 is not 42. A path of /example/secrets.txt is 20 characters. 20 is not 32. A location type is not a secret type.

The counts people quote when they want a leak figure did not open this alert. Dorothy Pearce and Eric Tooley, on the GitHub Blog of 14 April 2026, say that in 2025 customers using Secret Protection scanned nearly 2 billion pushes and blocked 19 million secret exposures. If the scan were exactly 2 billion, 2 billion divided by 19 million would begin 105.263. The page says nearly, and it does not print 105.263. The same post, in a different section about Code Security, says 460,258 security alerts were fixed using Copilot Autofix, and that 50 percent of vulnerability alerts were resolved in pull requests. 19 million is not 460,258. The page does not say the 50 percent is half of 460,258. Half of 460,258 is 230,129, which the page does not print. It also says mean time to remediation was nearly twice as fast with Copilot Autofix, 0.66 hours, compared with manual fixes, 1.29 hours. 1.29 divided by 0.66 begins 1.9545, which is not 2. 0.66 times 2 is 1.32. 1.32 minus 1.29 is 0.03 hours, which is 1.8 minutes. The page does not print 1.9545 or 1.8. 0.66 hours is 39.6 minutes. 1.29 hours is 77.4 minutes. The page does not print either minute count. A code-security hour is not alert number 2, and 19 million blocked exposures is not secret type adafruit_io_key (GitHub Blog, How exposed is your code?).

Do the three proofs on one real alert, in the repository that actually holds it. First, the binding. Copy the alert number, the secret type, the state, and the resolution. If resolution is null, write null. If the call hid the secret, write that the secret was not returned, and do not reconstruct it from a sample that printed X characters. If state is open, do not write resolved because an update example on the same page resolved a different moment of number 42. Second, the other alert. A different number, even in the same repository, is not this one. Alert 2 and alert 42 are that shape: one resolved false_positive on an Adafruit type, one open on a Mailchimp type, created 30 minutes and 21 seconds apart. A location list is not that second alert. A push total is not that second alert. Third, the other repository. A list that belongs to someone else's repository does not contain this number. If the only list is one shared organization, write that. A client you cannot name is the finding.

Three moves feel like the proof and are a second problem. Resolving the alert because the type was embarrassing, and then describing the missing row as a cleanup. The update sample changes state and keeps number 42. It does not erase the number you failed to copy. Quoting 19 million or 2 billion because they look precise, while the alert you were asked about is one object, and the post that printed them had already separated Secret Protection from Code Security. Asking a model which secret the alert named. The model will pick a plausible token. It will not open the alert. A dependency alert you have not opened is which alert did that dependency raise?. Opening that advisory does not name this secret type, and a GHSA id is not resolution false_positive.

The path is ordinary when an operator can open one client's alerts without opening the next client's alerts as the way to prove it. Gigbase is one agency workspace of projects, teams, and clients. The shape that matters here is one client's repository you can point at, in an account the agency or the client can open, distinct from the next client. That case is not a secret-scanning ledger. Nothing in that sentence is a headcount, a duration, or a result figure. If the only control on the screen lists every client's alerts together, you do not have this proof. You have a directory.

There is a version of this afternoon where the agency should not take the work. The work is not sold under the agency's name. The client asked to meet the builders. The room only has a slide. The buyer only wants a template. Or the buyer wants a legal opinion about what an alert promises. A white label software development partner is the page for capacity sold under the agency's name. It does not rank anyone, including us. 19 million is not this repository, and number 2 on a sample is not this repository, and false_positive is not used_in_tests.

When the repository is real and the alert is not on a screen you can open, the missing object is specific. The alert number, the secret type, and the state, a different alert that is not that one, and another client's repository that does not list it. A white-label engagement that expects this will put the repository in the client's organization, or in yours, before the first push, because an alert that lives only in a vendor dashboard is not a number you can hand the client. One that can only paste a redacted string into chat is telling you who holds the alert. Where the next slice is one capability and the acceptance sentence names the alert number, an AI integration sprint is the shape that can require the three proofs as the definition of done. Where you are not sure which repository the current engagement uses, a two-week AI readiness assessment maps the systems. The findings are yours. They are not a promise that 2 billion pushes were scanned on this repository, and they are not alert number 2.

Before you tell the client which secret the alert named, write the three lines. The alert number, the secret type, and the state, or the resolution the response actually stored. A different alert that is not that one. Another repository that does not hold it. Do not treat end_column 64 as the length of a secret the alert printed as 32 or 36, and do not ask a model which token it was. A note can tell you that 1.29 divided by 0.66 begins 1.9545, which is not twice. The binding is the alert you can defend.

Questions

Three records, in a repository the agency or the client can open. The alert number, the secret type, and the state, or a written line that the secret was not returned. A different alert whose number or type is not this one. Another client's repository that does not list this alert. A location column is not a secret, and a push total is not an alert number.

No. A count of other people's pushes is not the number on this alert. A secret you can defend is the alert number, the secret type, and the state. 19 million blocked exposures is not alert number 2, and a sample secret of 32 characters is not your token.

When the work is not sold under the agency's name, when the client asked to meet the builders, when the room only has a slide, when the buyer only wants a template, or when the buyer wants a legal opinion.

Find this useful? Tell Google to show you more of it.

Let's put AI to work in your business.

A 30-minute call. You bring the workflow or the roadmap — we'll tell you what's feasible, what it costs, and what we'd build first.

Book a call→