TTP
September 25, 2026 · View on GitHub
Version: 1.0
Last Updated: 2026-06-11
Scope: Transparent Tor Proxy (TTP) v0.4.x
Methodology: STRIDE per component
This document provides a structured threat model and risk assessment for TTP. It is intended for security auditors, contributors evaluating the security posture of the project, and users who want to understand the residual risks before deploying TTP in high-risk scenarios.
Table of Contents
- Security Objectives
- Trust Boundaries & Assets
- Threat Model (STRIDE)
- Known Limitations & Residual Risks
- Supply Chain Security
- Security Controls Summary
- Out of Scope
1. Security Objectives
TTP is designed to achieve the following security properties, in order of priority:
| # | Objective | Description |
|---|---|---|
| 1 | Traffic Confidentiality | All TCP traffic from the host must be routed through Tor. No cleartext traffic must reach the ISP. |
| 2 | DNS Leak Prevention | All DNS queries must be resolved by Tor's internal resolver. System, application, or browser-level DNS must not bypass the Tor network. |
| 3 | IPv6 Routing & Leak Prevention | Native transparent IPv6 support through Tor when supported; dropped to prevent leaks if IPv6 loopback is unavailable. |
| 4 | Crash-Safety / Fail-Closed | If TTP crashes, the network must be restored to a known state. The system must never be left in a half-configured state that leaks traffic. |
| 5 | Integrity of Session State | The session lock and runtime configuration must not be tampered with by unprivileged processes. |
| 6 | Supply Chain Integrity | TTP release artifacts must be signed. Dependencies must be audited for known CVEs. |
Critical Disclaimer: TTP is a best-effort privacy tool. It is not a guarantee of anonymity. See Section 4 for explicit residual risks.
2. Trust Boundaries & Assets
2.1 Trust Boundaries
┌─────────────────────────────────────────────────────────┐
│ TRUST BOUNDARY: Root Process (ttp running as root) │
│ │
│ ┌──────────────┐ ┌────────────┐ ┌───────────────┐ │
│ │ ttp CLI │──▶│ nftables │──▶│ Linux Kernel │ │
│ │ (Python) │ │ (inet ttp)│ │ (netfilter) │ │
│ └──────────────┘ └────────────┘ └───────────────┘ │
│ │ │
│ │ ┌────────────┐ ┌───────────────┐ │
│ └──────────▶│ systemd │──▶│ ttp-tor.svc │ │
│ └────────────┘ └───────────────┘ │
│ │ │
│ └──────────▶ /run/ttp/ (tmpfs) — volatile lock │
└─────────────────────────────────────────────────────────┘
│
▼ (all traffic exits via)
┌──────────────────────────────────┐
│ TRUST BOUNDARY: Tor Network │
│ (Entry Guards → Relays → Exit) │
└──────────────────────────────────┘
│
▼
┌──────────────────┐
│ PUBLIC INTERNET │
└──────────────────┘
2.2 Protected Assets
| Asset | Classification | Where Stored |
|---|---|---|
| Session lock file (PID, config) | Sensitive (runtime) | /run/ttp/ttp.lock (tmpfs, root-only) |
| Tor control auth cookie | Secret | /run/tor/ttp/auth_cookie (tmpfs, tor-user-only) |
| Tor Entry Guard state | Sensitive (performance) | /var/lib/tor/ttp/ (root-owned) |
Generated torrc | Configuration | /run/tor/ttp/torrc (tmpfs, root-only) |
| User's real IP address | Highly sensitive | Never stored by TTP |
| User's DNS queries | Highly sensitive | Routed through Tor's DNSPort, never logged by TTP |
3. Threat Model (STRIDE)
3.1 ttp/firewall/ Package — nftables Rules
| Threat | STRIDE Category | Description | Mitigation | Residual Risk |
|---|---|---|---|---|
Rule injection via concurrent nft command | Tampering | An attacker with root access runs nft to add bypass rules to inet ttp table | Atomic rule load via nft -f ensures consistent state at load time. Watchdog re-applies rules if the table is modified. | Low. Requires root compromise; watchdog detects within 15s. |
| Redirect silently stops matching | Information Disclosure | The NAT redirect is present in the table but no longer matches the traffic it should — a competing nat chain that DNATs first, a rule reordered by a concurrent write. The ruleset still looks correct, so shape-based checks pass. | For plain DNS a competing nat chain can take the connection first: the kernel accepts nat chains down to priority -199, below TTP's -150, and the first one to bind a connection ends NAT evaluation for it. filter_out therefore rejects any query whose original destination port was 53 and which is not headed for loopback, ahead of the LAN bypass that would otherwise accept a rewrite to a LAN resolver (#29; measured in tests/test_nse_rules.py). That reject, like the DoH and DoT rejects, carries a named counter and is unreachable while the redirect works (ADR 0012), so the watchdog treats a rise in any of the three since its previous check as an integrity failure rather than as a user's DNS habit (a first reading is compared against zero). The DNS leak probe reads the redirect counter around its own query instead of inferring from the reply, which cannot distinguish Tor's answer from the resolver's. | Low. Detected within one watchdog cycle. A counter that cannot be read is reported absent, so the check degrades to "unknown", never to "clean". |
| Pre-existing connections survive rule application | Information Disclosure | TCP connections established before ttp start continue in cleartext | No ct state established accept anywhere, so their packets reach the catch-all, which answers TCP with a reset. filter_out accepts traffic to the host's own addresses so that reset (and the ICMP error for UDP) reaches the local socket: before #36 the catch-all rejected those error replies too on a public address, and the application hung until its own timeout. Measured in tests/test_nse_rules.py for a sending and a receive-only connection, with a LAN connection shown to survive. | Low. Nothing escapes either way; a connection is reset at its next packet in either direction. An idle one lives until then, carrying nothing. |
| LAN bypass creates cleartext side-channel | Information Disclosure | Local LAN traffic (RFC 1918) bypasses Tor, revealing internal network topology | Default behavior; explicitly documented. Disabled with --no-lan-bypass. | Medium. Accepted design tradeoff; user-controlled. |
| Outbound traffic leak during session teardown | Information Disclosure | During graceful teardown, closing active Tor circuits could leak in-flight packets in cleartext | A temporary teardown lockdown rule drops all non-loopback outbound traffic (excluding Tor UID). conntrack state is also flushed. | Low. Outgoing paths are locked before rules are destroyed. |
| nftables rule persistence after crash | Elevation of Privilege | If TTP crashes, inet ttp rules might remain without DNS overlay, creating inconsistent state | Watchdog detects inconsistency; ttp stop --restore-only performs forced cleanup; ttp start detects orphaned lock and auto-restores. | Low. Multiple recovery paths exist. |
3.2 dns.py — DNS Overlay
| Threat | STRIDE Category | Description | Mitigation | Residual Risk |
|---|---|---|---|---|
| Application-level DNS bypass (DoH, DoH/QUIC) | Information Disclosure | Browsers using DNS-over-HTTPS (TCP) or HTTP/3 QUIC (UDP 443) bypass the system resolver entirely | 3-layer defense: (1) NAT output redirects all TCP/443 to Tor TransPort; (2) torrc maps DoH canary domains to 0.0.0.0; (3) nftables blocks DoT (port 853), well-known DoH IP:port 443 via TCP and UDP (QUIC). | Medium. Mitigations are best-effort. Unlisted DoH resolvers are proxied through Tor; QUIC DoH to unlisted resolvers is not blocked. Disable DoH/Secure DNS in browser settings for maximum security. |
| Stale mount stack from prior crash | Denial of Service | Multiple stale bind-mounts on /etc/resolv.conf block normal operation | Pre-start cleanup iterates /proc/mounts and removes stale layers | Low. Handled at startup. |
Symlink attack on /etc/resolv.conf | Tampering | On systemd systems, /etc/resolv.conf is a symlink; an attacker could redirect it | TTP resolves the real path via os.path.realpath() before mounting | Low. Mitigated; requires root to modify the symlink target. |
| DNS query content analysis by exit node | Information Disclosure | Tor exit nodes can observe DNS queries if not using Tor's internal resolver | TTP forces all DNS through Tor's DNSPort — queries never leave the Tor circuit as plaintext | Low (by design). Tor DNS resolution is used. |
3.3 tor_install.py / tor_control.py — Tor Daemon
| Threat | STRIDE Category | Description | Mitigation | Residual Risk |
|---|---|---|---|---|
| Malicious Tor package from distribution | Tampering | A compromised package manager provides a backdoored Tor binary | TTP uses the OS-native package manager (apt, dnf, pacman) which verifies package signatures | Low. Depends on distribution integrity; outside TTP's control. |
| Forged SELinux policy revision stamp | Tampering | TTP records the policy revision it installed in /var/lib/ttp/selinux-policy-version, because semodule reports presence but not version. A writer of that file could assert a revision that is not loaded, suppressing the reinstall. | The file and its directory are root-owned. The stamp can only ever suppress a recompile, and a host left without the current policy is one where Tor cannot bind its DNSPort: start then fails verification and exits 3 with the kill-switch standing, rather than routing anything in cleartext. A missing or unreadable stamp reads as "not current". | Low. Requires root; fails closed, and the worst non-root outcome is a redundant recompile. |
| Tor control socket unauthorized access | Elevation of Privilege | An unprivileged process connects to /run/tor/ttp/control.sock and sends SHUTDOWN | Socket permissions: CookieAuthentication 1 + ControlSocketsGroupWritable 1 with the Tor service group | Low. Cookie auth required; socket group-restricted. |
| Tor never bootstraps after the rules are applied | Information Disclosure | start applies the ruleset at step 2 but only observes the bootstrap at step 5. A failure there finds the ruleset, the DNS overlay and the lock already in place. | Kill-switch REJECT rule and policy drop block everything that is not explicitly bypassed. The session is left standing rather than torn down, and start exits 3 (not 0) so a caller cannot read the blocked network as a success. A Tor that dies during startup no longer reaches this row: the unit is Type=notify, so systemctl restart fails at step 1 with Tor's own journal lines attached, before any rule is written. What remains here is the narrower case of a daemon that starts correctly and then fails to bootstrap. | Low. Fail-closed by design. |
| Tor service fails to start before the rules are applied | Information Disclosure | setup_managed_tor exits at step 1, so no rule has been written yet. Under ttp restart the previous session has already been torn down, so the host is left on plain clearnet rather than protected. | Teardown restores the network to its known pre-TTP state instead of a half-configured one, prints Traffic in cleartext, and start exits 1. | Low, provided the operator reads the exit code. Fail-open by construction: this is requirement 4 (crash-safety), not a silent leak - but a user who assumes restart failed safely would be wrong. |
| Malicious Tor exit node | Information Disclosure | Tor exit node observes unencrypted cleartext traffic (HTTP, unencrypted protocols) | Out of scope for TTP. Users must use TLS at the application layer. | High (inherent Tor limitation). Not addressable by TTP. |
3.4 state.py — Lock File & Session
| Threat | STRIDE Category | Description | Mitigation | Residual Risk |
|---|---|---|---|---|
| Lock file tampering by unprivileged user | Tampering | An attacker modifies /run/ttp/ttp.lock to spoof session state | Lock file is owned by root (chmod 600); tmpfs path is root-managed | Low. Requires root. |
| TOCTOU race on orphan detection | Elevation of Privilege | Between orphan detection and cleanup, a new session could be started | Atomic lock write + PID validation; only root can run ttp start | Low. Root-only execution. |
3.5 watchdog/ — Session Watchdog Package
| Threat | STRIDE Category | Description | Mitigation | Residual Risk |
|---|---|---|---|---|
| Watchdog service killed by attacker | Denial of Service | An attacker with root access kills ttp-watchdog.service to disable monitoring | Watchdog is optional; its absence does not degrade the firewall or DNS protection | Medium. Without watchdog, no auto-healing or killswitch. Mitigated by always-on nftables rules. |
| False-positive killswitch activation | Denial of Service | A transient system event (e.g., systemd reload) triggers the two-strike killswitch | Two-strike policy (first failure triggers healing, second triggers killswitch); 3s stabilization window | Low. Designed to minimize false positives. |
3.6 ttp bypass — cgroups v2 Bypass
| Threat | STRIDE Category | Description | Mitigation | Residual Risk |
|---|---|---|---|---|
| Slice hijacking by unprivileged user | Elevation of Privilege | An unprivileged process writes its own PID to /sys/fs/cgroup/ttp-bypass.slice/cgroup.procs to escape Tor routing | Slice controller cgroup directories are owned by root and writable only by root. systemd-run commands targeting ttp-bypass.slice require sudo/root privileges. | Low. Standard user processes cannot migrate themselves to the bypass slice. |
| Insecure slice file configurations | Tampering | An attacker modifies /run/systemd/system/ttp-bypass.slice to gain persistent bypass or alter slice settings | Slice definition files are created dynamically on-demand, owned by root, and deleted upon ttp stop. | Low. Requires root access to edit systemd slice configurations. |
3.7 ttp-watchdog — Privilege-Separated Watchdog Daemon
Corrected in 0.4.9. Until 0.4.9 this section overstated the separation in two ways, both found by the September 2026 audit.
NoNewPrivileges=yeswas described here but never emitted into the generated unit. Andensure_runtime_dir()chowned all of/run/ttpto thettp-watchdogaccount, so "no write access to system directories" did not hold: that account could replace root's lock, log,resolv.confand nftables ruleset with symlinks and redirect a root-privileged write. Both are fixed — the directory stays root-owned and the unit emits the directive — but the residual risk below is stated for the fixed design, not the prior one.
| Threat | STRIDE Category | Description | Mitigation | Residual Risk |
|---|---|---|---|---|
| Watchdog process compromise | Elevation of Privilege | An attacker exploits the watchdog to execute arbitrary code with full root privileges | The watchdog drops all root privileges, running under the unprivileged user ttp-watchdog with NoNewPrivileges=yes and the minimal set of capabilities (CAP_NET_ADMIN). | Low. The watchdog holds CAP_NET_ADMIN, so it can program nftables directly; it has no write access to system directories and cannot run administrative shell commands. |
| Insecure Polkit rules authorization | Tampering | An attacker bypasses authentication checks to start/stop the watchdog service | Polkit rules explicitly restrict starting/stopping ttp-watchdog.service to root users and the TTP controller. | Low. Standard Polkit controls prevent unauthorized service state tampering. |
3.8 systemd-resolved — DNS Resolution Edge Cases
| Threat | STRIDE Category | Description | Mitigation | Residual Risk |
|---|---|---|---|---|
| DBus API query bypass | Information Disclosure | An application queries resolved via DBus IPC directly, bypassing the /etc/resolv.conf bind-mount overlay | Outbound DNS queries originating from the systemd-resolved daemon process are intercepted by the TTP NAT output firewall rules and forced through Tor's DNSPort on loopback. | Low. Intercepting outbound port 53 traffic from resolved guarantees DBus bypass queries are still Tor-resolved. |
| resolved fallback DNS servers leak | Information Disclosure | resolved falls back to compiled-in Google/Cloudflare DNS servers, bypassing Tor | All outbound cleartext DNS queries (UDP/TCP port 53) are strictly intercepted by nftables. Direct WAN DNS queries are dropped/rejected. | Low. Fail-closed firewall ensures no fallback queries escape in cleartext. |
systemd-resolved Interaction Matrix
| systemd-resolved State | Resolv.conf Configuration | TTP Action & Mitigation | Risk Level |
|---|---|---|---|
| Active (Stub Mode) | Symlink to /run/systemd/resolve/stub-resolv.conf (pointing to 127.0.0.53). | TTP applies bind-mount overlay to the target file. systemd-resolved's stub listener queries are hijacked by TTP firewall rules and redirected to Tor DNSPort. | Low. DNS queries to 127.0.0.53 are securely forced into Tor. |
| Active (Static Mode) | Symlink to /lib/systemd/resolv.conf or /usr/lib/... | TTP resolves realpath and bind-mounts. Outgoing queries to external DNS servers are blocked by nftables filter drop rules. | Low. Fail-closed firewall blocks leaks. |
| Inactive | Static file (managed by NetworkManager/dhclient). | TTP bind-mounts directly on /etc/resolv.conf. | Low. Overlay mount forces nameserver 127.0.0.1. |
| Resolved DBus Query Bypass | Direct DBus IPC from applications (e.g. systemd-resolved API). | resolved query is processed by systemd-resolved daemon, which attempts upstream DNS resolution. The upstream query is intercepted by TTP nftables output rules and redirected to Tor DNSPort. | Low. NAT redirection catches outbound DNS queries on port 53. |
3.9 cli.py — Entry Point & Privilege Escalation
| Threat | STRIDE Category | Description | Mitigation | Residual Risk |
|---|---|---|---|---|
ttp binary replaced with malicious version | Tampering | An attacker replaces the ttp binary installed in /usr/local/bin/ | Release artifacts are signed via Sigstore; native packages use OS package manager signature verification | Low. Requires root or write access to installation path. |
Argument injection via --bypass-user | Elevation of Privilege | Malicious input in --bypass-user could be passed to shell commands | User/group names are resolved via Python's pwd/grp libraries to numeric UIDs/GIDs before use; no shell interpolation | Low. Mitigated by library-level resolution. |
| Python dependency compromise | Tampering | A compromised version of typer, stem, or rich is installed | Dependabot monitors for CVEs; pip-audit --path . is part of the security workflow | Medium. Inherent supply-chain risk for any Python application. |
4. Known Limitations & Residual Risks
This section documents risks that are by design, inherent to Tor, or out of scope for TTP to mitigate.
Caution
If you are a whistleblower, journalist, or person at high personal risk, do not rely on TTP alone. Use Tails OS or the official Tor Browser instead.
| Risk | Severity | Description | User Mitigation |
|---|---|---|---|
| Malicious Tor exit node | High | Exit nodes can read unencrypted traffic (HTTP, SMTP, etc.) | Always use HTTPS/TLS at the application layer |
| Browser-level DNS-over-HTTPS | Medium | Normal browsers may bypass system DNS via DoH (port 443). TTP routes unlisted DoH through Tor, but it compromises anonymity. | Disable "Secure DNS" in browser settings for all standard browsers |
| Double Tor hop (Tor Browser) | Low/Medium | Using Tor Browser while TTP is active creates a double-hop that degrades anonymity | Use a standard browser (Firefox) while TTP is active |
| Application-level identifier leaks | High | Cookies, browser fingerprint, logged-in accounts, and WebRTC can deanonymize you regardless of IP routing | Use a fresh browser profile; avoid logging into personal accounts |
| IPv6 loopback unsupported | Low/Medium | If IPv6 loopback is unsupported by the host OS, IPv6 connectivity is lost since TTP drops all IPv6 to prevent leaks | Ensure the host kernel supports IPv6 loopback for full dual-stack routing |
| Kernel network namespace bypass | High | Applications using their own network namespaces (e.g., Docker containers, VMs) bypass nftables entirely | Out of scope; TTP only controls the host network namespace |
| Timing correlation attacks | High | A global passive adversary can correlate entry/exit traffic timing to deanonymize users | Inherent Tor limitation; not addressable by TTP |
| Physical access / kernel-level rootkit | Critical | If the host OS is compromised at the kernel level, no user-space tool can provide security guarantees | Use full disk encryption; operate from a live OS (Tails) for high-risk scenarios |
4.1 Toggleable Proxy Model vs. Whonix Gateway/Workstation Compartmentalization
TTP runs as a local transparent proxy on the host, meaning it can be toggled on and off at runtime. This introduces fundamental design differences and increased risks compared to dedicated gateway architectures like Whonix:
-
Lack of Physical/Virtual Isolation: In Whonix, the workstation VM is completely isolated and has no physical network path to the WAN; its only network interface connects to the gateway VM, which forces all traffic through Tor. Under TTP, everything runs in the same host namespace. If the TTP firewall or service fails, or if a user-space application bypasses the routing rules (e.g. via specific namespaces, custom routing tables, or raw socket creation by privileged processes), cleartext leaks can occur.
-
Transition and Toggle Leak Risks: Since TTP is toggleable, active connections, sockets, and local caches (such as DNS) exist before
ttp startand afterttp stop. Applications may establish cleartext sessions that survive TTP's initialization, or leak packets during startup/shutdown phases before rulesets are atomically committed. -
No Defense-in-Depth against Root Compromise: If a host running TTP is compromised, root processes can easily disable nftables, bypass UID/GID exemptions, or read memory directly. In a segmented Gateway/Workstation model, compromising the Workstation VM does not compromise the Gateway's routing integrity.
4.2 Leak Testing Requirements (Zero-Leak Assertions)
TTP's Network Sandbox Engine (NSE) test suite programmatically validates the firewall ruleset against leaks. The testing requirements are modeled after official industry leak-testing protocols:
- Whonix Dev Leak Tests: Ref. Whonix Dev/Leak Tests Wiki
- Tor Project Wiki Leak Tests: Ref. Tor Project Torify Leak Testing
The NSE environment asserts at the link layer that:
- No TCP/UDP packets escape the WAN interface except those generated by the Tor daemon user (UID) or explicit cgroup bypasses.
- All DNS traffic is intercepted and redirected to Tor's DNSPort, with zero cleartext DNS queries escaping to standard nameservers.
- No IPv6 traffic escapes to the WAN if IPv6 routing is disabled or unsupported.
4.3 Lifecycle Transitions: What Is Measured and What Is Not
Every containment assertion in TTP's suite is about a steady state: a ruleset is loaded into a namespace, a packet is fired, and its absence on the wire is asserted. The leaks that happen to real users are in the transitions — the seconds in which the ruleset, the DNS overlay, the Tor process and the lock file are not all in the same state. This section says which transitions are measured, so that the ones that are not cannot be mistaken for the ones that are.
Measured. The third column matters as much as the second: two of these run on every commit and two do not, and a reader should not have to guess which.
| Transition | What is asserted | Where it runs |
|---|---|---|
| The teardown lockdown window | apply_teardown_lockdown() closes the LAN/bypass traffic that TTP otherwise permits, and still exempts the Tor UID — which do_stop needs, because it applies the lockdown before asking Tor to close its circuits. | tests/test_nse_rules.py, on the wire, in CI on every commit |
| A completed teardown | destroy_rules() leaves no inet ttp table behind and the host reaches the WAN again. A teardown that strands the lockdown rule would remove the user's network with no session left to explain it. | Same |
ttp start failing mid-sequence | The four rollback branches in ttp/commands/start.py each unwind a different amount of state. | Unit tests, in CI on every commit. Not on the wire |
| A live session under tampering | tests/chaos_monkey.py sweeps six faults against a running session — Tor stopped, Tor SIGKILLed behind systemd's back, table flushed, table destroyed, resolv.conf unmounted, link flapped — auditing containment after each. | make chaos-monkey, manual, not in CI. Needs a runner that can survive losing its own network |
Measured in a VM. scripts/vm/lifecycle/run.sh boots a disposable Debian 13
guest under QEMU and records every packet it sends with QEMU's filter-dump, outside
the guest and below TTP's own firewall. A probe inside the guest, running as an
ordinary non-bypassed user, keeps trying to reach 198.51.100.7 (TEST-NET-2, never a
Tor relay) over UDP/53 and TCP/80. A packet to that address in a capture is a leak,
and a capture with TTP stopped must contain the probe or the run is void. It runs in
.github/workflows/lifecycle.yml when the firewall, lifecycle or DNS code changes,
weekly, and on demand.
| Transition | What is asserted | Result |
|---|---|---|
| Shutdown with an active session | No probe packet from systemctl poweroff until the VM is off. | Holds: the network goes down while TTP's rules are still loaded. |
| Suspend/resume onto a new network | After S3 suspend, wake, and a move to a different subnet (new NIC, new lease), no probe packet, and the session is still ACTIVE. | Holds: rules, DNS overlay and Tor survive; Tor rebuilds circuits. |
| Reboot with an active session | The host comes back in one defined state, not half a session. | The session ends: no table, no overlay, no /run/ttp, ttp status says INACTIVE, and the host is in cleartext from the first minute (DNS and NTP in the capture). |
The reboot row is a statement of behaviour, not a pass: a TTP session is volatile by
design and nothing restores it at boot. An operator who reboots is unprotected until
they run ttp start again. The suite checks that this is what happens, so the day it
changes, it changes on purpose.
A mutant that exempts the probe's user from nat output and filter_out fails all
three containment checks, so the suite can go red.
Still not measured. The chaos sweep is not yet run inside the VM, so it remains a manual gate. Shutdown and reboot are measured on Debian with systemd-networkd only, not under NetworkManager. Tracked in #30.
5. Supply Chain Security
5.1 Release Artifact Integrity
All TTP release artifacts (.deb, .rpm, .whl, .tar.gz) are signed using Sigstore (keyless signing via GitHub Actions OIDC). Signatures can be verified with:
cosign verify-blob \
--bundle <artifact>.sigstore.json \
--certificate-identity "https://github.com/onyks-os/TransparentTorProxy/.github/workflows/release.yml@refs/tags/<tag>" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
<artifact>
The release workflow runs on tag pushes, so the certificate identity is bound to
refs/tags/<tag>, never to a branch. See verification.md for the
full procedure.
5.2 Dependency Monitoring
Dependency CVE scanning, Dependabot configuration, and the remediation SLA are documented in the authoritative source:
DEPENDENCIES.md § 2.3 — Vulnerability Monitoring & Remediation
5.3 Trusted Code Paths
- All commits to
mainrequire a Pull Request with maintainer review. - Security-critical files (
ttp/firewall/,dns.py,tor_control.py,selinux.py,watchdog/,.github/workflows/) require explicit sign-off from the Project Lead (see MAINTAINERS.md). - All commits must include a
Signed-off-byheader (DCO) — see CONTRIBUTING.md.
6. Security Controls Summary
| Control | Type | Status |
|---|---|---|
| Atomic nftables rule loading | Preventive | ✅ Implemented |
| Kill-switch (reject all on failure) | Preventive | ✅ Implemented |
| IPv6 routing or fallback blocking | Preventive | ✅ Implemented |
| DoT (port 853) blocking | Preventive | ✅ Implemented |
DoH canary domain mitigation (torrc MapAddress) | Preventive | ✅ Implemented (best-effort) |
| DoH TCP+QUIC IP blocking (nftables, port 443) | Preventive | ✅ Implemented (v0.4.7) |
| Teardown outbound traffic lockdown | Preventive | ✅ Implemented |
| Conntrack table flush during teardown | Preventive | ✅ Implemented |
| DNS bind-mount overlay (no disk writes) | Preventive | ✅ Implemented |
| Volatile runtime (tmpfs, zero persistent configuration residue) | Preventive | ✅ Implemented |
| Cookie-authenticated Tor control socket | Preventive | ✅ Implemented |
| Session watchdog with auto-healing | Detective + Corrective | ✅ Implemented (optional) |
| Emergency killswitch (two-strike policy) | Corrective | ✅ Implemented |
| Crash recovery (orphaned lock detection) | Corrective | ✅ Implemented |
| Sigstore artifact signing | Preventive | ✅ Implemented |
| Dependabot CVE monitoring | Detective | ✅ Enabled |
pip-audit scoped to project | Detective | ✅ Documented |
| DCO commit sign-off | Preventive | ✅ Required |
| PR review for security-critical files | Preventive | ✅ Policy (MAINTAINERS.md) |
7. Out of Scope
The following threats are explicitly out of scope for TTP's security model:
- Anonymity against a global passive adversary (timing attacks, traffic analysis at internet scale)
- Security of the Tor network itself (malicious relays, Tor protocol vulnerabilities)
- Application-layer deanonymization (browser fingerprinting, cookie tracking, WebRTC leaks)
- Host OS compromise (kernel rootkits, malicious hardware, physical access attacks)
- Non-host network namespaces (Docker, LXC, VMs running on the same host)
- User behavioral deanonymization (logging into personal accounts, metadata in documents)
- Protection across a reboot, or from boot. A session lives in
/runand ends with the machine; TTP has no start-at-boot mode. After a reboot the host is in cleartext untilttp startis run again - measured in section 4.3, not assumed.