Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Escaped Dollar sign ($) in string environment variables not getting cleaned after import #271

Closed
mmoallemi99 opened this issue Aug 9, 2020 · 15 comments
Assignees
Labels
bug Something isn't working

Comments

@mmoallemi99
Copy link

Hi People,

I've encountered an issue while setting the EMAIL_HOST_PASSWORD environment variable.

If you have Dollar sign $ in the beginning of your env variable string django-environ treats it as another environment variable (nested variable):
.env file:

EMAIL_HOST_PASSWORD='$my_password_including_$_sign_in_the_beginning'

settings.py

EMAIL_HOST_PASSWORD = env.str('EMAIL_HOST_PASSWORD')

This configuration raises:

django.core.exceptions.ImproperlyConfigured: Set the my_password_including_$_sign_in_the_beginning environment variable

which as you can see omitted the first $ sign.

Now if we try to escape the $ character with a backslash and change our .env file to this:

EMAIL_HOST_PASSWORD='\$my_password_including_$_sign_in_the_beginning'

django-environ escapes the backslash instead of the dollar sign $ and we end up with something like this:

>>> from django.conf import settings
>>> settings.EMAIL_HOST_PASSWORD
'\\$my_password_including_$_sign_in_the_beginning'

Which breaks our configurations and settings.

This is my proposal which if is agreed on I'll make a pull request:

# Current string reader function
def str(self, var, default=NOTSET, multiline=False):
    """
    :rtype: str
    """
    value = self.get_value(var, default=default)
    if multiline:
        return value.replace('\\n', '\n')
    return value


# My proposal for string function, which we can use escape=True while passing env variables that have such characters
def str(self, var, default=NOTSET, multiline=False, escape=False):
    """
    :rtype: str
    """
    value = self.get_value(var, default=default)
    if multiline:
        return value.replace('\\n', '\n')
    if escape:
        return value.replace('\$', '$')
    return value
@rkelly90
Copy link

rkelly90 commented Aug 14, 2020

Interestingly enough, I encountered an issue related to this yesterday. My organization uses VSCode, and the variable substitution syntax it uses requires the more explicit variable definition of:

${var}

This means that, functionally, I am unable to use variable substitution, since it won't work if ran from the VSCode debugger AND if ran in the shell. If django-environ could support both styles, that would be amazing. And from looking at the code, probably not a difficult change.

*Edit: Whoops. Also meant to add that this would solve mmoallemi99's issue.

@lociii
Copy link

lociii commented May 21, 2021

Would really love to see this fixed as it's also preventing our organization from moving the SECRET_KEY to env.

@gp-saurabh
Copy link

We are having the same issue, Is it fixed yet?

@eriklesbr
Copy link

Correction done?

@sergeyklay sergeyklay added the bug Something isn't working label Sep 6, 2021
@ratondeau
Copy link

Same here switched to python-dotenv in the meantime, but this is not a good replacement as you have to do type conversion by yourself e.g. for int and list values.

@eriklesbr
Copy link

@mmoallemi99 I'm currently using your suggestion, but many still have this problem, any forecast when they will analyze and fix this bug?

@sergeyklay sergeyklay self-assigned this Sep 21, 2021
@sergeyklay
Copy link
Collaborator

I'l sort out with this ASAP.

@fdemmer
Copy link
Contributor

fdemmer commented Oct 20, 2021

I'l sort out with this ASAP.

Looking forward to a release, that supports completely disabling proxy/interpolation (or at least using only ${VAR} format). I personally don't need it at all and it generally adds complexity that leads to bugs as documented by the numerous issues reporting problems.

Thank you for your work on all those recent updates @sergeyklay !

@sergeyklay
Copy link
Collaborator

I apologize @fdemmer for completely overlooking this issue. Thank you for the reminder.

Version v0.8.0 with an ability to escape dollar sign ($) was released 3 days ago:

For details and usage please refer the documentation: https://django-environ.readthedocs.io/en/latest/tips.html#escape-proxy

Today we released a hotfix version v0.8.1:

Thank you all for your patience, and I am sorry about the delay.

@cvipul
Copy link

cvipul commented Feb 2, 2022

I have upgraded the django-environ library and also using the syntax provided in documentation here - https://django-environ.readthedocs.io/en/latest/tips.html#escape-proxy

django-environ==0.8.1
python==3.8

.env file :
ESCAPED_VAR="\$asasd"

.py file :
env = environ.Env()
env.escape_proxy=True
env.str('ESCAPED_VAR')

But facing the same error:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
~\lib\site-packages\environ\environ.py in get_value(self, var, cast, default, parse_default)
    366         try:
--> 367             value = self.ENVIRON[var]
    368         except KeyError:

~\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0\lib\os.py in __getitem__(self, key)
    674             # raise KeyError with the original key value
--> 675             raise KeyError(key) from None
    676         return self.decodevalue(value)

KeyError: 'asasd'

During handling of the above exception, another exception occurred:

ImproperlyConfigured                      Traceback (most recent call last)
<ipython-input-4-d690e5bb1c8d> in <module>
----> 1 env.str('ESCAPED_VAR')

~\lib\site-packages\environ\environ.py in str(self, var, default, multiline)
    189         :rtype: str
    190         """
--> 191         value = self.get_value(var, cast=str, default=default)
    192         if multiline:
    193             return re.sub(r'(\\r)?\\n', r'\n', value)
~\lib\site-packages\environ\environ.py in get_value(self, var, cast, default, parse_default)
    378         if hasattr(value, 'startswith') and value.startswith(prefix):
    379             value = value.lstrip(prefix)
--> 380             value = self.get_value(value, cast=cast, default=default)
    381
    382         if self.escape_proxy and hasattr(value, 'replace'):

~\lib\site-packages\environ\environ.py in get_value(self, var, cast, default, parse_default)
    369             if default is self.NOTSET:
    370                 error_msg = "Set the {} environment variable".format(var)
--> 371                 raise ImproperlyConfigured(error_msg)
    372
    373             value = default

Looks like the error comes even before we can reach the "escape_proxy" setting.
What am I doing wrong here?

@cvipul
Copy link

cvipul commented Feb 2, 2022

Apparently I cannot use quotes ("") to encase the ESCAPED_VAR in env file.
Once I remove the quotes from env file, it works perfectly.

@sergeyklay - Should this also be mentioned in the documentation?

@salaxieb
Copy link

salaxieb commented Jul 22, 2022

Hi everyone
following helped me: with my pas$word
using double $

export PASSWORD='pas$$word'

@mode9
Copy link

mode9 commented Dec 26, 2022

version=0.9.0

Still same issue.
I solved this issue as following,

# .env
SECRET_KEY=supersecret

# settings.py
SECRET_KEY = env('SECRET_KEY', parse_default=lambda x: f'${x}') 

@jackfrancisjr
Copy link

single quotes worked for me
conda env config vars set MY_PASSWORD='MyPa$$word$333'

@sachalau
Copy link

sachalau commented Aug 30, 2024

This has been confusing me for some while as I couldn't understand why my SECRET_KEY couldn't be parsed.

Just to let you know regarding the documentation, it's a bit misleading, as the issue will arise whenever there's a $ in the value, it does not need to be leading.

Edit because I wrote something incorrect.

For instance, setting as value lol$lowlzer will prompt django-environ to try and set the environment variable lowlzer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests