)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"aa188755f74ef2e08b05d85974571268ec67f053","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"377f44c4_89047007","updated":"2026-03-19 14:38:04.000000000","message":"Pre-reviewed in the security bug while private","commit_id":"351e843083673c99ffb8cb4708c39aef9186d8d2"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"36413a6bbc4a5ae862d4d394cf6501e966babc8e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"cd7ad903_25b5b733","updated":"2026-03-20 11:37:13.000000000","message":"Few questions inline","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":5314,"name":"Brian Rosmaita","email":"rosmaita.fossdev@gmail.com","username":"brian-rosmaita"},"change_message_id":"6965be5254d3c9786e7bf2bca3324ac42c6d4fec","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"15d553f3_e50018ba","updated":"2026-03-20 14:22:38.000000000","message":"I think Abhishek has answered Rajat\u0027s questions; the exception narrowing can be done in a followup if appropriate","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"a122af1ca9b1ab4ad328609b51fff5414d8e3f1a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"1ed5112c_fbaaff7b","updated":"2026-03-20 13:10:24.000000000","message":"Thank you for review Rajat, I have added inline response for your comments.","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"99efbea0f35bd5ca77d76636650bee6f7ed4a730","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"d73357c0_a847ef2c","updated":"2026-03-20 14:23:38.000000000","message":"can take another review later but my current questions are answered so removing -1. Thanks Abhishek!","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"8954532f32ecfea2dc4ee77bf9eaf4adce651454","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"4d8c0940_b7dcf7c2","updated":"2026-03-20 16:55:21.000000000","message":"recheck unrelated timeout","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"}],"glance/common/utils.py":[{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"36413a6bbc4a5ae862d4d394cf6501e966babc8e","unresolved":true,"context_lines":[{"line_number":145,"context_line":"    # decimal (2130706433), hex (0x7f000001), or octal (017700000001)."},{"line_number":146,"context_line":"    try:"},{"line_number":147,"context_line":"        return str(ipaddress.IPv4Address(host))"},{"line_number":148,"context_line":"    except ValueError:"},{"line_number":149,"context_line":"        pass"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    # NOTE(abhishekk): Try to parse as IPv6. ipaddress module only accepts"}],"source_content_type":"text/x-python","patch_set":4,"id":"a4c47b54_7914f7a4","line":148,"range":{"start_line":148,"start_character":11,"end_line":148,"end_character":21},"updated":"2026-03-20 11:37:13.000000000","message":"ValueError seems to be the parent class but the actual error raised is AddressValueError, any reason why we don\u0027t use the specific error and instead use the generic ValueError here?","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"99efbea0f35bd5ca77d76636650bee6f7ed4a730","unresolved":false,"context_lines":[{"line_number":145,"context_line":"    # decimal (2130706433), hex (0x7f000001), or octal (017700000001)."},{"line_number":146,"context_line":"    try:"},{"line_number":147,"context_line":"        return str(ipaddress.IPv4Address(host))"},{"line_number":148,"context_line":"    except ValueError:"},{"line_number":149,"context_line":"        pass"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    # NOTE(abhishekk): Try to parse as IPv6. ipaddress module only accepts"}],"source_content_type":"text/x-python","patch_set":4,"id":"4c5996bc_4a6f9eb0","line":148,"range":{"start_line":148,"start_character":11,"end_line":148,"end_character":21},"in_reply_to":"8a303933_90315563","updated":"2026-03-20 14:23:38.000000000","message":"Acknowledged","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"a122af1ca9b1ab4ad328609b51fff5414d8e3f1a","unresolved":true,"context_lines":[{"line_number":145,"context_line":"    # decimal (2130706433), hex (0x7f000001), or octal (017700000001)."},{"line_number":146,"context_line":"    try:"},{"line_number":147,"context_line":"        return str(ipaddress.IPv4Address(host))"},{"line_number":148,"context_line":"    except ValueError:"},{"line_number":149,"context_line":"        pass"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    # NOTE(abhishekk): Try to parse as IPv6. ipaddress module only accepts"}],"source_content_type":"text/x-python","patch_set":4,"id":"8a303933_90315563","line":148,"range":{"start_line":148,"start_character":11,"end_line":148,"end_character":21},"in_reply_to":"a4c47b54_7914f7a4","updated":"2026-03-20 13:10:24.000000000","message":"NO specific reason, if you prefer to catch specific exception for clarity we can do it in followup.","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"36413a6bbc4a5ae862d4d394cf6501e966babc8e","unresolved":true,"context_lines":[{"line_number":146,"context_line":"    try:"},{"line_number":147,"context_line":"        return str(ipaddress.IPv4Address(host))"},{"line_number":148,"context_line":"    except ValueError:"},{"line_number":149,"context_line":"        pass"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    # NOTE(abhishekk): Try to parse as IPv6. ipaddress module only accepts"},{"line_number":152,"context_line":"    # standard IPv6 format and rejects encoded formats."}],"source_content_type":"text/x-python","patch_set":4,"id":"d5b1c9c3_f86ecc3b","line":149,"range":{"start_line":149,"start_character":8,"end_line":149,"end_character":12},"updated":"2026-03-20 11:37:13.000000000","message":"why don\u0027t we return here?","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"99efbea0f35bd5ca77d76636650bee6f7ed4a730","unresolved":false,"context_lines":[{"line_number":146,"context_line":"    try:"},{"line_number":147,"context_line":"        return str(ipaddress.IPv4Address(host))"},{"line_number":148,"context_line":"    except ValueError:"},{"line_number":149,"context_line":"        pass"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    # NOTE(abhishekk): Try to parse as IPv6. ipaddress module only accepts"},{"line_number":152,"context_line":"    # standard IPv6 format and rejects encoded formats."}],"source_content_type":"text/x-python","patch_set":4,"id":"6d721461_6c4995e6","line":149,"range":{"start_line":149,"start_character":8,"end_line":149,"end_character":12},"in_reply_to":"b68b8739_8fef1176","updated":"2026-03-20 14:23:38.000000000","message":"Ack, makes sense.\nSo the first series of checks are for IPv4 and IPv6 addresses and later checks are for domain names that are resolvable via DNS.","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"a122af1ca9b1ab4ad328609b51fff5414d8e3f1a","unresolved":true,"context_lines":[{"line_number":146,"context_line":"    try:"},{"line_number":147,"context_line":"        return str(ipaddress.IPv4Address(host))"},{"line_number":148,"context_line":"    except ValueError:"},{"line_number":149,"context_line":"        pass"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    # NOTE(abhishekk): Try to parse as IPv6. ipaddress module only accepts"},{"line_number":152,"context_line":"    # standard IPv6 format and rejects encoded formats."}],"source_content_type":"text/x-python","patch_set":4,"id":"b68b8739_8fef1176","line":149,"range":{"start_line":149,"start_character":8,"end_line":149,"end_character":12},"in_reply_to":"d5b1c9c3_f86ecc3b","updated":"2026-03-20 13:10:24.000000000","message":"Because this is not the end of the function.\n\nnormalize_hostname is a chain of attempts:\n\nTry IPv4 --\u003e on ValueError / invalid IPv4, keep going.\nTry IPv6 --\u003e same idea if that fails.\nThen apply hostname rules (digits-only, dotted-numeric, DNS with trailing dot, etc.).\n\nIf you return in that except block, you’d have to return something fixed (e.g. None or host), which would skip the IPv6 and hostname paths and break correct behavior for valid IPv6 strings and real hostnames.\n\nSo pass is intentional: “not IPv4 in canonical form; try the next branch.","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"36413a6bbc4a5ae862d4d394cf6501e966babc8e","unresolved":true,"context_lines":[{"line_number":165,"context_line":"    # \"10.1\". These are shorthand IP addresses. ipaddress module rejects them"},{"line_number":166,"context_line":"    # because they need 4 octets, but OS may still resolve them. We block to"},{"line_number":167,"context_line":"    # prevent SSRF bypass attacks."},{"line_number":168,"context_line":"    if all(c.isdigit() or c \u003d\u003d \u0027.\u0027 for c in host):"},{"line_number":169,"context_line":"        return None"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"    # NOTE(abhishekk): Add trailing dot to force DNS lookup instead of numeric"},{"line_number":172,"context_line":"    # parsing. This blocks encoded IP formats like 0x7f000001 or 127.0x0.0.1"}],"source_content_type":"text/x-python","patch_set":4,"id":"8dea1172_d3d1c0fa","line":169,"range":{"start_line":168,"start_character":4,"end_line":169,"end_character":19},"updated":"2026-03-20 11:37:13.000000000","message":"I\u0027m not sure if I\u0027m missing anything here but for a valid host like 127.0.0.1, this evaluates to True and we will return None which is incorrect behavior right?\n\n    \u003e\u003e\u003e host \u003d \"127.0.0.1\"\n    \u003e\u003e\u003e all(c.isdigit() or c \u003d\u003d \u0027.\u0027 for c in host)","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"a122af1ca9b1ab4ad328609b51fff5414d8e3f1a","unresolved":true,"context_lines":[{"line_number":165,"context_line":"    # \"10.1\". These are shorthand IP addresses. ipaddress module rejects them"},{"line_number":166,"context_line":"    # because they need 4 octets, but OS may still resolve them. We block to"},{"line_number":167,"context_line":"    # prevent SSRF bypass attacks."},{"line_number":168,"context_line":"    if all(c.isdigit() or c \u003d\u003d \u0027.\u0027 for c in host):"},{"line_number":169,"context_line":"        return None"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"    # NOTE(abhishekk): Add trailing dot to force DNS lookup instead of numeric"},{"line_number":172,"context_line":"    # parsing. This blocks encoded IP formats like 0x7f000001 or 127.0x0.0.1"}],"source_content_type":"text/x-python","patch_set":4,"id":"c7c0bc39_fd229f69","line":169,"range":{"start_line":168,"start_character":4,"end_line":169,"end_character":19},"in_reply_to":"8dea1172_d3d1c0fa","updated":"2026-03-20 13:10:24.000000000","message":"\"127.0.0.1\" is accepted earlier by line 147;\n\n    return str(ipaddress.IPv4Address(host))","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"99efbea0f35bd5ca77d76636650bee6f7ed4a730","unresolved":false,"context_lines":[{"line_number":165,"context_line":"    # \"10.1\". These are shorthand IP addresses. ipaddress module rejects them"},{"line_number":166,"context_line":"    # because they need 4 octets, but OS may still resolve them. We block to"},{"line_number":167,"context_line":"    # prevent SSRF bypass attacks."},{"line_number":168,"context_line":"    if all(c.isdigit() or c \u003d\u003d \u0027.\u0027 for c in host):"},{"line_number":169,"context_line":"        return None"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"    # NOTE(abhishekk): Add trailing dot to force DNS lookup instead of numeric"},{"line_number":172,"context_line":"    # parsing. This blocks encoded IP formats like 0x7f000001 or 127.0x0.0.1"}],"source_content_type":"text/x-python","patch_set":4,"id":"7a90e380_f3264711","line":169,"range":{"start_line":168,"start_character":4,"end_line":169,"end_character":19},"in_reply_to":"c7c0bc39_fd229f69","updated":"2026-03-20 14:23:38.000000000","message":"Acknowledged","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"36413a6bbc4a5ae862d4d394cf6501e966babc8e","unresolved":true,"context_lines":[{"line_number":177,"context_line":"        testhost +\u003d \u0027.\u0027"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":"    try:"},{"line_number":180,"context_line":"        socket.getaddrinfo(testhost, 80)"},{"line_number":181,"context_line":"    except socket.gaierror:"},{"line_number":182,"context_line":"        # NOTE(abhishekk): DNS resolution failed, reject the hostname"},{"line_number":183,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":4,"id":"60b1da42_a9b9d38a","line":180,"range":{"start_line":180,"start_character":8,"end_line":180,"end_character":40},"updated":"2026-03-20 11:37:13.000000000","message":"after adding the \u0027.\u0027 in the end (as stated above) this seems to fail?\n\n\n    \u003e\u003e\u003e host\n\t\u0027127.0.0.1\u0027\n\t\u003e\u003e\u003e testhost\n\t\u0027127.0.0.1.\u0027\n\t\u003e\u003e\u003e socket.getaddrinfo(host, 80)\n\t[(\u003cAddressFamily.AF_INET: 2\u003e, \u003cSocketKind.SOCK_STREAM: 1\u003e, 6, \u0027\u0027, (\u0027127.0.0.1\u0027, 80)), (\u003cAddressFamily.AF_INET: 2\u003e, \u003cSocketKind.SOCK_DGRAM: 2\u003e, 17, \u0027\u0027, (\u0027127.0.0.1\u0027, 80)), (\u003cAddressFamily.AF_INET: 2\u003e, \u003cSocketKind.SOCK_RAW: 3\u003e, 0, \u0027\u0027, (\u0027127.0.0.1\u0027, 80))]\n\t\u003e\u003e\u003e socket.getaddrinfo(testhost, 80)\n\tTraceback (most recent call last):\n\t  File \"\u003cpython-input-36\u003e\", line 1, in \u003cmodule\u003e\n\t    socket.getaddrinfo(testhost, 80)\n\t    ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^\n\t  File \"/usr/lib64/python3.13/socket.py\", line 977, in getaddrinfo\n\t    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"99efbea0f35bd5ca77d76636650bee6f7ed4a730","unresolved":false,"context_lines":[{"line_number":177,"context_line":"        testhost +\u003d \u0027.\u0027"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":"    try:"},{"line_number":180,"context_line":"        socket.getaddrinfo(testhost, 80)"},{"line_number":181,"context_line":"    except socket.gaierror:"},{"line_number":182,"context_line":"        # NOTE(abhishekk): DNS resolution failed, reject the hostname"},{"line_number":183,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":4,"id":"c9a75019_bdc3b92c","line":180,"range":{"start_line":180,"start_character":8,"end_line":180,"end_character":40},"in_reply_to":"58df92d4_54196ffd","updated":"2026-03-20 14:23:38.000000000","message":"Acknowledged\nThis works\n\n\t\u003e\u003e\u003e host\n\t\u0027google.com\u0027\n\t\u003e\u003e\u003e testhost\n\t\u0027google.com.\u0027\n\t\u003e\u003e\u003e socket.getaddrinfo(host, 80)\n\t[(\u003cAddressFamily.AF_INET6: 10\u003e, \u003cSocketKind.SOCK_STREAM: 1\u003e, 6, \u0027\u0027, (\u00272404:6800:4003:c00::64\u0027, 80, 0, 0)), (\u003cAddressFamily.AF_INET6: 10\u003e, \n\t...\n\t\u003e\u003e\u003e socket.getaddrinfo(testhost, 80)\n\t[(\u003cAddressFamily.AF_INET6: 10\u003e, \u003cSocketKind.SOCK_STREAM: 1\u003e, 6, \u0027\u0027, (\u00272404:6800:4003:c00::8b\u0027, 80, 0, 0)), (\u003cAddressFamily.AF_INET6: 10\u003e, \u003cSocketKind.SOCK_DGRAM: 2\u003e, 17, \u0027\u0027, (\u00272404:6800:4003:c00::8b\u0027, 80, 0, 0)), (\u003cAddressFamily.AF_INET6: 10\u003e, \u003cSocketKind.SOCK_RAW: 3\u003e, 0, \u0027\u0027, \n     ...","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"a122af1ca9b1ab4ad328609b51fff5414d8e3f1a","unresolved":true,"context_lines":[{"line_number":177,"context_line":"        testhost +\u003d \u0027.\u0027"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":"    try:"},{"line_number":180,"context_line":"        socket.getaddrinfo(testhost, 80)"},{"line_number":181,"context_line":"    except socket.gaierror:"},{"line_number":182,"context_line":"        # NOTE(abhishekk): DNS resolution failed, reject the hostname"},{"line_number":183,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":4,"id":"58df92d4_54196ffd","line":180,"range":{"start_line":180,"start_character":8,"end_line":180,"end_character":40},"in_reply_to":"60b1da42_a9b9d38a","updated":"2026-03-20 13:10:24.000000000","message":"Valid dotted IPv4 is handled earlier via ipaddress.IPv4Address before we add . and call getaddrinfo. The trailing dot is for real hostnames (e.g. example.com), not those IPs.","commit_id":"8c43caaefd8820e3e45b3c95b60bc6e1c668c55b"}]}
