{"record":{"id":"bb914231576df1dc","repo":"swisskyrepo/PayloadsAllTheThings","slug":"value-not-found-s","errorCode":null,"errorMessage":"Value not found: %s","messagePattern":"Value not found: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"Server Side Request Forgery/Files/ip.py","lineNumber":120,"sourceCode":"\t\t\tif x <= 2:\n\t\t\t\treturnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar('.');\n\t\telse:\n\t\t\treturnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar(IPAddressParts4EnclosedAlphanumerics[x][0]);\n\t\t\tif len(IPAddressParts4EnclosedAlphanumerics[x]) >= 2:\n\t\t\t\treturnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar(IPAddressParts4EnclosedAlphanumerics[x][1]);\n\t\t\tif len(IPAddressParts4EnclosedAlphanumerics[x]) == 3:\n\t\t\t\treturnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar(IPAddressParts4EnclosedAlphanumerics[x][2]);\n\t\t\tif x <= 2:\n\t\t\t\treturnEnclosedAlphanumericsIPAddress = returnEnclosedAlphanumericsIPAddress + plain2EnclosedAlphanumericsChar('.');\n\treturn returnEnclosedAlphanumericsIPAddress\n\ndef convert(s, recurse_chunks=True, error_on_miss=False):\n\t\tif s in EnclosedAlphanumericsData:\n\t\t\treturn random.choice(EnclosedAlphanumericsData[s])\n\t\tif recurse_chunks and len(s) > 1:\n\t\t\treturn convert(s[:-1]) + convert(s[-1])\n\t\tif error_on_miss:\n\t\t\traise Exception('Value not found: %s' % s)\n\t\treturn s\n\ndef convert_ip(ip, sep='.'):\n\treturn convert(sep).join([convert(chunk) for chunk in ip.split(sep)])\n\nif len(sys.argv) < 4 or len(sys.argv) >= 6:\n\tprint(\"\\nUsage: python \"+sys.argv[0]+\" IP PORT WhiteListedDomain EXPORT(optional)\\nUsage: python \"+sys.argv[0]+\" 169.254.169.254 80 www.google.com\\nUsage: python \"+sys.argv[0]+\" 169.254.169.254 80 www.google.com export\")\n\texit(1)\n\nredcolor='\\x1b[0;31;40m'\ngreencolor='\\x1b[0;32;40m'\nyellowcolor='\\x1b[0;33;40m'\nbluecolor='\\x1b[0;36;40m'\nresetcolor='\\x1b[0m'\narg1 = str(sys.argv[1])\n\nif validIP(arg1) == False:\n\tprint(\"\\n\",yellowcolor,arg1,resetcolor,redcolor,\" is not a valid IPv4 address in dotted decimal format, example: 123.123.123.123\",resetcolor,sep='')","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/swisskyrepo/PayloadsAllTheThings/blob/3bff425aca2b020f7334f9d744eed3ca55de8cdf/Server Side Request Forgery/Files/ip.py#L102-L138","documentation":"convert(s, recurse_chunks=True, error_on_miss=False) in ip.py raises Exception('Value not found: %s' % s) only when error_on_miss is True and the string s (after recursive right-to-left splitting down to single characters) still has a bottom-level character absent from EnclosedAlphanumericsData. The table only covers '0'-'9', '10'-'20', '.', 'a'-'f', and 'x', so any other character — letters g-z, uppercase, ':', '-', whitespace — reaches the single-char base case, misses, and (with the flag set) raises. With the default error_on_miss=False the same input is silently returned unchanged, which is the designed fallback behavior.","triggerScenarios":"Calling convert() or convert_ip() with error_on_miss=True on input containing characters outside the table: a hostname like 'www.google.com' (w, g, o, l, m miss), an IPv6 address (':' misses), a hex IP with letters beyond a-f, or a malformed octet with stray characters. Conversely, plain IPv4 dotted-quads ('169.254.169.254' with default '.') always hit the digit/dot keys and never raise.","commonSituations":"Extending the SSRF testing script to convert whitelisted-domain strings or alternative notations and passing error_on_miss=True to surface bad data; refactoring call sites to reuse convert() for user-supplied strings (the earlier strict plain2EnclosedAlphanumericsChar at line 90 is the same idea without recursion); feeding locale/case variants (uppercase hex 0XA9) that the lowercase-only table cannot map.","solutions":["Call convert()/convert_ip() without error_on_miss (default False) when passthrough of unmappable characters is acceptable — that is the function's built-in fallback.","Pre-filter input to the supported alphabet (digits, '.', a-f, x) and reject or normalize everything else (lowercase hex, drop IPv6/hosts) before calling with error_on_miss=True.","Extend EnclosedAlphanumericsData with the missing glyphs (g-z circled equivalents) if coverage is genuinely required.","Catch the exception at the call site and log which substring failed (the message already names it via 'Value not found: %s') to pinpoint bad input."],"exampleFix":"# before\nconverted = convert(user_string, error_on_miss=True)   # raises on 'www.google.com'\n\n# after (validate charset, then convert with strict flag only for known-good input)\nSUPPORTED = set('0123456789.afx')\nif set(user_string.lower()) <= SUPPORTED | {'.'}:\n    converted = convert(user_string.lower(), error_on_miss=True)\nelse:\n    converted = convert(user_string)   # passthrough fallback for unmappable chars","handlingStrategy":"fallback","validationCode":"# Only strict-convert strings made of table-supported characters\nSUPPORTED = set('0123456789.fx') | {'.'}\ndef is_convertible(s):\n    return all(ch.lower() in SUPPORTED for ch in s)\n\nresult = convert(s, error_on_miss=is_convertible(s))  # strict only when safe","typeGuard":"def is_enclosed_convertible(s):\n    \"\"\"True when convert() can map every character without hitting the miss branch.\"\"\"\n    return all(ch in EnclosedAlphanumericsData or ch.lower() in EnclosedAlphanumericsData\n               for ch in s)","tryCatchPattern":"try:\n    out = convert(s, error_on_miss=True)\nexcept Exception as e:\n    msg = str(e)\n    if msg.startswith('Value not found:'):\n        missing = msg.split(':', 1)[1].strip()\n        out = s  # fallback: keep original text, optionally log `missing`\n    else:\n        raise","preventionTips":["Leave error_on_miss at its default False unless you truly need strict failures — passthrough is the intended fallback.","Constrain convert_ip() input to plain IPv4 digits and the chosen separator; hostnames and IPv6 are outside the table's alphabet.","Lowercase hex input before converting (the table has no uppercase keys).","When extending the script to new input classes, add the needed glyphs to EnclosedAlphanumericsData rather than assuming coverage."],"tags":["ssrf","unicode","lookup-table","recursion","input-validation","python"],"backgroundTag":null,"analyzedSha":"3bff425aca2b020f7334f9d744eed3ca55de8cdf","analyzedAt":"2026-08-14T19:57:51.590Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}