T05 · Unauthorized Access and Privilege Escalation
- Location
fluid_network/skills/inputs.py:153- Finding
Agent-Callable Analysis Tools Permit Unrestricted Local File Reads
- Content
View full analysis
Vulnerability Details
File Location:
fluid_network/skills/inputs.py:153-156;fluid_network/parser.py:133-137
Vulnerability Type: Missing filesystem sandbox and path authorization
Risk Level: MediumVulnerable Code
fluid_network/skills/inputs.py:153-156:python if looks_like_path(text): path = Path(text) if path.is_file(): network, scenarios = parser.load(path) return ResolvedNetwork(network, tuple(scenarios), "path", str(path))fluid_network/parser.py:133-137:python path = Path(path) if not path.exists(): raise ConfigError(f"配置文件不存在:{path}") try: raw_bytes = path.read_bytes()Technical Analysis
The
parse_network,analyze_scenario, andanalyze_all_scenariostools acceptnetwork_sourceas a string. When the string resembles a path and points to an existing file,resolve_network_source()passes it directly toFluidConfigParser.load(), which reads the entire file withPath.read_bytes().This path lacks all of the controls claimed by the documented security boundary:
- No approved-root or directory-containment check
- No canonical path validation
- No rejection of traversal paths
- No protection against symlinks escaping an approved directory
- No
.tomlextension restriction - No file-size limit
- No default-deny behavior when a sandbox is not configured
Consequently, any file readable by the Skill process can be supplied as
network_source. The parser may then expose information derived from that file through parsed network summaries or detailed syntax and validation diagnostics.The issue also creates a denial-of-service risk because
read_bytes()loads the complete target into memory without first enforcing the documented 256 KB limit.The SSH-key reference at
SKILL.md:484is only a deny-list example and does not itself read or write SSH keys. However, the unrestricted path handling means the implementation does not enforce that documented prohibition....[truncated 1487 chars]
- Remediation
View remediation
Remediation Suggestions
- Introduce one centralized file-access policy and require every file-reading entry point to use it.
- Resolve the requested path with strict canonicalization before reading:
python requested = Path(value).expanduser().resolve(strict=True) - Resolve configured allowed roots and verify containment using
Path.is_relative_to()rather than string-prefix comparisons:python if not any(requested.is_relative_to(root) for root in allowed_roots): raise PathNotAllowed(...) - Default to denying all path-based reads when no allowed roots are configured.
- Permit only the required
.tomlextension fornetwork_source. - Reject symlinks or ensure that the resolved target remains inside an allowed root.
- Inspect file metadata before reading and reject files over 256 KB. Also use bounded reads to reduce time-of-check/time-of-use risk.
- Avoid including file contents in parse errors. Return only sanitized locations and diagnostics.
- Apply the same controls to CLI JSON loading in
skill_runner.pyif the CLI may process attacker-controlled paths. - Add tests covering absolute paths,
../traversal, symlink escapes, sibling directories with matching prefixes, SSH-key paths, unsupported extensions, oversized files, and operation without configured roots. - Update the tool documentation to match the actual registered tool set, or implement the documented sandboxed
read_filetool without allowing analysis tools to bypass its policy.
