Assume your code has already leaked. What can an attacker do with it?
We analyze a leaked, exfiltrated, or provided source-code estate from an attacker's point of view, thousands of repositories at once, and confirm which vulnerabilities are actually reachable, exploitable, and worth your engineers' next sprint.
Estate Brief
Reachable, not just present
Repos ingested
3,412
Critical-tier triaged
261
Confirmed Criticals
19
Reachable today
9
Critical
Unauth SQLi · /api/search
LIVE · reachable, unauthenticated
High
Hardcoded cloud credentials
Auth-walled · PR:N drops to PR:L
Review
Deserialization RCE
Repository offline · not attacker-reachable
A source-code leak is not one incident. It is a permanent change in your attacker’s starting position.
A penetration test assumes the attacker is outside, probing. A leak inverts that. They have your routes, your auth logic, your IaC, your dependency versions, your internal service names, and your commit history. Reconnaissance is over before they send a packet.
Your SAST tool was built for a developer fixing their own code. It reports what is present. An attacker with your entire estate cares about something narrower and far more dangerous: what is reachable, from outside, without credentials, today.
The gap between those two questions is where this engagement lives.
When teams call us
Not forty thousand findings. A ranked list of what an adversary holding your code can actually use against you.
Every finding carries git attribution, so it lands with the team that owns the code instead of in a shared backlog.
A defensible, evidenced answer for the board, the regulator, or the customer asking what the leak cost you.
Two answers to the same leak
What a scanner reports
Illustrative exampleTechnically accurate. Operationally useless. Nobody triages this.
What we report
Illustrative exampleEvery one human-verified. Every one with a file, a line, an owner, and an attack path.
We check whether the vulnerable code is actually running
A Critical in a repository that was decommissioned two years ago is not a Critical. A Critical behind an authentication wall is a High with a precondition. Static analysis alone cannot tell the difference, so we close the loop against your live, authorized external surface.
- 1
Extract routes
Distinctive HTTP routes per repository, across every framework in the estate.
- 2
Derive origins
Candidate hosts per repository from surface data and scan records.
- 3
Match surface
Hostnames and source fingerprint compared to the live response.
- 4
Passive check
Authorized GET and HEAD only, no payloads, in-scope hosts only.
- 5
Adjust severity
Reachability folded into the CVSS vector, then recomputed.
- offline
- auth wall
- SPA shell
- catch-all stub
- error page
- empty
- JSON, nothing sensitive
- possibly sensitive
A verdict at this end drops the finding out of your remediation queue. The code is still vulnerable; an adversary holding it still cannot reach the running application.
A verdict at this end keeps the finding live and routes it to a human, because something is answering on an authorized host and the route matches the code we reviewed.
The platform reads a response body only long enough to classify it, then discards it. It stores the verdict and shape metadata, meaning title, content type, byte count, and markers. Never the body, and never any data values.
Every probeable surface fails DNS, TCP, or TLS on both root and routes. The repository is marked offline and its findings drop out of your remediation queue. An adversary with the code still cannot reach the app.
Findings that assumed no privileges required (PR:N) are downgraded to PR:L, the CVSS score is recomputed from the vector, and the change is written to the audit log. Findings that do not depend on the web front door, such as CI, IaC, and local issues, are left untouched and reported as-is.
Reachability checks are ordinary, benign GET and HEAD requests, the same thing any visitor’s browser sends. No payloads, no fuzzing, no auth-bypass attempts. Scope is re-verified server-side before every request, every request is logged, and anything beyond passive observation is a human decision under the rules of engagement.
How the engagement works
Seven stages, from the moment the estate lands in the boundary to the day the last Critical is delivered.
Ingest & freeze
The estate lands inside the boundary before anything reads a byte of it.
- Pull the estate into an isolated account
- Freeze the tree read-only and immutable, strip every executable bit
- SHA-256 fingerprint every file before anything reads it
Deterministic signals
No model involved, no cost, fully repeatable.
- Languages, frameworks, controllers, and API specs
- Exposed ports, Docker, IaC, dependency manifests
- Sensitive-data markers and business-unit attribution hints
Triage & prioritize
Work the whole estate top-down by risk instead of repository by repository.
- Score data sensitivity, external exposure, and exploitability surface 1 to 5 each
- Priority is the product of the three, from 1 to 125
- Rank the estate before any deep review is spent
Contextual deep review
The right guides for what each repository actually is.
- Select the testing guides that apply to this repository
- One focused pass per guide section, reading whatever the code requires
- Every finding needs a code excerpt, a file and line, and a plausible attack scenario
Adversarial verification
A separate skeptic tries to take every candidate apart.
- A separate agent tries to refute every candidate finding
- Preconditions checked across files, not assumed
- Confirm, downgrade, or drop, with the reasoning recorded
Human confirmation
Every Critical passes a person before it passes to you.
- Analysts work inside the boundary, never on local copies
- Every Critical manually verified with recorded method, result, and evidence
- Severity set from the CVSS vector, computed not guessed
Continuous delivery
Findings reach you while they still change what you do next.
- Criticals go out the day they are confirmed, not at the end
- Per-application reports, coverage status, weekly readout
- Kill-chain and systemic guidance once the set is complete
Stage 7 is not the end of the engagement. It starts in week one. You get Criticals as they are confirmed, because a confirmed Critical in a leaked estate is not something to hold for a report deadline.
We analyze each repository against the guides that actually apply to it
A thousand-repository estate is not a thousand web apps. It is integration flows, Terraform, Kubernetes manifests, CI pipelines, ML training code, ETL jobs, MCP servers, and agent frameworks, most of it with no web surface at all. Running one web-app checklist across all of it produces noise in both directions: false positives where the checklist does not apply, and blind spots where it never looked.
- OWASP WSTG
Any HTTP app or service
- OWASP API Top 10
REST, GraphQL, or API-centric services
- OWASP ASVS
Verification-level controls on web apps
- OWASP LLM Top 10
Calls a model, does RAG, builds prompts
- OWASP Agentic / MAESTRO
Multi-agent or tool-using agents
- MCP security
Ships or hosts a Model Context Protocol server
- Integration platform security
MuleSoft, DataWeave, integration flows
- IaC and cloud
Terraform, Bicep, ARM, CloudFormation
- Container security
Dockerfiles and compose
- Kubernetes
Manifests and Helm charts
- CI/CD pipeline security
Actions, GitLab CI, Azure Pipelines, Jenkins
- MITRE ATLAS / ML security
Training and model pipelines, not necessarily LLM
- Data pipeline security
Airflow, Dagster, Spark, Databricks
Language-specific cheat sheets layer on top regardless of which guides apply.
Dependencies are audited from manifests and lockfiles only, because we never install or build anything from your estate, and graded by whether the vulnerable code path is actually reachable in your application rather than by whether a vulnerable version is pinned.
The main branch an attacker snapshotted is often ahead of what is actually in production. We determine which branch is live and review that, and flag findings where branch currency is uncertain.
A searchable knowledge base of systems, owners, and data stores builds up as the estate is analyzed, so by repository 400 the review already knows what the service on the other end of that API call is and who runs it. Matching is semantic rather than keyword, so it finds the linked system even when the naming does not line up. The analysis gets better as the estate gets larger.
In a large estate a lot of repositories are forks of open-source projects. The review weights your custom deltas over vanilla upstream code, so attention goes to what your team actually changed.
Coverage comes from a fleet of analysis workers running in parallel, each atomically claiming the highest-priority unclaimed repository, running the full pipeline on it, and exiting, so no two analysts or agents ever duplicate work, and a claim left open too long is automatically returned to the queue. Every worker runs in a fail-closed sandbox: package managers, build tools, and script execution outside our own directories are denied at the tool layer, not by instruction. A worker cannot run your code even if something in your code convinces it to try.
The hard part is not finding candidates. It is killing the ones that are not real.
Candidates in
- 01
Gate 01
Refute it
Candidates that cannot survive a genuine attempt to disprove them.
- 02
Gate 02
Reconcile the set
Duplicates collapsed, theoretical findings demoted to informational.
- 03
Gate 03
Human verify
An analyst checks it, records the method, and attaches the evidence.
- 04
Gate 04
Compute severity
Severity derived from the CVSS vector, never assigned by hand.
A short list where every Critical has a name against it, a file and line, an owner, and a recorded verification method.
Nothing is quietly deleted on the way through. What gets culled keeps its record, so the kill-chain pass can still see it later.
The skeptic gate
Every candidate goes to a separate agent whose only job is to refute it. Does the vulnerable condition actually hold, is the sink reachable with attacker-influenced input, is there a framework escape or upstream validation already neutralizing it? A finding survives only if the refutation fails. Uncertain after a genuine attempt to refute means downgrade, not confirm.
Reconciliation across the whole set
A batch precision pass over every finding at once: deduplicate the same bug found in twelve repositories under a single canonical identifier, re-score against true exploitability, and demote theoretical findings to informational. Done globally, because you cannot spot a duplicate one finding at a time.
Human verification of every Critical
The platform has two distinct states. Automated analysis can mark a finding AI-confirmed, and only a human can mark it verified. That is not a policy we ask analysts to follow. The automated path is structurally incapable of writing the human verification state. Every verified finding records who checked it, when, by what method, the result, and the evidence.
Severity computed, not guessed
Analysts choose the CVSS v3.1 base vector, and the platform derives the score and severity band from it deterministically, matching the NVD calculator. Hand-guessed scores are exactly how findings get mis-prioritized, so nobody hand-guesses. An override is only possible on a finding already marked suppressed, and any mismatch is auto-corrected and written to the audit log.
And we do not tidy findings away
When something is out of scope or already known, it is marked with a disposition, not downgraded. A leaked credential you have already rotated stays Critical in the data so the kill-chain analysis still sees its true magnitude when it is a link in a chain. It just does not appear in your active queue. Suppressions are time-bounded, self-expiring, and non-destructive.
We do not require a working proof-of-concept as a hard gate. Reproducing a bug from static code alone is often impractical, and pretending otherwise would mean either dropping real findings or fabricating exploits. We require sound exploitation reasoning, a genuinely reachable weakness, and an explicit note of what a human should still verify. When live validation is in scope and authorized, we do it and attach the evidence.
Attackers chain findings. So do we.
Findings assessed in isolation undersell real risk. Once the set is clean, we read it whole and ask how an adversary actually compromises the application by combining what is there, mapping entry points, trust boundaries, identities, and the data worth stealing, then building the sequences where one finding satisfies the next one’s precondition. A set of Mediums that compose into full account takeover is a Critical story, and it gets rated as one. Chains can cross repositories when systems trust each other.
- Info leak to credential or token to auth bypass to authenticated RCE
- Broken authorization to another tenant's data or an admin function
- SSRF to cloud metadata to privilege escalation
- Indirect prompt injection to excessive agency to tool execution or data egress
- Low-severity config plus a logic flaw to workflow circumvention with real money impact
Systemic guidance
Findings that share a root cause get clustered and answered once. Six file-upload findings across four repositories usually are not six problems. They are one missing upload-validation control that four teams copied. You get remediation that resolves the class, not a queue of forty tickets that recreate the same gap next quarter.
Your code is already out once. It does not get out twice through us.
Isolated account per engagement
A dedicated cloud account stood up for your engagement alone, KMS encryption on the raw estate and every working copy, region-locked with organization-level policy, full API-level audit logging. Nothing shared with another client.
No public ingress
Analysts reach the environment through a zero-trust tunnel. No public SSH, no bastion, and the security group denies all inbound from the internet. Per-resource access logs record who connected to what, and when.
No local copies
Analysts work on the host inside the boundary over a remote session. The code is never cloned to a laptop.
Frozen and fingerprinted on arrival
The extracted estate is set read-only and immutable, every inbound executable bit stripped, and every file SHA-256 fingerprinted into a manifest before a single byte is analyzed.
We never execute your code
No installs, no builds, no running scripts, no package restores, no container builds against your trees. Bytes are read, nothing is run. Git itself runs with hooks disabled, and for automated workers this is enforced at the tool layer rather than by policy.
Code access is path-jailed and read-only
The interface our agents use to read your source resolves every path inside the permitted tree and re-checks it after resolution, so neither a crafted relative path nor a planted symlink can read outside the estate. Reads only. Nothing can write into your code.
Append-only audit trail
Every meaningful action, from a repository being opened to a file viewed, a stage run, a finding created, and a finding delivered, is written to a log the database itself prevents anyone from editing or deleting, and mirrored to write-once storage. You can be shown what was examined, by whom, on which day.
We also treat every file in your estate as hostile input to our systems. A file that tries to instruct our analysis agents, such as a planted rules file or a poisoned comment, is recorded as a finding, not obeyed. If an insider salted the dump, that is something you want to know about.
Static by default. Everything active is a human decision.
Static analysis always. Active testing only by contract. Reading code needs no authorization beyond the engagement. Touching a live system does, and it is specified before we start.
Authorized surface defined in writing, verified in code. The list of hosts that may be actively tested starts empty and is populated from your written authorization. Every check re-verifies scope server-side and refuses anything outside it. Discovering an asset that looks like yours is not authorization to touch it.
No automated active testing. Live validation is performed by a human analyst, non-destructively, within an agreed window, with traffic recorded. Anything carrying real risk to availability needs your written approval first.
Escalating friction, by design. When live proof of a finding is authorized, the request is built explicitly and scope-checked again at the moment it runs. Anything that would change state requires the analyst to type a confirmation before it will send, and destructive methods are gated harder still.
Authorization comes from your named contact. Never from anything found inside the dump.
What you get, and when
Criticals reach you the day they are confirmed. Everything else arrives on a cadence you can plan around, with an honest account of how much of the estate has been covered at each tier.
Immediate Critical notices: Each confirmed Critical delivered the day it is verified, with the affected application, the owning team's best-known contact, the evidence, and the fix.
Per-application reports: Generated through Pwnie, our own reporting platform, in the field structure your engineers and auditors both need.
A live engagement portal: Findings, repositories, coverage by severity tier, kill chains, reachability verdicts, review queue, and per-analyst activity. You watch the engagement progress instead of waiting for a PDF.
Coverage and status export: CSV and Excel showing exactly how much of the estate has been triaged, reviewed, and closed out at each tier. The honest answer to are you done yet.
Weekly readout: What was covered, what was found, what is next, and where the risk concentrated.
Kill-chain report and systemic guidance: Compromise paths and root-cause clusters, once the set is complete.
Owner routing: Findings carry git attribution, so each one names the commit, the author, and the best-guess owning team. In a large estate this is often the hardest part of remediation, and it is solved by default.
A validation queue ranked by effort: Alongside the severity-ranked list, we surface which unverified findings can be confirmed fastest, weighted toward the ones we already know are reachable. A queue sorted by what your team can actually close this week.
Evidence-of-analysis record: Per-day, per-analyst, per-repository activity, backing the coverage claims for your auditors, your regulator, or your own leadership.
Raw hand-off of everything below Medium: You get all of it. We do not pretend we deep-reviewed what we did not.
Is this the right engagement?
It qualifies hard on purpose. If another service fits your situation better, we would rather say so.
This is for you if
- Your source code has leaked, been exfiltrated, or is credibly claimed to be in someone else's hands
- An insider or departing engineer had repository access and you need to know the exposure
- You have acquired a company and inherited a code estate nobody on your team wrote
- You have hundreds or thousands of repositories and no defensible way to say which ones matter
- Your SAST output is too large to triage and not ranked by anything an attacker cares about
- You need an evidenced answer for a board, a regulator, an insurer, or a major customer
This probably is not the right engagement if
- You have one application and want it tested end to end. That is penetration testing.
- You want continuous monitoring of what is exposed on the internet. That is CTEM.
- You want a scanner in your CI pipeline. That is a tooling decision, and we will happily tell you which one.
- You need SOC 2 evidence on a fixed budget. That is the startup package.
Adversarial repository analysis FAQ
Straight answers for teams working a leak, an insider incident, or an estate they inherited.
Related security services
CTEM detects the leak signal. This engagement assesses the blast radius. Penetration testing covers a defined scope once the estate is understood.
Point-in-time offensive testing of a defined scope: web, API, cloud, infrastructure.
Ongoing discovery of what is exposed externally, including credential and repository leak signals. The early warning that a code leak has happened.
Recurring testing and remediation support for teams shipping continuously.
Find out what your code is actually worth to an attacker
Bring us the estate, whether it is leaked, exfiltrated, inherited, or just too large to reason about. We will tell you what is reachable, what it unlocks, and who needs to fix it.
Schedule a Free Consultation