T09 · Insecure Skill Coding Practices
- Location
funding_harvester.py:39- Finding
Predictable Temporary Output Path Allows Symlink-Based File Overwrite
- Content
View full analysis
Vulnerability Details
File Location:
funding_harvester.py, line 39 and lines 397–401
Vulnerability Type: Unsafe temporary-file handling and symbolic-link following
Risk Level: MediumVulnerable Code:
python # Output file path OUTPUT_PATH = "/tmp/funding_opportunities.json"python # 5. Save to output file try: with open(OUTPUT_PATH, "w") as f: json.dump(output, f, indent=2) log.info("Results saved to %s", OUTPUT_PATH) except OSError as e: log.error("Failed to write output file: %s", e)Technical Analysis
The program repeatedly writes to a fixed, predictable pathname in the shared
/tmpdirectory. Python'sopen(..., "w")follows symbolic links and truncates the resolved target before writing.On a multi-user system, an attacker with access to
/tmpmay create/tmp/funding_opportunities.jsonas a symbolic link to another file before the scheduled process opens it. The process does not verify that the destination is a regular file, reject symbolic links, useO_NOFOLLOW, or place the output inside a private directory.The feasibility and severity depend on operating-system protections, ownership of an existing output file, and the account under which the automaton runs. Protections such as
fs.protected_symlinksmay prevent some cross-user attacks, but the implementation should not rely exclusively on host-specific hardening.Attack Path
- The attacker obtains local access to the shared
/tmpnamespace. - The attacker waits until the expected output path is absent or otherwise gains the ability to replace that directory entry.
- The attacker creates a symbolic link:
text /tmp/funding_opportunities.json -> attacker-selected target - The scheduled automaton starts and calls
open(OUTPUT_PATH, "w"). - The operating system resolves the symbolic link, and the process truncates and writes generated JSON to the t ...[truncated 724 chars]
- The attacker obtains local access to the shared
- Remediation
View remediation
Remediation Suggestions
- Store output in an application-owned directory rather than the shared
/tmpnamespace. - Create that directory with restrictive permissions, such as mode
0700, and ensure it is owned by the automaton account. - Write to a securely created temporary file in the destination directory and publish it with an atomic
os.replace. - Where supported, open the final destination using
os.openwithO_NOFOLLOWand appropriate creation flags. - Verify with
lstatthat existing destination entries are regular files owned by the expected account; note that verification alone must be designed to avoid time-of-check/time-of-use races. - Run the automaton as a dedicated, unprivileged account with access only to its required output directory.
- Apply restrictive output permissions, such as mode
0600where other users do not need to read the results.
- Store output in an application-owned directory rather than the shared
