filevet
Self-hosted, open-source scanner that checks the files finance teams receive for security risks before anyone opens or ingests them.
Why
Fintechs and finance teams take in files from outside every day: invoices, bank statements, KYC documents, payment files. Any of them can carry malware, exploit the parser that reads it, or hide instructions meant for an AI system further down the line. Commercial scanners are closed and expensive, and the open-source ones don't understand financial formats like ISO 20022. filevet runs several independent analyzers over a file and returns one report you can act on.
Status
Quickstart
pipx install filevet
# or
uv tool install filevet
filevet scan statement.pdf
With Docker, without network access and with the file mounted read-only:
docker run --rm --network none --read-only --tmpfs /tmp -v "$PWD:/in:ro" ghcr.io/pablodt00/filevet scan /in/statement.pdf
To add ClamAV signature scanning, use the Compose file, which runs clamd as a sidecar and shares its socket with filevet:
docker compose --profile clamav up -d clamav
docker compose run --rm filevet scan /in/statement.pdf
filevet alone needs about 200 MB of RAM. With ClamAV, plan for 1 to 2 GB more for its signature database.
Example
filevet scan invoice.pdf
Trimmed output from a file named invoice.pdf that's really a Windows executable (the format may still change):
{
"filevet_version": "0.1.1",
"artifacts": [
{
"id": "1bf01f46-66b9-4b57-a40c-031d8d71615f",
"name": "invoice.pdf",
"sha256": "9f2c…e41a",
"declared_type": "pdf",
"detected_type": "pe",
"depth": 0
}
],
"findings": [
{
"rule_id": "basic.type_mismatch",
"title": "File content does not match its extension",
"severity": "critical",
"confidence": 1.0,
"evidence": "invoice.pdf",
"references": ["https://cwe.mitre.org/data/definitions/434.html"],
"analyzer": "basic.type_mismatch/0.1.0"
}
],
"summary": { "critical": 1, "high": 1, "medium": 0, "low": 0, "info": 0 },
"verdict": "block"
}
--format table prints the same report as a table for people. The full report format is in docs/schema/report.schema.json, and filevet schema prints it too.
Other commands: filevet analyzers lists the registered analyzers, and filevet version prints the version.
Integrity findings are signals for review, not proof of fraud. docs/integrity.md explains each technique and its limits. IBANs in the evidence are masked (ES91 **** **** **** **** 1332) unless you pass --no-mask. docs/privacy.md lists what a report can contain.
Exit codes
CI jobs can act on the exit code of filevet scan without parsing the report.
| Code | Meaning |
|---|---|
0 |
No findings of medium or higher (verdict pass) |
1 |
At least one medium finding (verdict review) |
2 |
At least one high or critical finding (verdict block) |
3 |
Usage error, including a missing input file or one over the size limit |
4 |
Internal error in filevet |
What it checks
Each rule has a page in docs/rules/ that explains what it means, why it matters for finance files, how to fix the file and when it can be a false positive.
| Rule ID | File types | Detects | Severity | References |
|---|---|---|---|---|
basic.type_mismatch |
All | Extension doesn't match the content | medium, critical for disguised executables | CWE-434 |
basic.executable |
All | Programs, scripts and .lnk shortcuts |
high | CWE-434 |
malware.clamav (optional) |
All | Known malware signatures, via a ClamAV sidecar | critical | ADR 5 |
malware.yara |
All | Bundled or your own YARA rules: embedded PE and .lnk headers, DDE commands, XXE, PDF auto-run |
from the rule, medium by default | YARA |
malware.pdf_active_content |
JavaScript, launch actions, auto-actions, rich media, XFA, form submission, URIs, embedded files, hex-obfuscated names, filter chains | low to critical | CWE-829 | |
malware.office_macros |
XLSX, XLSM, DOCX, DOCM, XLS, DOC | VBA, auto-run macros, Shell/CreateObject/URLDownloadToFile, XLM macro sheets, DDE, remote template injection |
medium to critical | ATT&CK T1137, T1221, CVE-2017-0199 |
malware.embedded_executable |
All containers | PE, ELF, Mach-O, scripts or .lnk files inside another file |
critical | ATT&CK T1027.009 |
parser.csv_formula_injection |
CSV, XLSX | Cells that spreadsheet apps run as formulas, including hidden prefixes, full-width characters and DDE payloads | medium, high | OWASP, CWE-1236 |
parser.xml_unsafe |
XML, ISO 20022 | DTDs, external and parameter entities, entity expansion, XInclude, deep nesting | medium to critical | CWE-611, CWE-776 |
parser.archive_bomb |
ZIP, OOXML | Extreme compression ratios, nested archives, too many entries, overlapping entries, quines | high, critical | CWE-409 |
parser.path_traversal |
ZIP, OOXML | ../ entries, absolute paths, drive letters, symbolic links |
high | CWE-22 |
parser.polyglot |
All | Files that are valid as more than one type | medium | CWE-434 |
parser.malformed |
All | Broken structure that viewers would repair, each in its own way | medium | |
format.iso20022_schema |
ISO 20022 XML | camt.052/053/054, pain.001/008 and pacs.008 messages that don't match their XSD | low | ISO 20022 |
integrity.pdf_incremental_updates |
Saved again after creation, with what each revision changed | info to medium | integrity.md | |
integrity.pdf_revision_diff |
Text, amounts, IBANs or dates that differ between revisions | low, medium | integrity.md | |
integrity.pdf_producer_mismatch |
Producer changed between revisions, XMP and Info disagree, dates run backwards, unexpected producer for the issuer | low, medium | integrity.md | |
integrity.pdf_digital_signature |
Invalid signatures, content added after signing, untrusted certificates | info to high | CWE-347 | |
integrity.pdf_text_overlay |
White boxes over text, text drawn over other text | medium | integrity.md | |
integrity.pdf_font_anomaly |
Digits in a second copy of a font, amount-only fonts, fonts added later | low, medium | integrity.md | |
integrity.iban_invalid |
PDF, text, CSV, XLSX, ISO 20022 | IBANs that fail mod-97, length or country checks | medium | SWIFT: IBAN |
integrity.bic_invalid |
PDF, text, CSV, XLSX, ISO 20022 | Malformed BICs, BIC and IBAN from different countries | low | SWIFT: BIC |
integrity.iban_inconsistent |
PDF, text | More than one beneficiary IBAN in a document | medium | |
integrity.iban_not_allowlisted |
PDF, text, CSV, XLSX, ISO 20022 | A known supplier with an IBAN that isn't on record (needs --context) |
medium | |
integrity.totals_mismatch |
PDF, text, ISO 20022 | Invoice lines that don't add up, unbalanced statements, camt.053 balances, pain.001 CtrlSum and NbOfTxs |
medium | ISO 20022 |
integrity.date_anomaly |
PDF, text, CSV, XLSX, ISO 20022 | Impossible dates, bookings long after the value date or outside the statement period, future dates | medium | ISO 20022 |
integrity.duplicate_ids |
ISO 20022 | Repeated MsgId, PmtInfId, EndToEndId and other unique references |
low, medium | ISO 20022 |
Configuration
| Variable | Effect |
|---|---|
FILEVET_CLAMD |
Address of clamd: unix:/path/clamd.sock or tcp:host:port. Without it, ClamAV isn't used |
FILEVET_YARA_RULES |
Directories of extra .yar files, separated by : |
FILEVET_XSD_DIR |
Directory of ISO 20022 XSDs, one <message>.xsd per version, such as camt.053.001.08.xsd |
filevet scan --context context.yaml adds what you already know: the IBANs on record for your suppliers, the PDF producers your banks use, and the certificates you trust for signatures. The format is in docs/integrity.md. The context file is never logged or copied into the report.
The synthetic test corpus in tests/corpus/cases/ has one case per threat and per legitimate look-alike. uv run pytest tests/corpus prints a detection matrix showing which rules fire on which case.
Limitations
- filevet never declares a file safe. It reports what it checked and what it found, and no scanner catches everything.
- PDFs are scanned as raw objects. Content hidden behind encryption, or behind filters other than Flate, isn't decoded.
- 7z, RAR and gzip archives are detected but not extracted, so their contents aren't scanned.
- VBA is found by its source text. P-code-only projects (VBA stomping) can get past it.
- No ISO 20022 XSDs ship with filevet yet, so schema validation only runs once you supply them.
- The rules are tested against a synthetic corpus, not real-world malware.
- It doesn't replace antivirus or EDR, email security, or human review of high-value payments.
- Integrity checks only see traces of editing. A document forged from scratch, or flattened into a new PDF, looks clean to them. Scanned images aren't read.
- PDF signatures are checked offline, against the trust roots you supply, without revocation data.
- Content aimed at AI pipelines isn't detected yet (planned for v0.3).
- It doesn't analyze network traffic, attribute malware to families, or store scanned files.
The full scope is in docs/SCOPE.md.
Roadmap
Work is split into phases, each tracked as a milestone: foundations, MVP (v0.1), integrity checks (v0.2), platform features such as a REST API and policy engine (v0.3), and hardening for v1.0.
Contributing
Start with CONTRIBUTING.md. Everyone taking part is expected to follow the Code of Conduct.
Security
Report vulnerabilities privately, as described in SECURITY.md. Please don't open public issues for them.
License
Apache License 2.0. See also NOTICE.
Metadata
Release files for filevet 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| filevet-0.3.0.tar.gz | 325.4 kB | With provenance | Details for filevet-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| filevet-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for filevet-0.3.0-py3-none-any.whl |
Total release size: 387.6 kB
Release files / filevet-0.3.0.tar.gz
| Download URL | filevet-0.3.0.tar.gz |
|---|---|
| Size | 325.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0739b30f1aeb8bbd3684628a64a93f6d5ece59052d460df02a10b110f9f65744
|
|
BLAKE2b-256 checksum How to use checksums |
1b9c0e86f532c0c377393efff830ceb3326c6ffb7c54a0c93ccede0e9da620e3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logRelease files / filevet-0.3.0-py3-none-any.whl
| Download URL | filevet-0.3.0-py3-none-any.whl |
|---|---|
| Size | 62.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4942f65b085437aabe2ac344464de185e4fd1ec1e9284fb2c9935dff91b64259
|
|
BLAKE2b-256 checksum How to use checksums |
9b65cb61dd86a194f71ca15c797c93dbd346dc87461981099739f249d5cbd5ba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logSecurity for filevet 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for filevet-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.