Safeguard
Application Security•

CWE-99 Resource Injection: Attacker-Chosen File and Port Names

Resource injection happens when input decides which file, port or other resource your code touches. CWE-99 explained with a fix.

Safeguard Security Team
3 min read

CWE-99, Improper Control of Resource Identifiers (Resource Injection), is a class level weakness. The product takes input from an upstream component and uses it as an identifier for a resource that may be outside the intended sphere of control, without restricting that input.

Think of any name your program accepts and then acts on: a filename, a port number, a socket path, a queue name, a config profile. If a user can influence that name, the program may reach something the author never intended.

How it happens

MITRE describes two conditions that must both be true. First, an attacker can specify the identifier used to access a system resource, for instance part of a filename to open or a port number to use. Second, by specifying the resource the attacker gains a capability they would not otherwise have, such as overwriting the file, running with an attacker controlled configuration, or sending sensitive information to a third party server.

# Vulnerable: the user picks the output file name
def save_report(name, data):
    with open("/var/reports/" + name, "w") as f:
        f.write(data)
# name = "../../etc/cron.d/job" reaches outside the reports folder

A related example from MITRE's observed list is CVE-2013-4787: a mobile OS verified the cryptographic signature of a file in an archive, then installed a different file with the same name that was also listed in the archive. The identifier, a file name, no longer pointed to the thing that had been checked.

What an attacker gains

MITRE lists confidentiality and integrity impact. The attacker can read or modify application data and read or modify files or directories, which may include protected files, directories and configuration files.

How to find it

MITRE says static analysis can find some instances by following data flow. Manually, list every API call that takes a name or number from outside: file open, socket connect, bind, database selection, queue or topic names. Trace each identifier to its source.

How to fix it

MITRE's mitigation is input validation using an accept known good strategy. Assume all input is malicious, define exactly which identifiers are valid, and reject everything else. Check length, type, range, syntax and business rules. Do not rely only on denylists, though they can help flag attacks.

import re
SAFE_NAME = re.compile(r"[a-z0-9_]{1,40}")

def save_report(name, data):
    if not SAFE_NAME.fullmatch(name):
        raise ValueError("invalid report name")
    with open("/var/reports/" + name + ".txt", "w") as f:
        f.write(data)

Better still, let the server generate the identifier and give the user an ID to refer to it later.

Quick check

Is resource injection only about files?

No. The identifier can be a port number, a socket, or any name used to reach a resource outside the intended scope.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.