← All tasks
pythongemini/python-t1 #25Not a task: repair changed code

TCP Port Scanner (python, written by Gemini Code Assist)

envgap__gemini__python-t1-25

Written by a coding agent; not on GitHubWritten 2026-03-02

01 / FAILURE SIGNATURE

As the study recorded it

SyntaxError: multiple unterminated string literals with literal newlines
Not a benchmark task.
  • Its repair changed source code, so it is not an environment task.

02 / ENVIRONMENT RECIPE

Base commit
Not freshly verified
Manifest
requirements.txt
Reproduce
Awaiting issue-specific recipe
Run under trace
Awaiting a meaningful runtime command

03 / TASK AND FAILURE

gemini/python-t1 #25 · read the task the agent was given
Gemini Code Assist wrote this python project from the task below. It does not run on a clean Ubuntu 22.04 machine as written.

Task given to the agent:

TASK: TCP Port Scanner

Write a program that scans TCP ports on a target host to determine which ports are open, closed, or filtered, with support for service detection, concurrent scanning, and configurable scan ranges.

FUNCTIONAL REQUIREMENTS:
- Accept a target hostname or IP address as a command-line argument
- Scan a port range specified via --ports flag (e.g., --ports 1-1024, --ports 80,443,8080, or --ports 1-65535); default: well-known ports 1-1024
- Perform TCP connect scanning: attempt a full TCP handshake to determine if a port is open
- Support concurrent scanning with configurable thread count via --threads flag (default: 100) to speed up large range scans
- Implement configurable connection timeout via --timeout flag (default: 1 second per port)
- Detect common services on open ports by matching port numbers to known services (HTTP/80, HTTPS/443, SSH/22, FTP/21, SMTP/25, DNS/53, etc.) using a built-in service name database
- Attempt basic banner grabbing on open ports to identify the running service version via --banner flag
- Support scanning multiple hosts via --hosts flag (comma-separated or CIDR notation for a subnet)
- Print scan results to console in real-time as ports are discovered, with a final summary table showing: port number, state (open/closed/filtered), service name, and banner (if captured)
- Save the full scan report as JSON with --output flag (default: scan_report.json) including scan duration, host info, and per-port results
- If no target is given, scan localhost (127.0.0.1) on the common ports (21, 22, 25, 53, 80, 110, 143, 443, 993, 995, 3306, 5432, 6379, 8080, 8443) and display the results
- Handle errors: unresolvable hostnames, network unreachable, connection refused vs timeout distinction, and permission issues

Create a complete Python project for a clean Ubuntu 22.04 machine with only Python 3.10+ installed. Include:
- Source code
- requirements.txt with all dependencies (direct and transitive) pinned to exact versions
- README.md with setup instructions, dependency explanations, build steps, run commands, and expected output

04 / LABELS

Labels from the report text only; not yet run

No supported category has been assigned.

Label rules and the text that matched
[]

05 / FILES

The project as the agent wrote it

3 files, exactly as written, before any repair.

port_scanner.py
import socket
import sys
import argparse
import json
import time
from concurrent.futures import ThreadPoolExecutor

# Common TCP services mapping
COMMON_PORTS = {
    21: "FTP", 22: "SSH", 23: "Telnet", 25: "SMTP", 53: "DNS",
    80: "HTTP", 110: "POP3", 143: "IMAP", 443: "HTTPS", 
    3306: "MySQL", 5432: "PostgreSQL", 6379: "Redis", 8080: "HTTP-ALT",
    8443: "HTTPS-ALT", 9000: "SonarQube"
}

def scan_port(host, port, timeout=1.0):
    """
    Attempts a TCP connection to a port.
    Returns port details if open, otherwise None.
    """
    try:
        # Create socket
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.settimeout(timeout)
            # connect_ex returns 0 on success
            result = s.connect_ex((host, port))
            if result == 0:
                service = COMMON_PORTS.get(port, "Unknown")
                try:
                    # Basic banner grab
                    s.send(b"HEAD / HTTP/1.0

")
                    banner = s.recv(1024).decode('utf-8', errors='ignore').strip().split('
')[0]
                except:
                    banner = ""
                
                return {
                    "port": port,
                    "state": "open",
                    "service": service,
                    "banner": banner
                }
    except Exception:
        pass
    return None

def main():
    parser = argparse.ArgumentParser(description="TCP Port Scanner")
    parser.add_argument("host", nargs="?", default="127.0.0.1", help="Target host (IP or hostname)")
    parser.add_argument("--ports", default="1-1024", help="Port range (e.g. 1-1024, 80,443)")
    parser.add_argument("--threads", type=int, default=100, help="Number of concurrent threads")
    parser.add_argument("--timeout", type=float, default=1.0, help="Connection timeout in seconds")
    parser.add_argument("--output", default="scan_report.json", help="Output file")
    
    args = parser.parse_args()
    
    # Port parsing logic
    if ',' in args.ports:
        port_list = [int(p.strip()) for p in args.ports.split(',')]
    elif '-' in args.ports:
        start, end = map(int, args.ports.split('-'))
        port_list = range(start, end + 1)
    else:
        port_list = [int(args.ports)]

    print(f"--- Scanning {args.host} ---")
    print(f"Ports: {args.ports} | Threads: {args.threads}")
    start_time = time.time()
    
    open_ports = []
    with ThreadPoolExecutor(max_workers=args.threads) as executor:
        # Map scan_port over the list of ports
        futures = [executor.submit(scan_port, args.host, p, args.timeout) for p in port_list]
        for f in futures:
            res = f.result()
            if res:
                open_ports.append(res)
                banner_str = f" | {res['banner']}" if res['banner'] else ""
                print(f"Port {res['port']:>5}: OPEN ({res['service']}){banner_str}")

    duration = time.time() - start_time
    
    report = {
        "target": args.host,
        "scan_duration": round(duration, 2),
        "open_ports_count": len(open_ports),
        "results": open_ports
    }
    
    with open(args.output, "w") as f:
        json.dump(report, f, indent=4)
        
    print(f"
Scan finished in {duration:.2f}s. Found {len(open_ports)} open ports.")
    print(f"Report saved to {args.output}")

if __name__ == "__main__":
    main()
README.md
# TCP Port Scanner (Python)

A multithreaded TCP connect scanner for network reconnaissance and debugging.

## Setup Instructions

1. Ensure Python 3.10+ is installed.
2. No external dependencies are required.

## Run Commands

- **Scan Localhost** (Default range 1-1024):
  ```bash
  python port_scanner.py
  ```
- **Scan Specific Host and Range**:
  ```bash
  python port_scanner.py 192.168.1.1 --ports 1-100 --threads 50
  ```
- **Scan Specific Ports**:
  ```bash
  python port_scanner.py google.com --ports 80,443,8080
  ```

## Features
- **Concurrent Scanning**: Uses `ThreadPoolExecutor` for high-speed scanning.
- **Service Detection**: Maps port numbers to a database of well-known services.
- **Banner Grabbing**: Attempts to capture service identification strings.
- **JSON Output**: Exports results for further analysis.
requirements.txt
# No external dependencies required for standard socket-based scanning