T07 · Tool Hijacking and Spoofing
- Location
scripts/fm_config.py:31- Finding
Execution of an Unverified Binary from a Predictable Temporary Directory
- Content
View full analysis
Vulnerability Details
File Location:
scripts/fm_config.py:31;scripts/fm_iq_pipeline.py:87-94, 151, 258-260
Vulnerability Type: Local tool hijacking through an unsafe temporary-directory fallback
Risk Level: HighVulnerable Code
scripts/fm_config.py:31:python DEFAULT_REDSEA_PATH = Path('/tmp/redsea/build/redsea')scripts/fm_iq_pipeline.py:87-94:python def resolve_redsea_bin() -> Path | None: redsea_in_path = shutil.which('redsea') if redsea_in_path: return Path(redsea_in_path) if DEFAULT_REDSEA_PATH.exists(): return DEFAULT_REDSEA_PATH return Nonescripts/fm_iq_pipeline.py:151:python redsea_probe = probe_tool([str(redsea_bin), '--help']) if redsea_bin is not None else {'available': False, 'probeMessage': 'Not found in PATH or fallback location'}scripts/fm_iq_pipeline.py:258-260:python proc = subprocess.Popen( [str(redsea_bin), '-r', '171000', '-p'],Technical Analysis
When
redseais unavailable throughPATH, the application falls back to the fixed path/tmp/redsea/build/redsea. The resolver verifies only that this path exists. It does not verify that the file:- Is a regular file rather than a symbolic link or another special file.
- Is owned by a trusted user.
- Has safe ownership and permission settings.
- Resides beneath directories that are not writable by untrusted users.
- Matches an expected cryptographic hash or trusted package.
- Remains unchanged between validation and execution.
/tmpis conventionally writable by local users. Although its sticky bit restricts deletion of entries belonging to other users, it does not prevent an attacker from creating a previously absent predictable directory hierarchy. If/tmp/redseadoes not already exist with secure ownership and permissions, an attacker can create the fallback path and place an executable there.The u ...[truncated 2268 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove the
/tmpfallback and requireredseato be installed through a trusted system package or in an explicitly configured, administrator-controlled location.python def resolve_redsea_bin() -> Path | None: candidate = shutil.which("redsea") return Path(candidate).resolve() if candidate else None -
If a fallback is operationally necessary, move it outside shared temporary storage, such as
/usr/local/bin/redseaor an application-owned directory with restrictive permissions. -
Before execution, validate the candidate and every parent directory:
- Resolve symbolic links with
Path.resolve(strict=True). - Require a regular executable file.
- Reject symbolic links.
- Require ownership by an expected trusted UID.
- Reject group-writable or world-writable files.
- Reject paths beneath group-writable or world-writable directories.
- Optionally verify a pinned SHA-256 digest or package signature.
- Resolve symbolic links with
-
Avoid time-of-check/time-of-use replacement between validation and execution. Where practical, open the verified executable with safe flags such as
O_NOFOLLOW, validate it withfstat(), and execute the same opened object through an appropriate platform mechanism. Otherwise, ensure the entire installation directory is protected against modification by untrusted users. -
Apply the same verification before both probe execution and normal RDS decoding. A
--helpprobe still executes the selected binary and must not be treated as harmless. -
Update the documentation to require a trusted, package-managed installation rather than recommending a binary under
/tmp.
-
