Skip to content

IndexError when parsing malformed SOCKS proxy string without colon separator #1214

@immortal71

Description

@immortal71

Bug Description

The SOCKS proxy parser in nettacker/core/socks_proxy.py crashes with an IndexError when users provide a malformed SOCKS proxy string containing @ but missing a : (colon) separator.

Location

File: nettacker/core/socks_proxy.py
Lines: 24-25
Function: set_socks_proxy()

Buggy Code

if "@" in socks_proxy:
    socks_username = socks_proxy.split(":")[0]
    socks_password = socks_proxy.split(":")[1].split("@")[0]  # IndexError!

Root Cause

The code assumes that if @ is present in the proxy string, there must also be a : separator for credentials (username:password@host:port). However, when a user provides input like:

  • user@hostname (no colon at all)
  • socks5://admin@server (missing port)

The split(":") returns a list with only 1 element, and accessing [1] raises IndexError.

How to Reproduce

Step 1: Create test script

from nettacker.core.socks_proxy import set_socks_proxy

# This will crash with IndexError
set_socks_proxy("user@proxyserver")

Step 2: Run the script

python test_socks_crash.py

Expected Result:

Clear error message like: "Invalid SOCKS proxy format. Expected: username:password@host:port"

Actual Result:

Traceback (most recent call last):
  File "test_socks_crash.py", line 4, in <module>
    set_socks_proxy("user@proxyserver")
  File "nettacker/core/socks_proxy.py", line 25, in set_socks_proxy
    socks_password = socks_proxy.split(":")[1].split("@")[0]
IndexError: list index out of range

Proof of Concept

I've created a standalone test script that demonstrates the bug:

#!/usr/bin/env python3
"""Demonstrates IndexError in socks_proxy.py"""

def buggy_code(socks_proxy):
    # Remove scheme if present
    socks_proxy = socks_proxy.split("://")[1] if "://" in socks_proxy else socks_proxy
    
    if "@" in socks_proxy:
        print(f"Parsing: {socks_proxy}")
        print(f"split(':') = {socks_proxy.split(':')}")
        
        socks_username = socks_proxy.split(":")[0]
        socks_password = socks_proxy.split(":")[1].split("@")[0]  # CRASH!
        
        return (socks_username, socks_password)

# Test cases
print("Test 1: Valid input")
try:
    result = buggy_code("user:pass@host:1080")
    print(f" Success: {result}\n")
except IndexError as e:
    print(f" IndexError: {e}\n")

print("Test 2: Missing colon (BUG)")
try:
    result = buggy_code("user@hostname")
    print(f" Success: {result}\n")
except IndexError as e:
    print(f" IndexError: {e}\n")

Output:

Test 1: Valid input
Parsing: user:pass@host:1080
split(':') = ['user', 'pass@host', '1080']
 Success: ('user', 'pass')

Test 2: Missing colon (BUG)
Parsing: user@hostname
split(':') = ['user@hostname']
 IndexError: list index out of range

Impact

Severity: Medium

  • User Experience: Application crashes with cryptic error instead of helpful validation message
  • Common Mistake: Users often forget the : when typing proxy credentials
  • Workaround: None - users must provide correctly formatted input, but error doesn't explain the format

Affected Scenarios

  1. User provides --socks-proxy user@server (forgot port)
  2. User provides socks5://admin@proxy.local (forgot password and port)
  3. Any malformed proxy string with @ but missing : separator

Suggested Fix

Add validation before accessing split results:

if "@" in socks_proxy:
    # Validate format: username:password@host:port
    if ":" not in socks_proxy:
        die_failure(_(
            "Invalid SOCKS proxy format. "
            "Expected: username:password@host:port or socks5://username:password@host:port"
        ))
    
    parts = socks_proxy.split(":")
    if len(parts) < 2:
        die_failure(_(
            "Invalid SOCKS proxy format. Missing credentials separator. "
            "Expected: username:password@host:port"
        ))
    
    socks_username = parts[0]
    socks_password = parts[1].split("@")[0]
    
    # ... rest of the code

Or use a more robust approach with maxsplit:

if "@" in socks_proxy:
    # Split credentials from host:port
    if ":" not in socks_proxy.split("@")[0]:
        die_failure(_("Invalid SOCKS proxy credentials format. Expected: username:password"))
    
    creds, _ = socks_proxy.split("@", 1)
    parts = creds.split(":", 1)
    
    if len(parts) != 2:
        die_failure(_("SOCKS proxy credentials must be in format: username:password"))
    
    socks_username = parts[0]
    socks_password = parts[1]

Additional Notes

This is similar to the recently fixed IndexError in arg_parser.py (#1199) where split() was used without validating the result length before index access.

Environment

  • OS: Windows 11
  • Python: 3.13.7 (project supports 3.9-3.12)
  • Nettacker Version: 0.4.0 (commit: 0cd1d0d)

Checklist

  • Bug is reproducible with minimal test case
  • Root cause identified (missing validation before index access)
  • Suggested fix provided
  • Impact assessment included

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions