CWE-291 describes a product that uses an IP address as its authentication check. If the request comes from an address on the list, the caller is trusted. No password, no certificate, no token.
It shows up in admin panels that only allow "the office range", in internal APIs that trust "anything on the private network", and in embedded and industrial devices that keep an allowlist of peers. Anyone who owns a service like that has a stake in this one.
How it happens
The reasoning is understandable. An address feels like a fact about the caller. It arrives with every packet, it costs nothing to check, and it is easy to put in a config file.
The trouble is that the address is only a claim. MITRE notes that attackers can forge the source IP address of the packets they send. The reply goes to the forged address, so the attacker normally has to be able to see that traffic. To do that they try to sit on the same subnet as the victim, or they use source routing, which MITRE says is disabled across much of the Internet today.
That sounds like a high bar until you remember what many flat internal networks look like. If one laptop, one camera or one compromised container on the right segment can reach the service, the "network location" check has stopped meaning anything.
A vulnerable pattern in Python with Flask:
# Vulnerable: the caller's address is the only credential
ALLOWED = {"10.0.0.5", "10.0.0.6"}
@app.route("/admin/export")
def export():
if request.remote_addr not in ALLOWED:
abort(403)
return dump_everything()
What an attacker gains
The record's consequence is plain: malicious users can fake authentication information, impersonating any IP address. That covers access control, because they get in, and non-repudiation, because logs now say the trusted host did it. It also lets them hide their activity behind someone else's address.
The one observed example is CVE-2022-30319, where S-bus functionality in a home automation product performed access control using an IP allowlist that could be bypassed with a forged address.
How to find it
The MITRE record lists no formal detection methods for this weakness, so the checks are simple and manual:
- Search code and config for allowlists keyed on
remote_addr,REMOTE_ADDR, client IP, or CIDR ranges used in an "if allowed, skip login" branch. - Ask of every endpoint: if I removed the network restriction, would anything still stop an anonymous caller?
- From a different host on the same network segment, try the call. If it works with no credential, the address is doing all the work.
How to fix it
MITRE's mitigation is short and correct: use other means of identity verification that cannot be simply spoofed, such as a username and password or a certificate.
- Require a real credential on every sensitive call: a session, an API token, or a client certificate.
- Keep the address check if you like, but as one layer on top. MITRE says IP verification can be a useful part of an authentication scheme, just not the only factor.
- Log the authenticated identity, not only the address, so the audit trail does not depend on a forgeable value.
# Better: identity is proven, the address is only a hint
@app.route("/admin/export")
@require_token(scope="admin:export")
def export():
return dump_everything()
Quick check
Is an IP allowlist ever acceptable?
As an extra layer, yes. MITRE says IP verification can be part of an authentication scheme, but it should not be the single factor required.
Why does spoofing matter if the attacker cannot see the replies?
They often can. MITRE explains that attackers try to place themselves on the victim's subnet so they can sniff the traffic, or use source routing where it is still enabled.