workflow_dispatch button to bump version (patch/minor/major/custom),
update CHANGELOG.md, commit, tag and push to main via standard-version
— reusing the existing yarn release / sync-versions.js / .versionrc
setup instead of duplicating bump logic in YAML. The tag push then
triggers images.yml as-is.
Requires a GH_PAT secret: pushes made with the default GITHUB_TOKEN
don't trigger other workflows (GitHub anti-loop policy), so a plain
checkout token would silently skip the images.yml build.
sync-versions.js now also bumps the 4 workspace pyproject.toml files
(flowsint-api/core/enrichers/types) — previously only root
pyproject.toml and flowsint-app/package.json were kept in sync.
standard-version added as an explicit devDependency (was only
resolved transitively via yarn.lock before).
flowsint-app/package.json was stuck at 1.0.0 and root pyproject.toml
at 1.2.8, both behind the actual v1.2.11 tag. standard-version reads
flowsint-app/package.json as its source of truth, so the next release
would have tagged v1.0.1 — a semver regression breaking the Docker
image tags in images.yml.
Container couldn't open /etc/nginx/nginx.conf (permission denied) on
SELinux-enforcing hosts (e.g. Fedora Kinoite) because the bind-mounted
file kept its host label. Add :Z to relabel it for container-only
access; no-op on hosts without SELinux.
Fixes#207
Two enrichers silently return empty results instead of failing loudly.
1. domain_to_dns
dnsx >= 1.2 treats -d as "bruteforce this domain" and exits with
"missing wordlist(w) flag required with domain(d) input" unless -w is
also given, so `dnsx -d example.com -a -aaaa -json -silent` never
produces output. The enricher catches nothing (the tool exits 0) and
returns [], while Celery still reports the task as succeeded.
Feed the single target on stdin instead, which is the supported
single-target invocation. DockerTool.launch() gains an optional
entrypoint override so a shell can be put in front of the image
entrypoint; the domain is passed through shlex.quote().
2. ip_to_fraudscore
Scamalytics assigns each account a numbered API node (api11, api12,
...) and the host was hardcoded to api12, which returns 404 for every
account provisioned on a different node. The host is now read from a
SCAMLYTICS_API_HOST secret/env var, defaulting to the previous api12
so existing deployments are unaffected.
Verified against dnsx v1.2.2 and a live Scamalytics v3 account.
ctx.clip() without save/restore was permanently mutating the clipping
region across all subsequent canvas draw calls, causing uncontrollable
scaling on nodes and background when a node had an imageUrl.
Remove Docker-specific resolver (127.0.0.11) in favor of direct
proxy_pass, which falls back to the system resolver (/etc/resolv.conf).
Mount local nginx.conf into the prod image to override the baked-in config.
TXT imports of file hashes were detected as Username, because File.detect
always returned False and Username.detect matches any 3-80 char
alphanumeric string. Hashes therefore couldn't be used as File entities
to pivot from (VirusTotal, MalwareBazaar, sandboxes), per #45.
- File.detect now recognizes 32/40/64-char hex strings (MD5/SHA1/SHA256),
and File.from_string stores the value in the matching hash_* field
(normalized to lowercase) while keeping it as the filename/label.
- Username.detect now explicitly rejects hash-shaped strings, so hash
detection is correct regardless of type-registration order (File is
already registered before Username, but this removes the implicit
dependency).
Tests cover detection of each hash type (case/whitespace), rejection of
non-hashes, from_string field population, the Username regression, and
end-to-end detect_type() resolution to File.
Closes#45
Adds application-level technology fingerprinting, extending coverage
beyond ip/port/website/ssl_certificate as requested in #59.
- New `Technology` type (name, version, category, source) registered in
the type registry, the package exports, and TYPE_TO_MODEL. Its
from_string accepts both bare names ("nginx") and wappalyzer-style
"name:version" pairs ("PHP:8.1").
- New `tech_detect` enricher: Website -> Technology, using the existing
httpx tool with -td (wappalyzer dataset). Each detected technology
becomes a Technology node linked to the website with a
USES_TECHNOLOGY relationship; results are de-duplicated per probe.
Tests cover the Technology type (label, from_string, registry), the
tech entry parser, enricher registration/metadata, and scan() with the
httpx Docker tool mocked, so no Docker daemon is required.
Closes#59
Adds a `domain_to_dns` enricher that resolves a domain's A (IPv4) and
AAAA (IPv6) records through ProjectDiscovery's dnsx, emitting each
resolved IP as an `Ip` node linked to the domain with a `RESOLVES_TO`
relationship.
This complements the existing `domain_to_ip` enricher (which uses
Python's socket.gethostbyname and is limited to a single IPv4 result)
by leveraging the dnsx toolkit for full A/AAAA resolution.
Implementation:
- Extend DnsxTool with `resolve_domain()` that runs
`dnsx -d <domain> -a [-aaaa] -json -silent` and parses the JSONL
output (a/aaaa fields per retryabledns.DNSData) into a de-duplicated
IP list. The existing CIDR `launch()` path is left untouched.
- New DomainToDnsEnricher (auto-registered via @flowsint_enricher) with
an optional `ipv6` toggle and optional PDCP_API_KEY vault secret.
- Unit tests covering registry wiring, JSONL parsing (A/AAAA, dedup,
blank/malformed lines, empty output) and scan() with the Docker tool
mocked, so no Docker daemon is required to run them.
Closes#79
Detected by Aeon + semgrep.
Severity: medium
CWE-350 (reverse-DNS trust) / CWE-352 (CSRF via DNS rebinding) / CWE-1021 (UI layering / dropped X-Frame-Options).
- Add `map $http_host $is_flowsint_host` allowlist + default-deny `if` at
the top of the server block. Default permits localhost / 127.0.0.1 /
::1 (any port, case-insensitive); two commented-out template lines show
LAN operators how to add their server hostname/IP.
- Re-declare the four `add_header` security headers in the static-assets
and `/index.html` location blocks, which previously dropped them due to
nginx`s replace-all add_header inheritance.
- README: one paragraph under "Deploy on a network" naming the new
operator step alongside the existing `.env` rotation.
Any code path reaching the Neo4jConnection singleton requires NEO4J_*
env vars at construction — tests only passed thanks to developers'
local .env files. Driver creation is lazy, nothing connects.
Verified by running all four suites with every .env removed:
458 passed.
Previous fix covered one occurrence; 17 other tests built
Neo4jGraphRepository(neo4j_connection=None), hitting the singleton
fallback that requires NEO4J_* env vars. Single helper, no env
dependency left.