violetre.io
Decompile binaries. Read the code. Check it for known weakness types.
Send an executable or a mobile package you own or are authorised to assess. Violet RE recovers readable source, then checks that source for known vulnerable patterns. Targets are never executed on the public tier. The analysis is static, start to finish.
The service is not open. Uploads are not being accepted, and accounts cannot be created.
An archive holding the worked example further down this page, dumped byte for byte. The first four bytes, 50 4b 03 04, are the local file header signature every ZIP starts with: read back as a little-endian integer that is 0x04034B50, the constant the example function compares against. Illustration of the material, not a product screen.
- Readable source Decompiled and deobfuscated, with every proposed rename checked against a language-specific equivalence gate before it is accepted.
- Vulnerability checks Known weakness types, such as injection and path traversal, each finding with its conditions, confidence and limits. Guided by a database of CVE, NVD and CISA KEV records.
.renames
How a rename gets accepted.
Most deobfuscation tools guess identifier names and hope. Violet RE puts every proposal through a gate that is specific to the language, and records what happened.
The worked example below is one decompiled Python function, first as the decompiler emitted it, then after renaming. Seven renames were proposed. Six compiled to identical bytecode and were kept. One did not, so the original name stands and the report records which gate rejected it.
- gate applied
- Python bytecode equivalence
- proposals accepted
- 6 of 7
- rejected by the gate
- 1, name unchanged
- Obfuscated identifier, as emitted
- Rename accepted by the gate
- Rename rejected, original kept
In the example, six identifiers are renamed and the seventh, _0x3d, is left as the decompiler emitted it. Both files ship: the raw decompiler output and the Violet reconstruction are separate artefacts in the same package, alongside the transformation record and the rejection log. Diff them yourself.
- Python
- Bytecode equivalence. The renamed version must compile to identical bytecode.
- C, C++, Java
- Structural equivalence via Tree-sitter. The syntax tree after renaming must match.
- every language
- Per-proposal accept and reject tracking, surfaced in the report, including which gate rejected each proposal.
These are gates, not proofs. A gate checks equivalence under the rules of one language. It is not a claim of semantic understanding, and the report says where understanding stops.
.locate
Finding a function in a stripped binary.
A gate only has something to judge once you know what the function is. The name sqlite3_str_vappendf is in neither of the two SQLite builds we compiled for the published teardown. The function at 0x100002778 was identified three ways, and none of them needs the source.
Three independent lines of evidence, all agreeing, none of them requiring a symbol table. Done by hand with rabin2, radare2 and python3, every command printed in the analysis writeups. The released source sits beside these binaries in our fixture directory and was used afterwards to confirm what the disassembly showed. This is an analyst reading a binary, not a product screen.
- one rare string
- The
%Qhandler emits the literal(NULL), with parentheses, when the argument is null. That exact spelling occurs once in the file, and there is exactly one cross-reference to it, in the function beginning at0x100002778. - the format table
- The specifier scan loop is plainly visible in the disassembly: a counter of 23, a base address, and a stride of 6. Read the first byte of each of those 23 entries and they spell
dsgzqQwcouxXfeEGin%pTSr, which is SQLite'sfmtinfo[]table in order, byte for byte. A function that owns the format-specifier table is the printf implementation, whatever it is called. - struct field offsets
- The first argument is an
sqlite3_str*. The offsets the function loads from are0x10,0x14,0x18,0x1cand0x1d, the last two as bytes. That is exactlynAlloc,mxAlloc,nChar,accErrorandprintfFlags, laid out after a pointer to the database handle and a pointer to the text buffer.
One function, in one binary we built ourselves, argued by an analyst with every command printed. Violet RE does not do this part for you. What it does is the part above: once a name is proposed, the gate decides whether it survives, and the report says which gate rejected the ones that did not.
.findings
Check your own builds for known vulnerable patterns.
Shipped code is often code nobody on the team has read. Violet RE checks the recovered source for weakness types with a long public record: command and SQL injection, path traversal, template injection, unsafe deserialisation, server-side request forgery, hard-coded credentials, disabled TLS checks, unbounded string copies, and Android components exported without protection. No source code needed. Rule-based checks miss things.
A finding is a candidate, not a verdict. It names the weakness type (CWE), severity and confidence, the conditions required to reach it, the impact, the remediation, and what the analysis could not verify.
- your releases
- Check a build before it ships, from the binary rather than the repository.
- mobile apps
- APK, AAB and IPA. Android packages also get component export, WebView and cleartext traffic checks.
- supplier software
- Review a vendor binary you are authorised to assess, when there is no source to read.
void load_device_name(const char *src)
{
char name[64];
strcpy(name, src);
set_label(name);
}
int apply_config(const struct config *cfg)
{
if (cfg->device_name == NULL)
return -1;
load_device_name(cfg->device_name);
return 0;
}
device.c -- 14 lines shown
title Unbounded C string copy
requires a proven
destination bound
cwe CWE-120
severity HIGH (CVSS 8.1)
confidence PROBABLE
component libexample.so,
load_device_name
cve_ids none claimed
conditions copy is in a reachable
build; src can exceed
the destination
impact memory past name may
be overwritten
limitations text-pattern rule;
destination bound,
callers, reachability
not established;
target not executed
remediation bound the copy to
sizeof(name)
evidence sha256:0000...0000
(placeholder)
F-0007 -- a candidate, not a verdict
- rule
- strcpy call (text pattern)
- confidence
- Probable
- target executed
- No
Illustrative only, not a customer result. The library, function and hash are placeholders. The finding is marked probable because a text-pattern rule matched strcpy. Destination size, callers and reachability were not established. It says so, rather than rounding up.
.corpus
Where the vulnerability data comes from, and what it is allowed to do.
Three public sources feed it: the CVE List V5 records maintained by the CVE Program, the enrichment NVD publishes on top of them, and the CISA Known Exploited Vulnerabilities catalogue. Every record keeps the source it arrived from and the date it was read. None of it is ours, and none of it is private.
Its job in an analysis is retrieval. Records and past fixes that resemble the code in front of the analyser are pulled in to steer where it looks, and that is the whole of the mechanism. Retrieved context carries no confidence effect: it cannot raise a finding, confirm one, or add a line to a report on its own. The counts below are an inventory of what is held. They are not a coverage claim, and your binary is not compared against them.
inventory as at 20 September 2026 -- counts move daily
| field | count | what the field actually records |
|---|---|---|
| vulnerability_records | 353,019 | Public vulnerability records ingested from CVE List V5, NVD and CISA KEV, each keeping its source. Public data: anyone can hold the same set. The number is here to be exact about what is stored, not to suggest a build gets checked against 353,019 vulnerabilities. |
| kev | 1,715 | Records that appear in the CISA Known Exploited Vulnerabilities catalogue, carried through as a flag on the record. |
| repository_urls | 64,161 | Records that carry a GitHub or GitLab URL among their references. The field is derived by scanning every reference URL for a github.com or gitlab.com path. It is metadata and nothing more: it does not prove the repository exists, does not establish that it is the right repository, and does not authorise fetching it. |
| patch_urls | 146,726 | Records that carry a reference NVD tagged as a patch or as a vendor advisory. Sampling puts the commit-URL share at roughly 5 to 21 per cent; the rest is dominated by vendor advisory pages. It is a count of references carrying a tag, not a count of fixes anyone can read, and it is not presented as one. |
| public_poc_status | 64,882 | Records with a public proof-of-concept reference. The URL is held as metadata. Exploit code is never downloaded and never run. |
| patch_candidates | 24,469 | Commits nominated by a record's own references as the fix for it, queued for checking. A nomination is a claim made by a reference, not a fact. |
| state = VERIFIED | 226 | Candidates that have passed that checking. The other 24,243 have not, and are not treated as though they had. |
| patch_pairs | 2,064 | Before and after pairs of the changed code, extracted from commits nominated in advisory references. Extraction is read-only: the fix is never checked out and never built. Being a pair says nothing about whether the nomination was ever checked: 986 come from a candidate that passed checking and 1,078 do not. |
| training_safe | 590 | Pairs that cleared the gate deciding whether a pair may be used at all: relevance policy ADVISORY_PATCH_RELEVANCE_V1, state ADMITTED, confidence VERIFIED or HIGH. The remaining 1,474 are quarantined, and a quarantined pair does nothing. Clearing the gate is permission to study a pair, not evidence about anyone's build. |
| trusted_patterns | 0 | Aggregate patterns over those pairs promoted to the trusted set: none. 257 are quarantined and awaiting review. No pattern from this table is in use in any analysis today. |
- guides, never concludes
- Retrieval steers where the analyser looks. It carries no confidence effect, so a resemblance to a past vulnerability can never create a finding, raise its severity or confirm it.
- no advisory matching
- Jobs submitted through the website run a bounded static pass with advisory queries switched off in the job type itself. No CVE identifier and no advisory match reaches a customer report, because the customer manifest has no field to put one in.
- read, never fetch
- Repository URLs, patch references and proof-of-concept references are stored as metadata. Nothing in the table is cloned or downloaded while your job runs, and exploit code is never downloaded or run at all.
- four gates, not one
- Nominating a fix commit, verifying it, extracting a pair and promoting an aggregate pattern are four separate steps with four separate gates. The counts above show how many records survive each one, and the last gate has let nothing through.
- the other patterns
- A second and separate thing is also called a pattern: one promoted from a confirmed finding on a target rather than from the pairs above. A pattern from a confirmed finding is promoted only after the same weakness is confirmed independently in separate targets. Rerunning one target cannot confirm it. Free-tier patterns enter only under the data condition set out below, and paid work never does.
- no uplift claimed
- No gain in detection is claimed until one is measured on held-out cases. The model used to retrieve similar code is pretrained and pinned rather than trained here, and no uplift from any of this has been measured.
Your binary is not matched against every CVE in this inventory. Holding a record about a vulnerability is not the ability to find it in your binary, and the reverse holds too: the checks can match code that no record describes. Zero matches do not mean zero vulnerabilities.
The worked SQLite teardown in the analysis writeups takes a published CVE this service would not find, and says exactly why.
.report
What you get back.
-
Vulnerability findings, with their limits
Weakness class (CWE), severity, a confidence level, the affected component, the conditions required to reach it, an impact assessment, remediation guidance and evidence hashes. Each finding also states what the analysis could not verify.
-
Both source files ship
Two files per unit: the raw decompiler output and the Violet reconstruction. Neither is the developer's original source code. Both are readable, and transformation records and rejection logs ship alongside them.
-
Nothing is renamed quietly
The report counts accepted proposals and rejected proposals, and names the gate that rejected each one.
-
Browser, PDF, ZIP
A browser report for triage, a PDF for people who were not in the room, and a content-addressed ZIP whose contents are fixed by contract: the report, the manifest, and the paired source trees. Nothing else is permitted inside it.
.scope
What you will be able to send.
| format | leading bytes | ascii |
|---|---|---|
| PE | 4d 5a | MZ |
| ELF | 7f 45 4c 46 | .ELF |
| Mach-O | cf fa ed fe | .... |
| WebAssembly | 00 61 73 6d | .asm |
| APK | 50 4b 03 04 | PK.. |
| AAB | 50 4b 03 04 | PK.. |
| IPA | 50 4b 03 04 | PK.. |
| Archives | container dependent |
Format and architecture detection is automatic. Supported extension labels are not guarantees that a particular target can be recovered, and the report says so when coverage is partial.
- not a sandbox Targets are never executed on the public tier. No dynamic analysis, no network callbacks, no sandbox escape surface. Public work is bounded and static.
- not an exploit generator Nothing is run, so nothing is proven exploitable. Findings state the conditions required to reach a weakness, and confirmation stays with you.
- not a name generator The deobfuscation engine is over 7,000 lines of dedicated code: bytecode-equivalence gates for Python, Tree-sitter structural validation for C, C++ and Java, and per-proposal accept and reject tracking.
.release
When you can use it.
expected release
Spring 2027
Violet RE is staged and closed. When it opens, this page is replaced by the product.
These are the free-tier limits as designed today, not an open offer:
- two analyses per UTC calendar month, up to 50 MB per target.
- severity counts only on the free tier: critical, high, medium, low, info, plus the total number of findings.
- reports kept 24 hours on the free tier. Paid plans keep them longer.
- no card required for the free tier.
- data condition Free use carries a data condition with no opt-out: independently validated, de-identified, generalisable structural patterns may be used in Violet's pattern library. Raw binaries, recovered source, source fragments, credentials, filenames, identifiers, report prose and customer-specific embeddings are excluded. Paid plans are isolated by default, and nothing from them enters general learning.
Prices, paid-plan allowances and the commercial terms are published at launch. Anything quoted before then is provisional.