Python 3 checker (and configurable exploit hook) for **[CVE-2026-90817]( (Securifera / Ryan Wincey).
| **Product** | [REDCap]( (Vanderbilt) |
| **Affected** | **≥ 13.3.0** (until branch patch) |
| **Fixed** | **16.0.49** LTS, **17.3.10** LTS, **17.4.4** Standard+ |
| **Auth** | None — **valid public survey hash** (`s=`) required for full chain |
| **CWE** | [CWE-73]( [CWE-94]( |
From a **public survey** context, attackers can abuse **`__passthru`** (survey passthrough) routing to reach unintended controllers (e.g. **Data Import**), then trigger unsafe **file-path / stream** handling → **RCE**.
Securifera has **not** published the full HTTP chain yet (no public PoC on GitHub / Exploit-DB at repo publish time).
| **`check`** | REDCap fingerprint, version heuristics, valid `s=` survey (if hash given), `__passthru` → DataImport **probes** |
| **`exploit`** | Runs only with a **verified** `exploit_chain.json` (not the placeholder example) |
`exploit_chain.example.json` is **placeholder only** (guessed routes/params). It will **not** RCE.
Research dry run: `--allow-placeholder-chain` (sends requests; expect failure).
# Single target (survey hash required for survey + passthru tests)
python poc.py -u --hash Ab12Xy34Zq --mode check
python poc.py -u " --mode check
# Mass check (one URL per line, optional |hash)
python poc.py --list targets.example.txt --mode check -j 20 -q
# Live stream: every host + test summary (recommended for long lists)
python poc.py --list targets.example.txt --mode check -j 20 -q --flow
# Exploit (after advisory → real exploit_chain.json)
cp exploit_chain.example.json exploit_chain.json # edit with real values
python poc.py -u --hash XXX --mode exploit -c id \
# Place export as fofa_csv_7561.csv (or any fofa*.csv), then:
# Writes list.txt (gitignored) and normalizes the CSV with a url column
python poc.py --list list.txt --mode check -j 20 -q --flow
Without a hash, check can still fingerprint REDCap and flag version windows, but cannot validate survey or run passthru probes.
| `-u`, `--url` | Single base URL (or `URL\|hash`) |
| `--hash` | Public survey hash (`s=` value) |
| `--list` | Target file (one URL or `URL\|hash` per line) |
| `--chain` | JSON chain for exploit mode (default `exploit_chain.json`) |
| `--allow-placeholder-chain` | Allow example JSON in exploit mode (no real RCE) |
| `-c`, `--command` | Shell command (exploit mode; needs working chain) |
| `--threads`, `-j` | Mass concurrency (default 15) |
| `--timeout` | HTTP timeout seconds (default 25) |
| `--output` | JSONL results (default `cve_2026_90817_results.jsonl`) |
| `--vuln-list` | Check → `hits.txt`; exploit → `exploited.txt` |
| `--quiet`, `-q` | Suppress periodic progress ticks |
| `--flow`, `-f` | One line per completed target (site + test summary) |
| `cve_2026_90817_results.jsonl` | Per-target JSON |
| `hits.txt` | Candidates (`exploitable_candidate`) |
| `passthru_dataimport_reachable` | Valid survey + passthru route looks like Data Import |
| `passthru_probe_reachable` | Passthru returned non-blocked HTTP |
| `likely_vulnerable_version` | Version in affected window (survey OK, probes inconclusive) |
| `redcap_version_hot_no_hash` | Affected version heuristics, no survey hash supplied |
| `redcap_no_survey_hash` | REDCap OK, no hash, version unknown |
| `patched` / `patched_no_survey` | At or above fixed version for branch |
| `no_valid_survey` | Hash invalid or survey not public |
| `no_redcap` | Host does not look like REDCap |
| `survey_ok_version_unknown` | Survey OK, version string not found |
- **Exploit** requires exact `__passthru` route and parameter names from Securifera/vendor; defaults are placeholders.
- Many instances hide version strings; `vulnerable_version` may be `null`.
- FOFA `title="REDCap"` rows often lack survey hashes — CVE preconditions need `s=` from public links.
├── poc.png # example --flow terminal output
- [NVD — CVE-2026-90817](
- [CVE Record](
- [Securifera advisories](
For **authorized security testing** only. You are responsible for compliance with applicable laws and program rules.
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
