daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

osint-foundations.md (41011B)


      1 ---
      2 title: "OSINT Foundations & Tradecraft"
      3 description: "How to run an open-source investigation without burning yourself or your case: research accounts, collection hygiene, provenance, and knowing when to stop."
      4 category: osint
      5 subcategory: "Foundations"
      6 tags: [osint, methodology, opsec, verification]
      7 tools: [hunchly, obsidian, logseq, multipass, lima, docker, curl, wget, dig, shasum]
      8 difficulty: beginner
      9 updated: 2026-10-04
     10 references:
     11   - name: "Bellingcat's Online Investigation Toolkit"
     12     url: "https://bellingcat.gitbook.io/toolkit"
     13     author: "Bellingcat"
     14     license: none
     15     relation: derived
     16     note: "Tool catalogue: names, descriptions, cost flags and links for this area."
     17   - name: "OSINT Newsletter Tools Library"
     18     url: "https://tools.osintnewsletter.com"
     19     author: "The OSINT Newsletter"
     20     license: none
     21     relation: derived
     22     note: "Second tool catalogue, cross-checked against the above."
     23   - name: "Bellingcat — Stay Safe"
     24     url: "https://bellingcat.gitbook.io/toolkit/resources/stay-safe"
     25     author: "Bellingcat"
     26     license: none
     27     relation: inspired
     28     note: "Operational-safety guidance for investigators."
     29 ---
     30 
     31 ## What this covers
     32 
     33 The habits that decide whether an investigation holds up: how you look at a target without telling
     34 them, how you record what you found so it survives the page being deleted, and how you avoid
     35 deciding the answer before you have it. Most of this sheet is discipline rather than tooling,
     36 because most of it has no command — and where a tool genuinely exists, the commands below are the
     37 ones that keep you from leaking.
     38 
     39 ## The rule that matters most
     40 
     41 **Every request you make is a signal to the other side.** Viewing a LinkedIn profile notifies its
     42 owner. Loading a Telegram channel with your real account puts your username in the member list.
     43 Hitting a small target's website leaves your IP in their logs. A reverse image search on a photo
     44 that only three people have seen tells those three people someone is looking.
     45 
     46 Decide before you start: is this target likely to notice, and does it matter if they do?
     47 
     48 ## Method
     49 
     50 1. **Write the question down before you collect anything.** One sentence, answerable, with a
     51    stated standard of proof. "Is this company linked to that one" is not a question; "does any
     52    public filing show a shared officer, address or beneficial owner" is.
     53 2. **Decide your exposure budget first.** Which identity touches the target, from what address,
     54    and what happens if that address is logged. Changing this mid-investigation is how an account
     55    gets burned.
     56 3. **Capture as you go, never afterwards.** Anything interesting is archived the moment you see it.
     57    Pages disappear, get edited or go private within hours of someone noticing attention. See
     58    [Archiving & Evidence Preservation](/sheets/osint/archiving-and-evidence).
     59 4. **Record the route, not just the result.** URL, UTC timestamp, the query that surfaced it, and
     60    what you clicked to get there. A screenshot with no source and no date is worth nothing, and the
     61    path to a finding is the part you forget first.
     62 5. **Keep raw separate from conclusions, in different files.** One place for what you collected,
     63    another for what you think it means. Conflating them is how an assumption becomes a fact three
     64    notes later and a published claim three weeks later.
     65 6. **Log what you looked for and did not find.** Negative results stop you re-running the same
     66    dead end next week, and they are what an honest report needs in order to describe its own limits.
     67 7. **Name the thing that would prove you wrong, then go look for it.** If you cannot state what
     68    evidence would change your conclusion, you are not investigating, you are assembling.
     69 8. **Stop at the question you wrote down.** The collection will always offer you more. More about a
     70    bystander, more about a family member, more that is interesting and none of your business.
     71 
     72 ## Key tools
     73 
     74 ### Hunchly
     75 
     76 The one tool that removes the discipline problem, because it captures continuously rather than when
     77 you remember to. It is a browser extension that records every page you visit while a case is open:
     78 the full HTML and resources, the URL, a UTC timestamp and a hash of the capture, into a local case
     79 file that is full-text searchable. That hash-at-capture-time is the evidentiary point — it is the
     80 same argument as the manifest pattern in
     81 [Archiving & Evidence Preservation](/sheets/osint/archiving-and-evidence), applied automatically to
     82 everything you looked at including the pages that turned out not to matter.
     83 
     84 Commercial, subscription, now owned by Maltego Technologies, with a 30-day trial that needs no card.
     85 There is no CLI and no API: this is a GUI tool and the workflow is the product.
     86 
     87 ```text
     88 1. Install the extension, open the desktop app, and create a case BEFORE you
     89    start looking. Captures outside an open case are not recorded.
     90 2. Set the case name to your case ID, not to the target's name. The case file
     91    leaks the target's name to anyone who sees your screen or your backups.
     92 3. Toggle capture ON. The extension icon state is the only indication; check it
     93    after every browser restart, because a silent-off session is unrecoverable.
     94 4. Add "selectors" — the names, handles, domains and phone numbers you are
     95    tracking. Hunchly then highlights them on every page you visit and logs
     96    which page each one appeared on. This is the feature people underuse: it
     97    catches a name in a footer you would never have read.
     98 5. Tag pages as you go. An untagged case file of 4,000 pages is a search index,
     99    not a narrative.
    100 6. Export: the case export carries the captured pages, the hashes, the timestamps
    101    and the selector hit log. Export at milestones, not just at the end — the
    102    case file is a single local database and a single local database can corrupt.
    103 7. Storage choice matters. Local keeps everything on your machine; the hosted
    104    option puts your captures and therefore your whole research pattern on
    105    someone else's infrastructure. Pick deliberately and write down which.
    106 ```
    107 
    108 What it does not do: a Hunchly capture is a record that *you* saw that content at that time, with no
    109 third-party attestation. It is excellent provenance for your own process and weak evidence against
    110 a determined challenge, which is why anything load-bearing still gets a public-archive capture and
    111 an independent timestamp. It also captures everything, including pages you visited by accident and
    112 pages containing other people's personal data — treat the case file as sensitive material in its own
    113 right.
    114 
    115 ### Obsidian or Logseq: the case vault
    116 
    117 Local, plain-text, file-per-entity notes with links between them. The reason this beats a document
    118 is that an investigation is a graph of entities, not a narrative, and the thing you need six weeks
    119 in is "every note that mentions this phone number". Obsidian suits entity-per-note work where the
    120 links between people are the finding; Logseq's daily journal and outliner suit chronology-heavy
    121 work. Both store Markdown on disk, so the vault is greppable, diffable and `git`-able without the
    122 application.
    123 
    124 Structure the vault so that provenance cannot be separated from content:
    125 
    126 ```text
    127 case-2026-014/
    128   00-question.md          the question, the standard of proof, the stop condition
    129   10-entities/
    130     person-a-khan.md      one file per entity, named by role not by guesswork
    131     company-northgate.md
    132     account-acct_f.md
    133   20-raw/                 collected artefacts, never edited
    134     2026-10-04T0407Z-post123.warc.gz
    135     2026-10-04T0407Z-post123.info.json
    136     MANIFEST.sha256
    137   30-findings/
    138     f01-post-edited-after-upload.md
    139   40-negative/
    140     not-found.md          every search that returned nothing, with the query
    141   90-log.md               append-only: what you did, when, from which identity
    142 ```
    143 
    144 Every entity note carries its own provenance header, so a claim can never be read without its
    145 source:
    146 
    147 ```markdown
    148 ---
    149 entity: company-northgate
    150 type: company
    151 aliases: ["Northgate Ltd", "Northgate Limited", "northgate ltd"]
    152 confidence: medium
    153 first_seen: 2026-10-03
    154 last_checked: 2026-10-04
    155 ---
    156 
    157 ## Established
    158 
    159 - Registered number 09876543, UK. Source: Companies House API, retrieved
    160   2026-10-04T04:07Z. Raw: `20-raw/ch-09876543.json` (sha256 4b1c8e...).
    161 
    162 ## Reported but unverified
    163 
    164 - Described as "the trading arm" in the filing at para 17. Single source,
    165   uncorroborated, author has an interest. Do not repeat as fact.
    166 
    167 ## Ruled out
    168 
    169 - Not the same as Northgate Mining Ltd (number 07654321). Different officers,
    170   different address, name similarity only. Checked 2026-10-04.
    171 
    172 ## Open
    173 
    174 - Beneficial owner behind the BVI parent. UK PSC filing names the parent only.
    175 ```
    176 
    177 The `Ruled out` section is the one people skip and the one that saves the investigation. An
    178 explicitly rejected hypothesis stays rejected; an implicitly rejected one resurfaces in a month as
    179 a half-remembered lead and sometimes as a published error.
    180 
    181 Three cautions. Do not use wiki-style double-bracket links if the notes might ever be published or
    182 converted — they do not resolve outside the application, and a dead link in a published finding
    183 reads as sloppiness. Sync services put your entire research graph on third-party infrastructure, so
    184 if the vault syncs, know where to. And a vault is not an archive: the notes reference the artefacts,
    185 and the artefacts need their own hashes and timestamps.
    186 
    187 ### The research account
    188 
    189 A separate identity that touches targets, which you expect to lose. Platforms ban research accounts
    190 eventually — for scraping, for viewing too many profiles, for geographic inconsistency, for nothing
    191 at all — so build nothing on it you cannot walk away from, and never let it share anything with an
    192 account you care about.
    193 
    194 There is no tool for this. There is a checklist, and the order matters:
    195 
    196 ```text
    197 BEFORE the account exists
    198   [ ] Decide the persona's purpose. A plausible-but-empty account is more
    199       suspicious than an obviously new one with a stated interest.
    200   [ ] Email first, from a provider that does not require a phone number, and
    201       never from the provider your real accounts use.
    202   [ ] Phone number, if the platform demands one. A number you control and can
    203       lose. Never your own; a reused number links the research account to you
    204       permanently and silently, because platforms match on it across services.
    205   [ ] Password manager entry with the case ID in the title, so the account is
    206       findable and disposable as a unit.
    207 
    208 WHEN the account exists
    209   [ ] Separate browser profile at minimum, separate VM if the target is
    210       competent. Never the same profile as anything personal — shared cookies,
    211       shared localStorage and shared autofill all link them.
    212   [ ] Consistent timezone, language and locale between the account's stated
    213       location and the browser's. A profile claiming Lisbon from an en-GB
    214       browser on UTC+0 is a detectable mismatch.
    215   [ ] No contact import. Ever. One accidental contact sync hands the platform
    216       your real address book and the platform hands the target "people you
    217       may know".
    218   [ ] Age the account before using it. A day-old account viewing 200 profiles
    219       is a rate-limit and a ban; a two-month-old one is a user.
    220 
    221 ONGOING
    222   [ ] One account per investigation where the targets could plausibly compare
    223       notes. Cross-contamination between cases is how one burn becomes three.
    224   [ ] Log every target the account touched, so you can assess the damage when
    225       it is eventually identified.
    226   [ ] Expect it to be lost. Export anything you need from it as you go.
    227 ```
    228 
    229 The legal and ethical line is not a technical question and the checklist does not answer it.
    230 Creating an account usually breaches a platform's terms of service; in some jurisdictions and some
    231 employment contexts it does more than that, and a persona that actively deceives a person — rather
    232 than merely observing public content — is a different act from a passive research account. Know
    233 which one you are doing, get it authorised in writing if you are doing it for anyone but yourself,
    234 and note that nothing here makes impersonating a real person or organisation acceptable.
    235 
    236 ### Isolation: a disposable VM
    237 
    238 A compromise or a deanonymisation should cost you a throwaway machine rather than your real one and
    239 the identity attached to it. Containers and virtual machines are not interchangeable here:
    240 a container shares the host kernel and, with default settings, the host network identity, which
    241 makes it fine for running CLI tooling and wrong for browsing a hostile target. Browse from a VM.
    242 
    243 ```bash
    244 # full VM, Ubuntu, disposable: multipass on macOS and Windows
    245 multipass find                                      # 26.04 is the current LTS alias
    246 multipass launch lts --name research-014 --cpus 2 --memory 4G --disk 20G
    247 multipass shell research-014
    248 multipass stop research-014 && multipass delete research-014 --purge   # gone
    249 
    250 # or Lima, the same idea with a declarative YAML template.
    251 # Note the locator form: `template:` — the older `template://` is deprecated as of Lima 2.0
    252 limactl create --name=research-014 template:ubuntu-lts
    253 limactl start research-014
    254 limactl shell research-014
    255 limactl delete --force research-014
    256 
    257 # snapshot before you touch the target, so you can roll back to clean.
    258 # multipass only snapshots a STOPPED instance, so stop it first
    259 multipass stop research-014
    260 multipass snapshot research-014 --name pre-target
    261 multipass start research-014
    262 # ...after the session, roll back
    263 multipass stop research-014
    264 multipass restore research-014.pre-target --destructive
    265 ```
    266 
    267 ```bash
    268 # containers: correct for CLI tooling, with the network identity made explicit
    269 docker run --rm -it \
    270   --dns 1.1.1.1 \
    271   --cap-drop ALL --security-opt no-new-privileges \
    272   -v "$PWD/out:/out" \
    273   python:3.13-slim bash
    274 
    275 # route a container's traffic through a proxy you control, and nothing else
    276 docker run --rm -it \
    277   -e ALL_PROXY=socks5h://host.docker.internal:1080 \
    278   -e HTTPS_PROXY=socks5h://host.docker.internal:1080 \
    279   -v "$PWD/out:/out" python:3.13-slim bash
    280 
    281 # a container that cannot reach the network at all, for handling a hostile file
    282 docker run --rm -it --network none -v "$PWD/sample:/sample:ro" python:3.13-slim bash
    283 
    284 # check the VM's egress before you use it, not after
    285 multipass exec research-014 -- curl -s https://am.i.mullvad.net/json
    286 ```
    287 
    288 For network-level rather than machine-level isolation, Whonix routes an entire VM's traffic through
    289 Tor at the gateway, so a misconfigured application inside it cannot leak around the proxy, and
    290 Tails gives you an amnesic live system that forgets everything on shutdown. Both are the right
    291 answer when the consequence of being identified is serious; both are heavy enough that people skip
    292 them for routine work, which is a defensible trade as long as it is a decision rather than a
    293 default.
    294 
    295 What isolation does not buy you: a clean VM behind a VPN is still identified by the account you log
    296 into, the browser fingerprint you present and the timing of your activity. Isolation limits the
    297 blast radius of a mistake. It does not make you anonymous.
    298 
    299 ### Touching a target without leaking
    300 
    301 When you need the bytes from a target's own server rather than from an archive, go via the command
    302 line rather than a browser, because a browser sends dozens of headers you did not choose and runs
    303 code the target wrote. Here the honest version matters: **neither `curl` nor `wget` has a
    304 `--no-referer` flag, because neither sends a `Referer` header unless you ask it to.** Verified, a
    305 default `curl` request arrives at the server carrying only `Host`, `User-Agent` and `Accept`.
    306 
    307 ```bash
    308 # exactly what a default curl sends — check this yourself rather than trusting it
    309 curl -s https://postman-echo.com/headers | jq .
    310 # {"headers":{"host":"postman-echo.com","user-agent":"curl/8.7.1","accept":"*/*", ...}}
    311 ```
    312 
    313 ```bash
    314 # headers only, no body: cheapest possible look, and it reveals the stack
    315 curl -sI 'https://target.example/page'
    316 
    317 # response headers AND body, with the body discarded — some servers lie on HEAD
    318 curl -s -o /dev/null -D - 'https://target.example/page'
    319 
    320 # present a plausible browser UA. A default "curl/8.7.1" in a small site's log
    321 # is a flag that says "someone is scripting against us"
    322 curl -s -A 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0 Safari/537.36' \
    323      'https://target.example/page' -o page.html
    324 
    325 # send no User-Agent at all, which is a different and sometimes better choice
    326 curl -s -H 'User-Agent:' 'https://target.example/page' -o page.html
    327 
    328 # a Referer only when you deliberately want the log to show a plausible path
    329 curl -s -A 'Mozilla/5.0 ...' -e 'https://www.google.com/' 'https://target.example/page'
    330 
    331 # show the redirect chain without following it into something you did not expect
    332 curl -sIL -w '%{http_code} %{url_effective}\n' -o /dev/null 'https://target.example/short'
    333 
    334 # through a SOCKS proxy, with DNS resolved AT the proxy — socks5h, not socks5
    335 curl -s --proxy socks5h://127.0.0.1:9050 'https://target.example/page' -o page.html
    336 
    337 # wget equivalents, for a recursive pull you want to keep polite
    338 wget -U 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0 Safari/537.36' \
    339      --wait=2 --random-wait --limit-rate=200k \
    340      --page-requisites --adjust-extension 'https://target.example/page'
    341 ```
    342 
    343 `socks5h` versus `socks5` is the one that bites people: with `socks5`, `curl` resolves the hostname
    344 locally and only the TCP connection goes through the proxy, so your resolver — and therefore your
    345 ISP and often your employer — sees exactly which host you looked up. With `socks5h` the proxy does
    346 the resolution. The same distinction applies to `ALL_PROXY` in the container examples above.
    347 
    348 Two things no flag fixes. The TLS handshake carries the hostname in SNI unless the server supports
    349 Encrypted Client Hello, so a passive observer on your network learns which site you contacted
    350 regardless of these options. And a target that fronts its site with a CDN sees your request through
    351 that CDN's logging, which is a second party you did not choose.
    352 
    353 ### Leak checks: IP, DNS and WebRTC
    354 
    355 Run these before you touch a target, after every network change, and after every VPN reconnect.
    356 The failure you are looking for is not "am I behind a VPN" — it is "does something on this machine
    357 resolve or connect outside the tunnel", which is invisible until you measure it.
    358 
    359 ```bash
    360 # the address a web server sees
    361 curl -s https://am.i.mullvad.net/json | jq '{ip, country, city, mullvad_exit_ip, organization}'
    362 curl -s https://ifconfig.co/json | jq '{ip, country, asn_org}'
    363 
    364 # the address your DNS RESOLVER egresses from — this is the leak that matters.
    365 # If this is your ISP while the line above is a VPN exit, DNS is outside the tunnel.
    366 dig +short TXT o-o.myaddr.l.google.com @ns1.google.com
    367 
    368 # resolver IP, your apparent client IP, and the EDNS Client Subnet your resolver
    369 # is handing to authoritative servers. An "ecs" line means your /24 is being
    370 # disclosed to every nameserver you query.
    371 dig +short TXT whoami.ds.akahelp.net
    372 
    373 # which resolvers this machine is actually using, whatever the VPN client claims
    374 scutil --dns | grep nameserver          # macOS
    375 resolvectl status | grep -A2 'DNS Serv' # systemd-resolved
    376 
    377 # does a hostname resolve the same inside and outside the isolated VM
    378 dig +short target.example
    379 multipass exec research-014 -- dig +short target.example
    380 
    381 # mullvad's own CLI, if that is your provider: state, and whether DNS is leaking
    382 mullvad status
    383 mullvad dns get
    384 ```
    385 
    386 WebRTC and browser fingerprinting have no CLI equivalent, because the leak is the browser's and
    387 only a browser reproduces it:
    388 
    389 ```text
    390 https://browserleaks.com/webrtc     does the browser disclose your real local
    391                                     and public IP via ICE candidates, around
    392                                     the proxy. This is the classic VPN leak and
    393                                     it is a browser setting, not a network one.
    394 https://browserleaks.com/dns        which resolvers the browser actually used
    395 https://www.dnsleaktest.com/        extended test; run it, not the standard one
    396 https://coveryourtracks.eff.org/    how distinctive your fingerprint is. Read
    397                                     the "one in N browsers" number, not the
    398                                     pass/fail badge.
    399 https://browserleaks.com/geo        whether the page can get a precise location
    400                                     from the OS rather than from the IP
    401 ```
    402 
    403 Read the fingerprint result carefully, because the intuition is backwards: hardening a browser with
    404 unusual settings and a long extension list makes it *more* identifiable, not less. A stock browser
    405 in a stock VM is often the better disguise than a heavily customised one, and the only reliable
    406 counter to fingerprinting is to look like a large crowd.
    407 
    408 What these checks cannot tell you: whether the target correlated your visit with something else.
    409 Timing, a reused screen resolution, the same unusual font set, a session that starts every weekday
    410 at 09:10 UTC — none of that shows up in a leak test, and all of it is linkable across identities.
    411 
    412 ### Chain of custody
    413 
    414 The record that lets you say, later, that the file you are producing is the file you received, and
    415 that nothing happened to it in between that you have not written down. It costs a minute per
    416 artefact and it is the first thing attacked when a finding matters.
    417 
    418 ```bash
    419 # the moment an artefact arrives, before you open it
    420 IN=~/cases/2026-014/20-raw
    421 mkdir -p "$IN"
    422 cp /Volumes/USB/clip.mp4 "$IN/"                     # copy, never move
    423 shasum -a 256 "$IN/clip.mp4" | tee -a "$IN/MANIFEST.sha256"
    424 chmod 444 "$IN/clip.mp4"                            # read-only: work on copies
    425 
    426 # the custody note, as a sibling file, written now and never edited
    427 cat > "$IN/clip.mp4.custody" <<'EOF'
    428 artefact:     clip.mp4
    429 sha256:       4b1c8e...                 # from MANIFEST.sha256
    430 received_at:  2026-10-04T04:07:56Z      # date -u +%FT%TZ
    431 received_from: source S-3 (see 10-entities/source-s3.md), in person, USB
    432 provided_as:  claimed original off a phone; no chain before this point
    433 handled_by:   J. Investigator
    434 first_action: hashed, set read-only, copied to 50-work/ for analysis
    435 onward:       none
    436 EOF
    437 
    438 # every derived file records what it came from, so no copy is ever orphaned
    439 shasum -a 256 50-work/clip-frame-0137.png >> 50-work/DERIVED.sha256
    440 printf '%s\tderived from\t%s\n' 'clip-frame-0137.png' 'clip.mp4 (4b1c8e...)' \
    441   >> 50-work/DERIVED.index
    442 
    443 # append-only activity log, one line per action, in UTC
    444 printf '%s\t%s\n' "$(date -u +%FT%TZ)" 'extracted frame 00:01:37.5 with ffmpeg 8.0' \
    445   >> ~/cases/2026-014/90-log.md
    446 
    447 # verify the whole raw tree before you hand anything over
    448 shasum -a 256 -c "$IN/MANIFEST.sha256" | grep -v ': OK$'
    449 ```
    450 
    451 Then timestamp the manifest, which is what converts your own record into a third party's assertion
    452 about time — `ots stamp` and the RFC 3161 route are in
    453 [Archiving & Evidence Preservation](/sheets/osint/archiving-and-evidence).
    454 
    455 Four rules that are not negotiable. UTC everywhere, because a local timestamp in a report with
    456 international sources is ambiguous and ambiguity is attackable. Copy rather than move, so the
    457 original stays where it was. Write the note at the time, because a custody note reconstructed from
    458 memory is exactly as reliable as it sounds. And record the gap honestly: if you do not know where
    459 the file was before your source handed it to you, the note says "no chain before this point" rather
    460 than nothing, because an unstated gap reads as a concealed one.
    461 
    462 ### The negative-results log
    463 
    464 The cheapest high-value habit on this page, and the one almost nobody keeps. A searchable record of
    465 every query that returned nothing stops you repeating dead ends, tells you where your coverage
    466 actually ends, and is the only honest basis for a sentence like "no public record of X exists".
    467 
    468 ```text
    469 # 40-negative/not-found.md — append-only, one block per attempt
    470 
    471 ## 2026-10-04T04:12Z — Companies House officer search
    472 query:    "Khan" + date of birth 1979-03
    473 scope:    all UK registered companies, active and dissolved
    474 result:   0 matches with that DOB month
    475 means:    not registered as a UK officer under that spelling. Does NOT mean
    476           not an officer: Companies House shows DOB month and year only, and
    477           transliteration variants were not tested.
    478 next:     re-run via Bellingcat Name Variant Search for Cyrillic variants
    479 
    480 ## 2026-10-04T04:31Z — Sherlock, handle "acct_f"
    481 query:    sherlock acct_f --print-found
    482 result:   3 hits, all confirmed unrelated third parties
    483 means:    handle is reused; it is not a usable pivot for this person
    484 next:     pivot on the profile photo instead, not the handle
    485 
    486 ## 2026-10-04T05:02Z — Wayback, target.example/about
    487 query:    CDX, matchType=prefix, from=20240101
    488 result:   no captures
    489 means:    nothing about absence of the page. The site serves a robots
    490           directive that Wayback honoured at crawl time.
    491 next:     check archive.today and Ghostarchive before concluding anything
    492 ```
    493 
    494 The `means:` line is the whole point and it is the line that gets dropped. "Zero results" is a fact
    495 about a tool's coverage, and turning it into a fact about the world is the single most common
    496 overreach in open-source work. A people-search service returning nothing means that service has
    497 nothing. A registry returning nothing means that registry, under that spelling, on that date.
    498 
    499 Write the `next:` line too. A negative result with a stated next step is a lead; a negative result
    500 without one is just a gap you will rediscover.
    501 
    502 ## Verification
    503 
    504 Treat every claim as unverified until it is pinned to something independent:
    505 
    506 - **Where** — does the imagery match satellite, street view, terrain? Are the shadows consistent
    507   with the claimed time? See [Geolocation](/sheets/osint/geolocation).
    508 - **When** — is the content older than the event it supposedly shows? Reverse image search first,
    509   every time. See [Reverse Image Search](/sheets/osint/reverse-image-search).
    510 - **Who** — does the account have history, or was it created last week? Do the same photos appear
    511   on other profiles under other names?
    512 - **What** — is the file original, or a re-encode of a re-encode? See
    513   [Image & Video Forensics](/sheets/osint/image-video-forensics).
    514 
    515 Two sources that both trace back to the same original post are one source.
    516 
    517 ## Note-taking and case management
    518 
    519 | Tool | What it does | Cost |
    520 | --- | --- | --- |
    521 | [Hunchly](https://www.hunch.ly/) | Browser extension that silently captures every page you visit during a case, with hashes and timestamps, and builds a searchable case file. | paid |
    522 | [Obsidian](https://obsidian.md/) | Local markdown notes with backlinks. Good for entity-per-note investigations where the links between people matter as much as the people. | free |
    523 | [Logseq](https://logseq.com/) | Outliner-style local notes with daily journals. Suits chronology-heavy work. | free |
    524 | [Atlos](https://www.atlos.org/) | Purpose-built collaborative platform for visual investigations, with source tracking and multi-investigator review. | free |
    525 
    526 ## Pitfalls
    527 
    528 - **Confirmation lock-in.** Writing the conclusion first and collecting support for it. Ask what
    529   evidence would prove you wrong, then go look for that.
    530 - **Machine translation as fact.** A mistranslated verb changes a claim. Check anything load-bearing
    531   with a speaker or a second engine.
    532 - **Automated tools as authority.** Username enumerators, facial recognition and breach lookups all
    533   produce false positives. They generate leads, not findings.
    534 - **Losing the chain.** If you cannot say where a file came from and when you got it, you cannot
    535   use it.
    536 - **Forgetting the human cost.** Publishing that someone can be located has consequences for them.
    537   Minimise what you expose beyond what the finding requires.
    538 - **A VPN indicator is not a leak test.** The client says "connected" while the system resolver
    539   still egresses from your ISP, and a browser can hand out your real address over WebRTC around any
    540   tunnel. Measure the resolver and the browser separately, after every reconnect.
    541 - **`socks5` where you meant `socks5h`.** The proxy carries the connection but your own resolver
    542   does the lookup, so the hostname is logged locally even though the traffic was not.
    543 - **Hardening a browser makes it more identifiable.** An unusual configuration and a long extension
    544   list are a fingerprint. A stock browser in a disposable VM hides in a larger crowd.
    545 - **Zero results is a fact about a tool, not about the world.** Record what the gap means and what
    546   it does not, in the same note, at the time.
    547 
    548 ## Worked example
    549 
    550 One datum: a tip-off email naming a company, `Northgate Minerals Trading`, and asserting it is a
    551 front. Nothing else. The question is not "is it a front" — that is a conclusion looking for support.
    552 This is the first hour, before any collection, and what it buys you.
    553 
    554 ```text
    555 # 1. write the question down. 00-question.md
    556 question:   Does any public record link Northgate Minerals Trading to
    557             [named entity] through a shared officer, address or owner?
    558 standard:   two independent primary sources per link, or it is "reported, unverified"
    559 out of scope: the tipster's motive; family members of any officer
    560 stop when:  the question is answered either way, or three named registries
    561             have been checked and returned nothing
    562 exposure:   registry APIs and archives only. NO requests to any Northgate-
    563             controlled domain from an attributable address until step 6.
    564 ```
    565 
    566 The exposure line is the decision that constrains everything after it. Having written it down, the
    567 first four steps are forced: only sources that do not touch the target.
    568 
    569 ```bash
    570 # 2. establish the egress before anything leaves the machine
    571 curl -s https://am.i.mullvad.net/json | jq '{ip, country, organization, mullvad_exit_ip}'
    572 dig +short TXT o-o.myaddr.l.google.com @ns1.google.com
    573 # web-visible IP: a VPN exit, country NL
    574 # resolver egress: 203.0.113.x — the SAME ISP range as the host, not the VPN
    575 ```
    576 
    577 DNS is outside the tunnel. Every hostname you look up is visible to the ISP, and will be whether or
    578 not the HTTP request goes through the VPN. Fix that before step 3, not after: the resolver leak is
    579 the one that persists, because it is a system setting and the VPN client reported "connected".
    580 
    581 ```bash
    582 # 3. isolation, and verify it from inside rather than trusting the launch
    583 multipass launch lts --name research-014 --cpus 2 --memory 4G --disk 20G
    584 multipass exec research-014 -- curl -s https://am.i.mullvad.net/json | jq -r .ip
    585 multipass exec research-014 -- dig +short TXT o-o.myaddr.l.google.com @ns1.google.com
    586 # both now report the VPN exit. Snapshot clean before use:
    587 multipass stop research-014 && multipass snapshot research-014 --name pre-target
    588 multipass start research-014
    589 ```
    590 
    591 ```text
    592 # 4. open the Hunchly case BEFORE the first search, not after
    593 case name:  2026-014            (the case ID, never "Northgate")
    594 selectors:  Northgate Minerals Trading
    595             Northgate Ltd
    596             09876543
    597             [officer surname, once known]
    598 capture:    ON — confirmed by the extension icon after the browser restart
    599 ```
    600 
    601 Every page from here on is captured, hashed and timestamped whether or not you thought it mattered
    602 at the time. That is the whole reason the case opens before the searching: the page you will need is
    603 the one you skimmed on the way to something else.
    604 
    605 ```bash
    606 # 5. collect from sources that do not touch the target, and log the negatives
    607 #    (the registry and sanctions commands themselves live on the companies sheet)
    608 printf '## %s — Companies House name search\nquery: "Northgate Minerals Trading"\nresult: 2 hits, gb/09876543 active + vg/1654321 (source dated 2019)\nmeans: a UK and a BVI company share the name. Not yet evidence they are related.\nnext: PSC filing on 09876543\n\n' \
    609   "$(date -u +%FT%TZ)" >> ~/cases/2026-014/40-negative/not-found.md
    610 ```
    611 
    612 ```bash
    613 # 6. the only step that touches the target, and only after deciding to
    614 #    headers first: it answers the hosting question without fetching the page
    615 multipass exec research-014 -- \
    616   curl -sI -A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0 Safari/537.36' \
    617   'https://northgate-minerals.example/' | head -12
    618 # Server: cloudflare  →  the origin IP is not in this response, and a CDN
    619 # operator now has a log line for this request. Noted in 90-log.md.
    620 ```
    621 
    622 A `HEAD` from a VM behind a VPN, with a browser UA, after an explicit decision — rather than a
    623 browser tab opened reflexively in hour one from your own address. The difference costs ninety
    624 seconds and is the difference between the target knowing and not knowing.
    625 
    626 ```bash
    627 # 7. the artefacts, hashed and custody-noted at the moment they arrive
    628 IN=~/cases/2026-014/20-raw; mkdir -p "$IN"
    629 multipass transfer research-014:/home/ubuntu/ch-09876543.json "$IN/"
    630 shasum -a 256 "$IN/ch-09876543.json" | tee -a "$IN/MANIFEST.sha256"
    631 chmod 444 "$IN/ch-09876543.json"
    632 printf '%s\t%s\n' "$(date -u +%FT%TZ)" 'retrieved CH filing 09876543 via API from research-014' \
    633   >> ~/cases/2026-014/90-log.md
    634 ```
    635 
    636 ```text
    637 # 8. the entity note, written as three separate claims. 10-entities/company-northgate.md
    638 Established:        number 09876543, UK, active. Source: CH API, 2026-10-04T05:12Z,
    639                     raw ch-09876543.json (sha256 4b1c8e...).
    640 Reported/unverified: "a front". Single source, the tipster, who has an interest.
    641                     Not repeated as fact anywhere else in the case.
    642 Ruled out:          not Northgate Mining Ltd (07654321) — different officers,
    643                     different address, name similarity only. Checked 2026-10-04.
    644 Open:               beneficial owner behind the BVI parent.
    645 ```
    646 
    647 After an hour the case holds: a written question with a stop condition, a fixed and verified
    648 exposure posture, a continuous capture log, two registry records with hashes and custody notes, one
    649 explicitly rejected lookalike company, and a negative-results entry that says what "two hits" does
    650 and does not mean.
    651 
    652 What you can assert: which sources were queried, from which exposure posture, what they returned,
    653 and that the preserved registry artefacts still match the hashes recorded at acquisition. This is
    654 an auditable collection record, not a finding that the tipster's allegation is true.
    655 
    656 What none of that establishes: whether Northgate is a front. The tipster's claim is still exactly
    657 one uncorroborated assertion, recorded as such, in a section of the note that cannot be mistaken
    658 for a finding. The substantive work now moves to
    659 [Company & Financial Records](/sheets/osint/companies-and-finance) — but it moves there on top of a
    660 record that will survive someone attacking it, which is the only thing this sheet is for.
    661 
    662 What would falsify it: an exposure check showing traffic left by the host rather than the research
    663 VM, a gap in the action log, or a hash mismatch on either source artefact. Those failures do not
    664 prove the allegation false; they make the collection record too weak to support later claims.
    665 
    666 ## Broader catalogues
    667 
    668 - [Foundational OSINT Tools](https://tools.osintnewsletter.com/tool-categories/foundational-osint-tools)
    669 - [Bellingcat — Guides & Handbooks](https://bellingcat.gitbook.io/toolkit/resources/guides-and-handbooks)
    670 
    671 
    672 ## More tools
    673 
    674 Further tools for this area from the OSINT Newsletter Tools Library ([Foundational OSINT Tools](https://tools.osintnewsletter.com/tool-categories/foundational-osint-tools), [Language Translation OSINT](https://tools.osintnewsletter.com/tool-categories/language-translation-osint)), excluding those already listed above.
    675 
    676 | Tool | What it does |
    677 | --- | --- |
    678 | [100 Search Engines](https://www.100searchengines.com/) | A simple search hub that brings multiple search engines and specialist search services into one place. |
    679 | [2lingual Search](https://www.2lingual.com/) | A specialist search engine that lets investigators search the web in one language and discover results in another. |
    680 | [527 Explorer](https://projects.propublica.org/527-explorer/) | A ProPublica database that lets you track political “527” organisations in the US i.e. groups that raise and spend money to… |
    681 | [Apertium](https://en.wikipedia.org/wiki/Apertium) | An open-source rule-based machine translation platform. |
    682 | [Authentic8 Silo Workspace](https://authentic8.com/) | A secure, cloud-native browser designed for conducting online investigations safely, anonymously, and at scale. |
    683 | [Babylon](https://www.babylon-software.com/dictionary/) | Multilingual dictionary and translation tool. |
    684 | [Copyleaks](https://copyleaks.com/) | AI-powered plagiarism and AI-content detection platform that compares text against web pages, academic sources and proprietary… |
    685 | [Cover Your Tracks](https://coveryourtracks.eff.org/) | A privacy-testing tool from the Electronic Frontier Foundation that checks how identifiable your browser and device are online. |
    686 | [DeepL Translator](https://www.deepl.com/en/translator) | Online translation tool that converts text from one language to another. |
    687 | [DuckDuckGo](https://duckduckgo.com/) | A privacy-focused internet search engine and web browser. |
    688 | [EarthPoint Convert](https://www.earthpoint.us/Convert.aspx) | A web-based conversion tool for transforming geographic coordinate data between formats. |
    689 | [Excite Web Search](https://www.excite.com/) | A general-purpose internet search service to search for publicly available webpages and online information using keywords, names… |
    690 | [Fagan Finder](https://www.faganfinder.com/) | A comprehensive search portal that brings together hundreds of search engines, specialist databases, and online resources in one… |
    691 | [FindTheScam](https://findthescam.net/) | Checks whether a website looks legitimate or risky by reviewing WHOIS age, HTTPS/SSL, DNS, reputation, and scam-warning signals. |
    692 | [Finger Printer](https://gonzosint.github.io/fingerprinter/) | An interactive browser fingerprinting dashboard that generates and displays a range of unique identifiers based on the behaviour… |
    693 | [Forensic OSINT](https://www.forensicosint.com/) | A digital evidence capture and preservation platform to collect, document, and preserve online content. |
    694 | [FreeSubtitles AI](https://subtitles.app/) | AI-powered transcription and subtitle generation tool that converts audio and video files into text and subtitles, with… |
    695 | [GetProofAnchor](https://getproofanchor.com/) | A web-based tool that captures and preserves online content as verifiable digital evidence. |
    696 | [Human or AI](https://humanizeai.com/human-or-ai/) | A game-style OSINT training tool that challenges you to spot the difference between real human profile photos and AI-generated… |
    697 | [Known Agents](https://knownagents.com/) | A directory of AI bots and the associated information it has on each bot. |
    698 | [Maltego](https://www.maltego.com/) | A visual link analysis and OSINT platform to discover, map, & understand relationships between people, organisations, domains… |
    699 | [OpenGraph Intel](https://ogi.khas.app/) | A self-hosted OSINT and link analysis platform that enables investigators to collect, enrich, visualise, and analyse… |
    700 | [OSINTracker](https://www.osintracker.com/) | A browser-based OSINT investigation management platform that helps organise entities, map relationships, visualise connections… |
    701 | [Palette by OSINT Industries](https://app.osint.industries/palette) | A powerful graph visualisation platform with integrated native search for mapping and analysing OSINT data relationships. |
    702 | [SIERRA](https://phantomhelix.com/download) | A local-first desktop investigation workspace for organizing evidence, entities, notes, timelines, and tool output in one case… |
    703 | [Ubikron](https://www.ubikron.com/) | An OSINT investigation workbench that transforms your browser into a structured intelligence collection and analysis platform. |
    704 | [Your social media fingerprint](https://robinlinus.github.io/socialmedia-leak/) | An OSINT awareness tool showing how much personal and behavioural data can be “leaked” from social media activity to understand… |
    705 
    706 ## Sources
    707 
    708 Both catalogues below are maintained by other people and are considerably larger than
    709 this page. Use them as the canonical index; this sheet is a working route through them.
    710 
    711 - [Bellingcat's Online Investigation Toolkit](https://bellingcat.gitbook.io/toolkit) — ~340 tools, each with its own
    712   review page covering cost, difficulty, requirements and limitations.
    713 - [OSINT Newsletter Tools Library](https://tools.osintnewsletter.com) — ~280 tools, organised by investigative goal.
    714 
    715 Neither publishes a licence, so nothing here is copied from them: tool names, one-line
    716 descriptions, cost flags and links are catalogue facts, and the method and commentary are
    717 this site's own. See [credits](/credits).