← BACK TO PRICING · HYDRA   ·  HOW TALOS WORKS (CZ) →   ·  ČESKÁ VERZE →
TIA · TALOS · REDACTED SAMPLE

Code Security Audit — Redacted Sample

What this is. A sanitized excerpt of an internal self-audit — we ran our own code through our attack-first review method ("dogfooding"). Target identifiers are redacted; the methodology, findings, severities and data-flow traces are verbatim. This is a representative sample of a client deliverable, not a marketing mock-up.

Provenance — read this first
This is a snapshot of one run, dated 2026-07-19. It is published as a specimen of the deliverable — what a TALOS report looks like, in full, including the parts most vendors leave out. It is not a statement about the present state of any system, ours or anyone else's. The target was our own code: we ran the method on ourselves before we sold it to anyone.

The counts are checkable against the tables below: 13 externally-controlled inputs traced → 10 candidates → falsification killed 2 → 8 confirmed (1 Medium, 7 Low). If a number here does not reconcile with a table, the table wins — tell us and we will correct it.
Target internal loopback API service (name redacted) — a local async task-gateway
Scan mode READ-ONLY — exploit tests were written but not executed; each finding carries a static source→sink trace with concrete payloads. No source file was modified.
Method Recon → Parallel Hunt → Adversarial Falsification → Capability Filter → independent read-only Verify (maker ≠ grader)
Findings 0 Critical, 0 High, 1 Medium, 7 Low — all Confirmed (2 further candidates dropped in falsification)

Why "attack-first + falsification" matters (the method)

Most scanners optimise for recall — they surface everything that pattern-matches a weakness and leave you to sort signal from noise. We optimise for precision under an adversary: every candidate must survive a step whose only job is to disprove it.

Recon ─▶ Parallel Hunt ─▶ Adversarial Falsify ─▶ Capability Filter ─▶ Independent Verify
 map     many hypotheses    "prove this is NOT     "is it reachable    read-only grader,
 sinks   in parallel         real" (default:        by a real actor?"   different context
 & inputs                    refuted)                                    (maker ≠ grader)

On this run the falsification step dropped 2 of 10 candidates as false positives (see Falsification drops below). A verified-only report is worth more than a long one: you spend remediation budget on real defects, not on triage.


Trust model (this is what caps severity)

The service binds 127.0.0.1 only (gateway.py:475) and authenticates every route except /health with a single shared install token X-Api-Token (secrets.token_urlsafe(24), constant-time compare :273). There is exactly one principal — any local process holding the token — so no cross-tenant boundary exists. This caps every finding: "read/write any task" is the authenticated baseline, and blast radius is one loopback host. The highest-value finding (F-001) is principal-independent (attribution spoof + destructive), hence Medium; everything else is Low. Honest scoping beats severity inflation.


Summary

ID Title CWE Severity Status
F-001 Answer spoofing + forced deletion of any pending task CWE-290 / CWE-639 Medium Confirmed
F-002 next_id() TOCTOU race → duplicate IDs / context overwrite CWE-367 / CWE-362 Low Confirmed
F-003 Unbounded request-body read (/submit, /upload) CWE-400 Low Confirmed
F-004 Unbounded base64 attachment decode + disk write (/upload) CWE-400 Low Confirmed
F-005 Unbounded request-body read (/answer) CWE-400 Low Confirmed
F-006 Global (non-per-caller) rate-limit shared-budget DoS CWE-770 / CWE-307 Low Confirmed
F-007 Unauthenticated /health triggers filesystem scrub CWE-306 Low Confirmed
F-008 Auth token in cleartext file + stdout; chmod no-op on Windows CWE-312 Low Confirmed

Each finding shipped with a static PoC and an exploit test (written, not run).


Findings

F-001 — Answer spoofing + forced deletion of any pending task

Field Value
CWE CWE-290 (Auth Bypass by Spoofing) / CWE-639 (Authorization Bypass Through User-Controlled Key)
Severity Medium
Entry point POST /answer
Location gateway.py:448-451 (write); poll read :302-308; scrub delete :186-191
Data flow attacker sets reply_to = any task id → the handler appends {author:"worker", …} with no check the task exists / is still open (:448-451) → (a) the polling UI receives the forged answer as genuine worker output (:304-307); (b) the "answered" cleanup deletes the target task's full-context transient before the real worker reads it (:186-191).
Fix In the answer handler, verify the target task exists and is open before appending; gate the answered-deletion on a validated answer; enforce answer provenance on read.
Root cause No existence/open-state binding on the user-controlled reply_to key; hardcoded author field.
Why Medium (not Low) Principal-independent: spoof + destroy in-flight tasks is beyond the authenticated "post answers" baseline.

The fix — shipped & re-tested the same day (identifiers redacted, logic verbatim):

  # POST /answer handler
- # any caller could answer ANY id — existence unchecked, author hardcoded
- append_reply(author="worker", reply_to=req["reply_to"], text=req["text"])
+ # a reply must answer a real, still-OPEN request — everything else is refused
+ if read_request(reply_to) is None:      # no such open request  -> 404
+     return 404
+ if already_answered(reply_to):          # can't double-answer    -> 409
+     return 409
+ append_reply(author="worker", reply_to=reply_to, text=text)

Re-test after the fix: the spoof path now returns 404 and appends nothing; a pending request survives the cleanup sweep (it can no longer be forced into the "answered" set by an attacker). Both prongs — attribution spoof and forced deletion — close at the same guard. Time from confirmation to verified fix: same day.

F-002 — next_id() TOCTOU race

Field Value
CWE CWE-367 (TOCTOU) / CWE-362 (Race Condition)
Severity Low
Entry point POST /submit, POST /upload (concurrency)
Location gateway.py:136-138 (next_id), callers :336, :390
Data flow next_id() derives the id from len(read_events()) (:137) → under the threading HTTP server (:475) two concurrent requests read the same count before either appends → both allocate the same id → duplicate ledger entry and one task's context transient overwritten. The rate-limit lock guards only the hit counter, not id allocation.
Fix Serialize next_id()→append→write under one dedicated lock, or derive ids from a monotonic counter / UUID instead of ledger length.

F-003 — Unbounded request-body read (/submit, /upload)

Field Value
CWE CWE-400 (Uncontrolled Resource Consumption)
Severity Low
Entry point POST /submit, POST /upload
Location gateway.py:323, :376
Data flow attacker sets a large Content-Lengthrfile.read(n) with no MAX_BODY cap → single unbounded allocation. The rate limiter caps request count, not size.
Fix Add a module-level MAX_BODY; reject over-limit / absent / negative Content-Length with 413/400 in one shared _read_json_body() helper used by every POST route.

F-004 — Unbounded base64 attachment decode + disk write (/upload)

Field Value
CWE CWE-400
Severity Low
Entry point POST /upload
Location gateway.py:392-403
Data flow attacker sends a large base64 attachment → b64decode (:394) → open(path,"wb").write(raw) (:402-403) with no length check → attacker-controlled bytes written to disk; the TTL sweep is slower than the write rate.
Fix Enforce MAX_ATTACHMENT_BYTES on the decoded length before the disk write; reject oversize.

F-005 — Unbounded request-body read (/answer)

Field Value
CWE CWE-400
Severity Low
Entry point POST /answer
Location gateway.py:445
Data flow same pattern as F-003 at the third handler: int(Content-Length)rfile.read(n) with no cap.
Fix Same shared _read_json_body() cap as F-003 — fixes all three routes at the root.

F-006 — Global rate-limit shared-budget DoS

Field Value
CWE CWE-770 (Allocation Without Limits) / CWE-307 (Improper Restriction of Excessive Attempts)
Severity Low
Entry point all routes (gate runs pre-auth)
Location gateway.py:261-269, checked :289, :312
Data flow the limiter keeps one class-global hit list with no per-caller key, checked before auth → an unauthenticated local caller exceeding the window forces 429 for the legitimate operator (shared budget).
Fix Key the limiter per caller (client address and/or token) with an isolated per-key window.

F-007 — Unauthenticated /health triggers filesystem scrub

Field Value
CWE CWE-306 (Missing Authentication for Critical Function)
Severity Low
Entry point GET /health
Location gateway.py:290-292 → scrub :161-192
Data flow the /health branch runs the filesystem scrub before the auth check (:293) → any local unauth caller triggers deletion of already-eligible (answered / TTL-stale) transients. Opportunistic only, but real — and it chains with F-001 (unauth deletion of attacker-marked tasks).
Fix Make /health a pure read — drop the scrub call; rely on the authenticated sweep and the startup wipe.

F-008 — Auth token in cleartext file + stdout

Field Value
CWE CWE-312 (Cleartext Storage of Sensitive Information)
Severity Low
Location gateway.py:66-70 (file), :468 (stdout)
Data flow token_urlsafe(24) written cleartext to .api-token; os.chmod(...,0o600) is a no-op on Windows (:70) → the file may be world-readable; the full token is also printed to stdout (:468) → a local non-operator user reading the file/console obtains the full token (which unlocks F-001/006/007).
Fix Encrypt at rest (OS keyring / DPAPI); set a real Windows ACL instead of relying on POSIX chmod; mask the stdout print (fingerprint / last-4 only).

Resolved input inventory (completeness artifact)

A finding list is only trustworthy if it also proves what was checked and cleared. Every externally-controlled input was traced to a disposition (redacted field names):

Input Disposition
Origin header SAFE — governs only CORS reflection, not access; prefix quirk not leverageable (token still required).
X-Api-Token SAFE (auth) — constant-time compare. Token storage is CWE-312 → F-008.
Content-Length CANDIDATEF-003 (/submit,/upload), F-005 (/answer).
primary payload SAFE — redacted/secret-scrubbed before store; no injection sink.
metadata object (assorted string fields) SAFE — wrapped/redacted context; no sink.
classifier url field SAFE — classification only (allow-by-default noted as a code smell → see DiD).
option selector SAFE — not a sink.
base64 attachment CANDIDATEF-004.
reply_to key CANDIDATEF-001.
answer text body SAFE — abuse is via the reply_to binding, not the text content.
path id {id} (GET routes) SAFE — sanitizer re.sub(r"[^a-z0-9\-]","",id) blocks traversal; cross-principal IDOR not expressible (single shared token).
second-order ledger / store reads SAFE — own writes; torn-line self-heals.
CLI flags DESIGN-INTENT — local operator only; not a data sink.

All inputs resolved. Findings not tied to a single input (concurrency, global rate-limit, zero-input /health) are captured as F-002 / F-006 / F-007.


Not found / excluded (checked-but-clean classes)


Sweep verification (did we catch every instance of each root cause?)

Root cause Instances found Mitigated (=finding) Remaining
Unbounded rfile.read(Content-Length) 3 3 (F-003 ×2, F-005) 0
Unbounded b64decode → disk 1 1 (F-004) 0
Lock-free next_id() TOCTOU 3 3 (F-002) 0
Global rate-limit budget 1 1 (F-006) 0
Pre-auth state-changing endpoint 6 routes 5 auth-gated + 1 (F-007) 0
Secret at rest / stdout 3 1 (F-008) + 1 dev-only excluded 0
Injection sinks 0 0 0
Path traversal 2 2 (sanitized) 0

Every root cause maps 1:1 onto the findings — no orphaned instances.


Code quality / defense-in-depth (not exploitable as-is, but worth hardening)

Pattern Why it's not a finding today Risk if conditions change Recommendation
Content classifier uses an allow-by-default keyword blocklist no attacker-controlled sink reached — a policy completeness gap, not an injection a sensitive site whose URL lacks a listed keyword gets its body egressed move to allowlist / content-based classification; anchor consistently
Origin check via startswith(...) prefix match only reflects CORS header; token still gates access if reflection were ever used as an access decision, a look-alike origin would match use exact-origin equality / parse the host
External redaction module fails open (returns text unchanged on error) out of scan scope; not attacker-controlled if the module is missing/broken, redaction silently degrades to passthrough fail-closed (withhold) when it can't load; log the degradation

Falsification drops (the candidates we killed)

Two hypotheses reached the adversarial step and were refuted — reported here on purpose, because what a scanner discards is as diagnostic as what it keeps:


One-line honest summary

A tightly-scoped local service with a single real design defect (F-001) and a cluster of routine hardening gaps — 1 Medium, 7 Low, zero inflation, two false positives caught before they reached the report. That is what a verified deliverable looks like.

Redacted sample · attack-first review · read-only mode · maker ≠ grader.


Remediation — what happened after this report

The report above is a snapshot of the run on 2026-07-19 and is not rewritten. This is the addendum: what was changed, when, and how the change was checked. Verification was done by a pass written against each fix — maker ≠ grader applies to the repair too.

IDClosedWhat changedHow it was re-tested
F-0012026-07-19Bound the reply key to an existing, still-open request before appending; double-answers refused.Re-tested the same day: the spoof path returns 404 and appends nothing; a pending request survives the cleanup sweep.
F-0022026-08-28Id allocation serialised under a lock with an in-process high-water mark.40 concurrent allocations produced 40 distinct ids.
F-0032026-08-28One shared capped body reader for every POST route — absent, negative and oversize Content-Length all refused before allocation.99 MB declared → 413; negative → 400; header absent → 400.
F-0042026-08-28Cap enforced on the DECODED attachment length, before the disk write.Oversize image → 413 with zero files written to the store.
F-0052026-08-28Same shared reader — the fix went in at the root, not three times at three handlers.99 MB declared on the third route → 413.
F-0062026-08-28Rate limit keyed per caller class instead of one process-global list.An unauthenticated flood no longer starves the authenticated caller (200); restoring the single global bucket reproduces the 429.
F-0072026-08-28The liveness route is a pure read; the sweep runs at startup and on the authenticated route only.A scrub-eligible transient survives an unauthenticated liveness call, and is still removed by an explicit sweep.
F-0082026-08-28Credential masked in console output (printing it is now opt-in); a real Windows ACL is set instead of a POSIX permission call that does nothing there.Source check plus the ACL call on the token file.
The part most reports leave out
Read the dates before you read the fixes. The single Medium closed the same day. The seven Lows sat for 40 days and were then closed in one batch. On a loopback-only service with a single principal that is a defensible triage order — but it is a real delay, and this is the document that records it rather than the place it gets lost. Reported is not remediated. A proof-of-fix ledger is only worth something if it also carries the wait. Every fix above was re-tested by a pass written against it, not by the pass that wrote it.
HYDRA · seal over findings + remediation · 8 × F · run 2026-07-19
b2d5597ac24a8d2050506c2904c692c9b48c61132d88d7e09aa02bac22925a61

One line per finding from the Summary table — ID|CWE|Severity|Status, exactly as printed. One line per row of RemediationID|fixed|date. One line run|2026-07-19. All lines sorted alphabetically together, joined with a newline (no trailing newline), SHA-256. Every input is printed on this page.

Supersedes 414329d8ff0b6e68a173a6d4d1383fba… — the earlier seal over the finding set alone, before the remediation addendum existed. A document that changes should say so with a chain, not quietly.

What this seal does not do. It does not attest the prose, the fixes, or when this page was published, and it is not a timestamp authority. It fixes the finding set — identifiers, CWEs, severities and dispositions — so a later version of this page cannot quietly gain a finding, lose one, or downgrade a severity without the digest changing. That is the whole claim.