HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Safely open a list of links in Firefox

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
openlinkssafelylistfirefox

Problem

I receive a list of links via http and I want to open them all in a new Firefox (or default browser) window as tabs; that is my script must not touch existing windows.

This is the best solution I could come up with:

from subprocess import call

links = GetListViaHTTP()

if len(links) == 1:
    call(['firefox', '-new-window'] + links)
elif len(links) > 1:
    call(['firefox'] + links)
else:
    print('Nothing to do.')


This worked like a charm when I tested it, but putting something I received via http into subprocess.call does not look save to me at all. So the question is:

How can I improve this code to avoid being vulnerable to MITM attacks?

If the list was not tampered with by an attacker, all links it contains will point to Stack Overflow answers, so maybe somehow validating the links with urllib.parse is good enough?

Solution

Rather than implementing this yourself, Python by default has webbrowser. This allows you to open one link in a; new tab, or new window. And so, to open all links in the list with the default web-browser you can:

import webbrowser

for link in links:
    webbrowser.open_new_tab(link)


Since you say you don't trust the source of these urls, you can make sure they are actually URLs, and check there is no shell injection going on. This question says how you could do that.

And so I personally would use:

import webbrowser

import rfc3987

def open_links(links):
    links = (
        link
        for link in links
        if rfc3987.match(link, rule='IRI') is not None
    )
    # Get default webbrowser, change if you want to force a specific browser
    browser = webbrowser.get()
    try:
        browser.open_new(next(links))
    except StopIteration:
        pass
    else:
        for link in links:
            browser.open_new_tab(link)

Code Snippets

import webbrowser

for link in links:
    webbrowser.open_new_tab(link)
import webbrowser

import rfc3987

def open_links(links):
    links = (
        link
        for link in links
        if rfc3987.match(link, rule='IRI') is not None
    )
    # Get default webbrowser, change if you want to force a specific browser
    browser = webbrowser.get()
    try:
        browser.open_new(next(links))
    except StopIteration:
        pass
    else:
        for link in links:
            browser.open_new_tab(link)

Context

StackExchange Code Review Q#158753, answer score: 3

Revisions (0)

No revisions yet.