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
- 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.
- Validate the input up front with validIP(arg1) and exit with the usage message instead of letting the table lookup explode mid-conversion.
- 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.
- 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
- Never pass zero-padded octets; normalize with str(int(part)) first.
- Restrict input to plain dotted-quad IPv4 (validIP) before calling the enclosed-alphanumerics converter.
- Remember the table only covers digits, 10-20, '.', a-f, x — anything else is unrepresentable by design.
- Prefer convert(s, error_on_miss=False) at line 114 when a passthrough is acceptable.
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.