swisskyrepo/PayloadsAllTheThings · error · Exception

value not found

Error message

value not found

What it means

plain2EnclosedAlphanumericsChar(s0) in ip.py raises Exception('value not found') when s0 is not a key of EnclosedAlphanumericsData — the table that maps plain characters to Unicode Enclosed Alphanumerics (⓪-⑳, circled a-f/x, and fullwidth dots). It is a strict lookup with no fallback: every digit string, letter, or separator passed in must already exist in the table (keys are '0'-'9', '10'-'20', '.', and 'a'-'f','x'). The function backs convertIP2EnclosedAlphanumericsValue(), which rewrites each dot-separated piece of the user-supplied IP argument into circled-character form for SSRF filter-bypass testing.

Source

Thrown at Server Side Request Forgery/Files/ip.py:92

def DEC_OVERFLOW_SINGLE(NUMBER):
	return str(int(NUMBER)+256)

def validIP(address):
	parts = address.split(".")
	if len(parts) != 4:
		return False
	try:
		for item in parts:
			if not 0 <= int(item) <= 255:
				return False
	except ValueError:
		print("\nUsage: python "+sys.argv[0]+" IP EXPORT(optional)\nUsage: python "+sys.argv[0]+" 169.254.169.254\nUsage: python "+sys.argv[0]+" 169.254.169.254 export")
		exit(1)
	return True

def plain2EnclosedAlphanumericsChar(s0):
	if s0 not in EnclosedAlphanumericsData:
		raise Exception('value not found')
	return random.choice(EnclosedAlphanumericsData[s0])

def convertIP2EnclosedAlphanumericsValue():
	IPAddressParts4EnclosedAlphanumerics = arg1.split(".")
	returnEnclosedAlphanumericsIPAddress = ""
	for x in range(0,4):
		if len(IPAddressParts4EnclosedAlphanumerics[x]) == 3 and (int(IPAddressParts4EnclosedAlphanumerics[x][0]+IPAddressParts4EnclosedAlphanumerics[x][1])) <= 20 and (int(IPAddressParts4EnclosedAlphanumerics[x][0]+IPAddressParts4EnclosedAlphanumerics[x][1]+IPAddressParts4EnclosedAlphanumerics[x][2])) >= 10:
			returnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar(IPAddressParts4EnclosedAlphanumerics[x][0]+IPAddressParts4EnclosedAlphanumerics[x][1]);
			returnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar(IPAddressParts4EnclosedAlphanumerics[x][2]);
			if x <= 2:
				returnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar('.');
		else:
			returnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar(IPAddressParts4EnclosedAlphanumerics[x][0]);
			if len(IPAddressParts4EnclosedAlphanumerics[x]) >= 2:
				returnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar(IPAddressParts4EnclosedAlphanumerics[x][1]);
			if len(IPAddressParts4EnclosedAlphanumerics[x]) == 3:
				returnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar(IPAddressParts4EnclosedAlphanumerics[x][2]);
			if x <= 2:

View on GitHub (pinned to 3bff425aca)

Solutions

  1. Normalize the argument before conversion: strip leading zeros from each octet (use str(int(part)) for pure-digit parts) so lookups hit the '0'-'9'/'10'-'20' keys.
  2. Validate the input up front with validIP(arg1) and exit with the usage message instead of letting the table lookup explode mid-conversion.
  3. If you must support other characters, extend EnclosedAlphanumericsData with the missing keys (e.g. '00'-'09' mapped to ⓪①…⑨ compositions) rather than calling the strict lookup.
  4. Replace the raise with a passthrough (return s0) or route through convert(s, error_on_miss=False) from line 114, which already returns unknown input unchanged.

Example fix

# before
def plain2EnclosedAlphanumericsChar(s0):
	if s0 not in EnclosedAlphanumericsData:
		raise Exception('value not found')
	return random.choice(EnclosedAlphanumericsData[s0])

# after (normalize zero-padded pairs, pass through unknown chars)
def plain2EnclosedAlphanumericsChar(s0):
	if s0 not in EnclosedAlphanumericsData and s0.isdigit():
		s0 = str(int(s0))          # '09' -> '9'
	if s0 not in EnclosedAlphanumericsData:
		raise Exception('value not found')
	return random.choice(EnclosedAlphanumericsData[s0])
Defensive patterns

Strategy: validation

Validate before calling

# Normalize + validate the IP argument before enclosed-alphanumerics conversion
parts = arg1.split('.')
if len(parts) != 4 or not all(p.isdigit() and 0 <= int(p) <= 255 for p in parts):
    print('Usage: python %s IP EXPORT(optional) — plain dotted-quad only' % sys.argv[0])
    exit(1)
parts = [str(int(p)) for p in parts]          # strip leading zeros: '019' -> '19'
arg1 = '.'.join(parts)

Type guard

def encodable_octet(part):
    """True when every lookup key needed for this octet exists in the table."""
    keys = set(EnclosedAlphanumericsData)
    if (len(part) == 3 and int(part[0] + part[1]) <= 20
            and int(part) >= 10):
        return (part[0] + part[1]) in keys and part[2] in keys
    return all(ch in keys for ch in part)

Try / catch

try:
    enc = plain2EnclosedAlphanumericsChar(s0)
except Exception as e:
    if 'value not found' in str(e):
        # not representable in Enclosed Alphanumerics — skip this mutation
        enc = s0
    else:
        raise

Prevention

When it happens

Trigger: Passing an IP octet with a leading zero and three digits, e.g. '019' or '009': the len==3 branch computes int(part[0]+part[1]) = 9 (<= 20) and int(full) >= 10, then calls plain2EnclosedAlphanumericsChar('09') — '09' is not a table key (keys have no leading zeros), so it raises. Passing input that is not a dotted-quad of bare digits, e.g. hex octets with letters outside a-f/x ('0x9g...'), uppercase letters, IPv6 colons, or hostname characters; any resulting character or two-digit pair not in EnclosedAlphanumericsData triggers the raise.

Common situations: Running the tool with zero-padded octets (some environments/CLI habit zero-pad, like 169.254.169.254 typed as 169.254.0169.254); feeding alternative IP notations (hex/octal/decimal-overflow forms the same script generates) into the enclosed-alphanumerics converter, which only understands digit pairs 10-20 and single digits; copying an IP with stray characters or a hostname where an octet is expected.

Related errors


AI-assisted analysis of swisskyrepo/PayloadsAllTheThings@3bff425aca (2026-08-14). Data as JSON: /api/errors/adf22992f95187ef. Report an issue: GitHub.