Skip to content

Harden proxy ping to avoid shell injection - #1110

Open
sainimal1ba-hue wants to merge 4 commits into
sugarlabs:masterfrom
sainimal1ba-hue:illegal-commands-injection
Open

Harden proxy ping to avoid shell injection#1110
sainimal1ba-hue wants to merge 4 commits into
sugarlabs:masterfrom
sainimal1ba-hue:illegal-commands-injection

Conversation

@sainimal1ba-hue

Copy link
Copy Markdown

The proxy configuration flow concatenates user-provided hostnames directly into an os.system call. This creates a local shell injection vector.

This replaces os.system with subprocess.run and an argument list to bypass the shell entirely, eliminating the injection risk. It also adds '--' before the hostname argument to prevent flag injection in case a malformed hostname starts with a hyphen.

Manual Test Plan:
Verified locally by entering '127.0.0.1; touch ~/ping_test' in the proxy settings. On the old code, the file is created. With this patch, the ping safely fails to resolve the malformed host, bypassing the shell, and no file is created.

Took inspiration from:- sugarlabs/sugar-ai#136

Refactor ping command to use subprocess for better error handling and readability.
Comment thread extensions/cpsection/network/view.py Outdated
['ping', '-c', '1', '-W', '1', '--', hostname],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
).returncode

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returncode?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returncode was used to get the exitcode to follow up with the next conditions. is there anything i have to fix? or you want me to intialize it like this?

var = subprocess.run(['ping', '-c', '1', '-W', '1', '--', hostname],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
response = var.returncode

if it returns 0 that means it finished sucessfully running it, if its 1 or any value other than 0 then it means it didnt execute properly. --> (ping)

or i can try doing it without returncode in the first place like this:-
( this one completely removes the if condition and response since try and except directly handles it )
if hostname:
non_blank_host_name_counter += 1
try:
subprocess.run(
['ping', '-c', '1', '-W', '1', '--', hostname],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=True,
)
except (OSError, subprocess.CalledProcessError):
self._proxy_inline_alerts[schema].show()
response_to_return = False

tried my best to give indentation and spacing for better understanding for you.
let me know which one you prefer.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all the spacing 💀

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

honestly i prefer this one:
if hostname:
non_blank_host_name_counter += 1
try:
subprocess.run(
['ping', '-c', '1', '-W', '1', '--', hostname],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=True,
)
except (OSError, subprocess.CalledProcessError):
self._proxy_inline_alerts[schema].show()
response_to_return = False

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the file to use check=True instead of return code for error handling.

@chimosky

Copy link
Copy Markdown
Member

You have a commit message "flask8 fixes", I'm assuming you meant flake8 so correct the commit message.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

yea i will correct the commit message as soon as possible and let you know.

@quozl

quozl commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

I don't mind if this is fixed, but be realistic - the Terminal activity is a much easier way to get a shell, and we can recommend that instead of this unexpected feature. 😀

@sainimal1ba-hue

Copy link
Copy Markdown
Author

thats true @quozl 🤣

@sainimal1ba-hue
sainimal1ba-hue requested a review from chimosky July 22, 2026 14:24
@sainimal1ba-hue

Copy link
Copy Markdown
Author

I don't mind if this is fixed, but be realistic - the Terminal activity is a much easier way to get a shell, and we can recommend that instead of this unexpected feature. 😀

but the "users" might get mislead by any youtube channel on running any command which can cause damage.

@quozl

quozl commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

yes, but we can't ban youtube. another way is to provide a web server that offers a zip file with content type application/vnd.olpc-sugar which browse will unpack and install. getting someone to click on a link is much easier than getting them to waste time on youtube.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

yes, but we can't ban youtube. another way is to provide a web server that offers a zip file with content type application/vnd.olpc-sugar which browse will unpack and install. getting someone to click on a link is much easier than getting them to waste time on youtube.

ur right there are easier ways like the one u mentioned. my intension for this PR to get rid of this avoidable shell injection by using subprocess.run. i will update the PR based on the comments ( usiing check=True instead of relying on returncode) and commit new changes.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

a doubt like we can add user confirmations before installing anything right? (the malicious installation u told me abt) i actually went and checked the code, and rn theres literally no confirmation for a fresh install. journalactivity.py listens for new journal entries and just calls handle_bundle_installation() straight away, which calls registry.install() with no prompt at all. only time it asks anything is if a downgrade is needed (theres already a ConfirmationAlert used for that in misc.py). so my idea is to reuse that same alert pattern for first time installs too, not just downgrades, so the user atleast sees a "do u want to install this activity?" popup before it happens. would like to work on this as a follow up PR if thats cool, lmk what u guys think.

@quozl

quozl commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

other operating systems have resolved this with code signing.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

other operating systems have resolved this with code signing.

that makes sense code signing would def be the stronger fix long term compared to just a popup. honestly im down to look into that too if yall think its worth it just lmk the direction u want ( confirmation dialog as a smaller step first or straight up trying to figure out signing ) and ill start looking into it

@sainimal1ba-hue

Copy link
Copy Markdown
Author

hello @chimosky whnever u get a chance can u take a look again? i have updated the code using check = True rather than relying on .returncode lmk if anything else needs changing.

@quozl

quozl commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

it would make the activity library smaller again. it was made much smaller when we ported to python 3. if we went for signing of activities, it would have to start from zero again. it's not the digital signatures that are a problem, it's the maintenance and release of activities that is not happening much. without that happening it's hard to see how signing would help. also, it's not the sort of problem that would be solved by ci/cd, tempting though that may seem. we lack maintainers, and the security assurance that they bring to development.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

it would make the activity library smaller again. it was made much smaller when we ported to python 3. if we went for signing of activities, it would have to start from zero again. it's not the digital signatures that are a problem, it's the maintenance and release of activities that is not happening much. without that happening it's hard to see how signing would help. also, it's not the sort of problem that would be solved by ci/cd, tempting though that may seem. we lack maintainers, and the security assurance that they bring to development.

then i guess the confirmation dialog is probably the more realistic thing to actually ship now?

@quozl

quozl commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

it would be a step in the right direction, as far as a security policy is concerned. i'm unfamiliar with your work, so don't know if you're aware of the extent of the challenge to just get one line of code in the browse activity to change, so here's a brief summary;

also, while i've assumed that a confirmation dialog in browse will handle the situation, you may have been thinking of a dialog in the sugar shell, jarabe. if so, the other test cases to consider are filesystem access by the embedded journal activity, and file sharing via collaboration stack.

good luck.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

hey quozl u mentioned (embedded journal access + collab stack), and also found another gap with Activities being watched live while sugar's running (the terminal case). think i found exactly where each one needs to change to close them properly. does this scope seem right before i start building it out as a real follow up PR?

@quozl

quozl commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

sorry, i don't understand what you mean by the other gap.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

@quozl to clarify what i meant by the "other gap" i was talking about a potential security bypass in the terminal activity. right now, a user can just use wget to download an untrusted file directly into the sugar environment and it happens completely silently without any UI confirmation or warning. (i attached a screenshot showing a .xo file being downloaded this way) also, on a separate note regarding GTK4 since i know there is an ongoing effort to port the environment who is the best person for me to connect with i just want to make sure my current work doesn't cause major merge conflicts or create extra headaches for whoever is handling the migration later on.

@sainimal1ba-hue

Copy link
Copy Markdown
Author
image

@quozl

quozl commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

oh, okay, that kind of change is best implemented in bash or the operating system, not in terminal. or remove the terminal activity.

check the sugar-toolkit-gtk4 repository for activity on gtk4. jukebox has the most recent pull requests i've seen.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

@quozl a quick doubt should the popup only occur when the user have downloaded anything from the browser or like only.xo files?

@quozl

quozl commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

don't know, sorry. it is a GET of the content-type application/vnd.olpc-sugar that is the critical link in the social engineering vulnerability.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

@quozl while actually editing and testing right i found this on the shell where i was not able to access the terminal. i went and checked on terminal-activity as well but i was not able to find where it was to raise a PR over there. so the thing is that it uses readfp at this line which breaks the code since fedora uses python 3.14 at the moment. (like the newer fedora linux)

this exact place:-
image

and this is the error i got like it showed me also the logs:-
image
image

after using read_file instead of readfp it actually worked.
(here is the proof that the terminal shows up after i use read_file() instead of readfp())
image

@sainimal1ba-hue

Copy link
Copy Markdown
Author

is this wantedly done? or u can actually do like this right?
try:
    conf.read_file(f)
except AttributeError:
    conf.readfp(f)

@sainimal1ba-hue

Copy link
Copy Markdown
Author

the version also i checked and it was 47

@chimosky

Copy link
Copy Markdown
Member

The terminal-activity lives in our GH org, where did you check that you couldn't raise a PR?

@sainimal1ba-hue

Copy link
Copy Markdown
Author

The terminal-activity lives in our GH org, where did you check that you couldn't raise a PR?

i went to terminal.py over there and still i cant find that exact line thats what i meant by checked. like the same function which shows theres a error:- def _configure_vt doesn't exists inside terminal.py.

@chimosky

Copy link
Copy Markdown
Member

The terminal-activity lives in our GH org, where did you check that you couldn't raise a PR?

i went to terminal.py over there and still i cant find that exact line thats what i meant by checked. like the same function which shows theres a error:- def _configure_vt doesn't exists inside terminal.py.

The change you're referring to has already been made in 451fd6d, but a release hasn't been made yet.

@quozl

quozl commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

apart from please don't use screenshots when you can copy and paste text, and that i agree with @chimosky, i've nothing else to add. thanks for sharing.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

The terminal-activity lives in our GH org, where did you check that you couldn't raise a PR?

i went to terminal.py over there and still i cant find that exact line thats what i meant by checked. like the same function which shows theres a error:- def _configure_vt doesn't exists inside terminal.py.

The change you're referring to has already been made in 451fd6d, but a release hasn't been made yet.

Oh ok Alright I understood. Thanks.

@sainimal1ba-hue

Copy link
Copy Markdown
Author

apart from please don't use screenshots when you can copy and paste text, and that i agree with @chimosky, i've nothing else to add. thanks for sharing.

Ok I will copy and paste texts from now.

@sainimal1ba-hue

sainimal1ba-hue commented Jul 30, 2026

Copy link
Copy Markdown
Author

hey @quozl, wanted to check in with a few open questions before i clean this up for review.

  • right now when someone declines installing something dropped straight into ~/Activities, i just delete the folder is that too aggressive?
  • i added a new setting (t rust-local-activities) so activity devs can skip the confirmation when testing their own stuff locally.
  • also wanted to confirm by "filesystem access by the embedded journal activity". i didnt really get it.

@quozl

quozl commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

I don't think dropping a folder into ~/Activities should be refused, and I do think deleting data is an inappropriate response.

Journal activity can show an external storage device, and it is one way a teacher is instructed to load specific activities without a network. Where signing is to be adopted, that path must also be considered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants